g_function_info_invoke() may truncate return values



Hello,

I've run into an issue with gobject-introspection where return values from functions can in some circumstances be truncated. An example of such a function is gdk_pixbuf_read_pixels() [1] which has the signature:

    const guint8 *
    gdk_pixbuf_read_pixels (const GdkPixbuf *pixbuf);

Calling gdk_pixbuf_read_pixels() directly and comparing the result when the function is called via g_function_info_invoke() is illustrative of the truncation problem:

    Calling gdk_pixbuf_read_pixels() directly...
    retval: 0x7fc14fd4a010    // healthy return value
    Calling gdk_pixbuf_read_pixels() via g_function_info_invoke()...
    ret_arg->v_pointer: 0x10  // truncated return value

I think the problem arises in gicallableinfo.c when we translate back and forth between the GI <-> FFI data types. There are two places in which this translation fails:

1. translating return-arg GITypeInfo -> ffi_type values

In g_callable_info_invoke() we call:

    rinfo = g_callable_info_get_return_type ((GICallableInfo *)info);

but this does not consider whether the return value is a pointer; a pointer-to-integral type is mapped to a integral type. e.g. a guint8* is mapped to a ffi_type_uint8.

2. translating ffi_return_value -> GIArgument return value

In gi_type_info_extract_ffi_return_value() we don't consider whether the return value is a pointer. In the case where the size represented by the type-info tag is less than the size of a pointer then we'll truncate the return value. For example, in the above case of gdk_pixbuf_read_pixels() we execute:

    switch (g_type_info_get_tag (return_info)) {
    ...
    case GI_TYPE_TAG_UINT8:
        arg->v_uint8 = (guint8) ffi_value->v_ulong;
        break;

ffi_value->v_pointer should hold the value of a (const guint8 *) but we instead look at ffi_value->v_ulong, and then cast it to a guint8.


Thanks

Keri

[1] https://developer.gnome.org/gdk-pixbuf/2.36/gdk-pixbuf-The-GdkPixbuf-Structure.html#gdk-pixbuf-read-pixels

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]