Skip to content

BiDi.SetLine binds ubidi_setLine's line object as an out parameter #246

Description

@imnasnainaec

Describe the bug

BiDi.SetLine passes ICU the wrong kind of argument for the line object.

ICU's C signature is:

void ubidi_setLine(const UBiDi *pParaBiDi, int32_t start, int32_t limit,
                   UBiDi *pLineBiDi, UErrorCode *pErrorCode);

pLineBiDi is an input. The caller opens it first with ubidi_open() or ubidi_openSized(). ICU then fills in that object.

icu-dotnet declares it as out IntPtr lineBiDi instead:

So ICU gets the address of an 8-byte managed slot and treats it as a UBiDi struct. It writes a whole struct there, which corrupts memory. The returned BiDi then wraps whatever pointer-sized value ended up in the slot. When that object is disposed or finalized, ubidi_close runs on that value.

BiDi.SetLine has no test, which is probably why this hasn't come up.

Expected behavior

SetLine returns a working line BiDi, and closing it doesn't touch memory that ICU doesn't own.

Possible fix

  1. Change the parameter to a plain input handle.
  2. In SetLine, open the line object first (ubidi_open()), then pass it to ubidi_setLine.
  3. Keep the paragraph object alive while the line object is in use. ICU's line object points into the paragraph's data.
  4. Add tests for SetLine.

ICU also says the paragraph object must not be modified while a line object uses it. Calling SetPara again on the paragraph would leave the line reading stale data. The fix should guard against that, e.g. by making the line throw ObjectDisposedException afterwards.

This isn't a breaking change. The public SetLine(int start, int limit) signature stays the same, and the binding is internal. Today's SetLine can't work, so no caller relies on its current behavior.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions