Re: g_function_info_invoke() may truncate return values



Thanks for the detailed analysis. I agree, it seems quite plausible that that's happening. Would you mind filing a bug report (https://gitlab.gnome.org/GNOME/gobject-introspection/issues)? Additionally if you are willing to look into fixing it, add me on the merge request and I will be happy to review the fix.

Regards,
Philip C

On Wed, Dec 19, 2018 at 2:14 PM Keri Harris via gir-devel-list <gir-devel-list gnome org> wrote:
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
_______________________________________________
gir-devel-list mailing list
gir-devel-list gnome org
https://mail.gnome.org/mailman/listinfo/gir-devel-list


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