Skip to content

Segmentation fault when calling FT_Open_Face with custom FT_StreamRec #31

@mcendu

Description

@mcendu

The following excerpt causes a segmentation fault inside FT_Open_Face:

    /* ... */
    Stream? s = /* ... */;
    var handle = GCHandle.Alloc(s);
    FT_FaceRec_* face = null;
    var ftStream = (FT_StreamRec_*)NativeMemory.AllocZeroed((nuint)sizeof(FT_StreamRec_));
  
    ftStream->size = 0x7FFFFFFF;
    ftStream->descriptor.pointer = (void*)(nint)handle;
    ftStream->read = (delegate* unmanaged<FT_StreamRec_*, nuint, byte*, nuint, nuint>)&ReadFromFreeType;
    ftStream->close = (delegate* unmanaged<FT_StreamRec_*, void>)&CloseFromFreeType;
  
    var openArgs = new FT_Open_Args_
    {
        flags = 0x2, // FT_OPEN_STREAM
        stream = ftStream,
        num_params = 0,
    };
  
    nint compoundFaceIndex = (ushort)FaceIndex | (NamedInstance << 16);
  
    FT_Error error = FT_Open_Face(freeType, &openArgs, compoundFaceIndex, &face);
    /* program crashes here */

GDB shows that FreeType does not see ftStream in the intended way:

Thread 43 ".NET TP Worker" hit Breakpoint 1, FT_Open_Face
(library=0x7fbe28005190, args=0x7fbe327fb810, face_index=0,
aface=0x7fbe327fb860) at /usr/src/debug/freetype-2.13.3-2.fc42.x86_64/src/base/ftobjs.c:2520
2520      {
(gdb) p *args->stream
$12 = {base = 0x0, size = 2147483647, pos = 0, descriptor = {value = 0,
  pointer = 0x0}, pathname = {value = 140737345688256,
  pointer = 0x7ffff77f12c0}, read = 0x0, close = 0x0,
  memory = 0x7fff7bb7a100,  cursor = 0x7fff7bb7a118 "\377%\372?",
  limit = 0x0}

On further inspection, the definition of FT_StreamDesc_ does not seem to be correct at the C# end (sizes and offsets assumes x86-64 Linux ABI):

    [StructLayout(LayoutKind.Sequential)]
    public unsafe struct FT_StreamDesc_ /* size = 16! */
    {
        public IntPtr value; /* offset = 0 */
        public void* pointer; /* offset = 8! */
    }

FreeType expects FT_StreamDesc_ to be a union instead:

typedef union  FT_StreamDesc_ /* size = 8 */
  {
    long   value; /* offset = 0 */
    void*  pointer; /* offset = 0 */

  } FT_StreamDesc;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions