After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 664848 - Passing array of structs fails
Passing array of structs fails
Status: RESOLVED FIXED
Product: pygobject
Classification: Bindings
Component: introspection
Git master
Other Linux
: Normal normal
: ---
Assigned To: Nobody's working on this now (help wanted and appreciated)
Python bindings maintainers
Depends on:
Blocks: 682604
 
 
Reported: 2011-11-25 21:36 UTC by Sebastian Pölsterl
Modified: 2013-07-19 03:05 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test case (2.89 KB, text/x-python)
2012-05-06 15:04 UTC, Sebastian Pölsterl
Details

Description Sebastian Pölsterl 2011-11-25 21:36:04 UTC
I discovered the following problem while dealing with drag and drop in GTK+. In this context there are many methods similar to gtk_target_list_new that expect a array of structs (here: GtkTargetEntry) and the size of the array as arguments.

gtk_target_list_new (const GtkTargetEntry *targets, guint ntargets);

However, the following code will pass the wrong address of the array to gtk_target_list_new.

entries = [Gtk.TargetEntry.new("STRING", 0, 0),
           Gtk.TargetEntry.new("text/plain", 0, 0)]

tlist = Gtk.TargetList.new(entries)

After debugging the problem I discovered that the problem is _pygi_marshal_from_py_array where the C array is created. There, array_->data will become the array that once is passed to gtk_target_list_new. In a couple of cases the following code is executed:

g_array_insert_val (array_, i, item);

As array_ should contain GtkTargetEntry's I think inserting item (of type GIArgument) is wrong and will store the wrong reference in the array. Instead, using the following code worked in this particular case:

g_array_insert_val (array_, i, *item.v_pointer);
Comment 1 johnp 2011-11-28 17:28:02 UTC
I thought we memcpyed structs.  Is TargetEntry a boxed struct?  We can't fix that without the flat array annotation as it will break other bindings.
Comment 2 Sebastian Pölsterl 2011-11-28 18:29:22 UTC
Yes, TargetEntry is a boxed struct. It looks to that only non-boxed structs are memcpyed. What do you mean by "flat array annotation"? Can it be fixed by adding an additional annotation to the C source?
Comment 3 johnp 2011-11-28 18:45:55 UTC
We have flat C arrays and C pointer arrays.  Flat arrays the struct is copied in place so each element is sizeof(element) where as the pointer arrays only the pointer is copied in.  Heuristics go like this:

Objects and Boxed types are pointers.  Structs and GValues are flat.  Copying a boxed type in a flat array is dangerous because you will double free if the boxed's free function is called and then the array is freed (or the other way around).  In any case there is currently no way to specify this in the gir which is why we have the heuristics.  There is a bug open about it somewhere but I don't think anyone is working on it.
Comment 4 Sebastian Pölsterl 2011-12-02 17:19:57 UTC
I tried to find the bug but of no avail. Was it filed against pygobject or gobject-introspection?
Comment 5 johnp 2011-12-02 18:39:35 UTC
I think this is it - https://bugzilla.gnome.org/show_bug.cgi?id=561099 though I thought I had commented on it.
Comment 6 Martin Pitt 2012-04-20 07:40:41 UTC
I ran the commands in the description, but there is no crash or anything. Do you have a more complete reproducer?

Or did that actually crash at the time you tried it?

I recently fixed the handling of GValue arrays (http://git.gnome.org/browse/pygobject/commit/?id=d7d28d71), but I suppose that was unrelated because the boxed structs are not GValues.

Thanks!
Comment 7 Sebastian Pölsterl 2012-04-20 09:43:10 UTC
IIRC, this did not result in a crash, but the drag-n-drop target was not set. I will test again with latest version and report back.
Comment 8 Tomeu Vizoso 2012-05-04 08:36:01 UTC
(In reply to comment #7)
> IIRC, this did not result in a crash, but the drag-n-drop target was not set. I
> will test again with latest version and report back.

Valgrind should complain in that case though.
Comment 9 Sebastian Pölsterl 2012-05-06 15:04:18 UTC
Created attachment 213551 [details]
Test case

The problem and the description above is still valid for latest master.

I don't see valgrind complaining, maybe because the pointer is not invalid but to the wrong object.

Breakpoint 1, gtk_target_list_new (targets=0xad09e0, ntargets=5)
    at gtkselection.c:227
(gdb) p *targets
$1 = {target = 0xacad20 "\300\277\254", flags = 0, info = 0}
(gdb) p ((GIArgument*)targets).v_pointer
$2 = (gpointer) 0xacad20
(gdb) p *(GtkTargetEntry*)((GIArgument*)targets).v_pointer 
$3 = {target = 0xacbfc0 "UTF8_STRING", flags = 0, info = 0}o
Comment 10 Simon Feltman 2013-07-19 03:05:05 UTC
Verified the example script works. Also debugged into gtk_target_list_new and verified the correct array of items is being passed. So it looks like this has already been fixed.