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 700338 - girepository: fix offset computation with callback fields
girepository: fix offset computation with callback fields
Status: RESOLVED OBSOLETE
Product: gobject-introspection
Classification: Platform
Component: libgirepository
unspecified
Other All
: Normal normal
: ---
Assigned To: gobject-introspection Maintainer(s)
gobject-introspection Maintainer(s)
: 706004 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2013-05-14 20:03 UTC by Giovanni Campagna
Modified: 2018-02-08 12:22 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
girepository: fix offset computation with callback fields (13.45 KB, patch)
2013-05-14 20:03 UTC, Giovanni Campagna
reviewed Details | Review
girepository: Use constant time calculation for sections after Object fields (22.96 KB, patch)
2014-02-28 01:18 UTC, Simon Feltman
committed Details | Review
g_struct_info_find_method: fix offset computation (1.14 KB, patch)
2016-10-23 17:42 UTC, Torsten Schoenfeld
none Details | Review

Description Giovanni Campagna 2013-05-14 20:03:51 UTC
Field blobs can be optionally followed by a inline callback blob.
While this is horrible (because now field offset computation is
linear time), we can't change it now to avoid breaking backward
compatibility, so change all locations using n * header->field_blob_size
to use the new field offset helper.
Comment 1 Giovanni Campagna 2013-05-14 20:03:54 UTC
Created attachment 244241 [details] [review]
girepository: fix offset computation with callback fields
Comment 2 Colin Walters 2013-05-15 20:05:58 UTC
Review of attachment 244241 [details] [review]:

Hmm.  Ugh =(  I wish we could go back and do something like synthesize types at the toplevel.  This is really an artifact of the fact that the typelib doesn't nest.

Anyways, this is another patch where it'd be *very* useful for me to know what program actually broke.  Was it that some library added an anonymous callback to a structure and all of a sudden things started crashing because we were looking at invalid field offsets?  If it's that kind of thing, what structure, what change?

Hmm.  Also it's not just that we're making field offset computation linear, we're also making *method* lookups linear in the number of fields since they come after fields.  Eww =/  Not your fault though.

So...just marking this as reviewed, let's keep talking about it.

::: girepository/girnode.c
@@ +817,3 @@
           size += _g_ir_node_get_full_size_internal (node, (GIrNode *)field->callback);
+        else
+          size += - sizeof (SimpleTypeBlob) +

The subtraction here looked really strange/wrong to me until I saw we're doing it elsewhere, in e.g. the FIELD case of _g_ir_node_build_typelib().  So...let's keep this as is I guess.
Comment 3 Giovanni Campagna 2013-05-15 20:13:16 UTC
This broke in my face when I was debugging bug 700347, which adds support for g_object_class_* in gjs.
It would call g_struct_info_find_method (not g_struct_info_get_method, used by g-ir-generate) on GObjectClass, which is a struct with plenty of callbacks.

I don't know if this would bite us should bug 700347 (or a pygobject equivalent) not land, but to me it looks like an incident waiting to happen, especially with structure types. It is less of a problem with GObject types, because usually you just have parent_instance and priv.
Comment 4 Daniel Drake 2013-08-15 21:39:13 UTC
*** Bug 706004 has been marked as a duplicate of this bug. ***
Comment 5 Daniel Drake 2013-08-15 21:43:05 UTC
I am working on making pygobject use lazy resolution of methods. This involves using g_struct_info_find_method() at some points.

I haven't finished this work yet, as I haven't got the testsuite passing yet. But I'm making progress. One of the issues that was in the way was a crash, didn't happen every time and could be influenced by meaningless print statements. Running under gdb found it right away though, the bug found here was causing a strcmp() of bad addresses.

Please do apply this patch...
Comment 6 Colin Walters 2013-08-19 23:59:32 UTC
Blah.  Okay, I shouldn't have sat on this one so long.  Now we're here at .90.  This patch from last I looked was probably correct, but two things make me nervous:

1) There's no test coverage of this inside g-i itself
2) There can't be test coverage inside the bindings yet since they'd crash

I can take a look at doing #1.
Comment 7 Simon Feltman 2014-02-27 22:55:30 UTC
So I just committed a very similar change in bug 725198 (I should have searched for similar bugs first). The commit did not however change the code for g_struct_info_find_method. Out of curiosity what was the problem with updating g_struct_info_find_method anyhow?

FWIW I like Giovanni's approach to sharing _g_base_info_get_field_offset better than what I did. I'd be happy to incorporate that as a refactoring pass if others agree.

In terms of linear time for the computation, we could grab one of a 16 bit reserved values on the blob and start writing out "n_field_callbacks" as the number of fields which are also callbacks. Then the computation becomes:

// n_fields includes n_field_callbacks (unsure if we'd want this)
(n_fields - n_field_callbacks) * sizeof(FieldBlob) + 
n_field_callbacks * (sizeof(FieldBlob) + sizeof(CallbackBlob))

That would at least allow a constant time skip over the fields section for ObjectBlobs when accessing anything after fields. This could work now in a compatible way since callback fields crashed the compiler prior to bug 725198 being fixed anyhow...
Comment 8 Simon Feltman 2014-02-28 01:18:50 UTC
Created attachment 270526 [details] [review]
girepository: Use constant time calculation for sections after Object fields

Add "n_field_callbacks" to ObjectBlob which represents the number of object
fields which are also callbacks. This a allows a constant time computation
for accessing sections after fields. Track writing of this field by passing
an extra argument through the girnode writers recursive call structure. This
essentally reverts a portion of commit 7027bb256d0d1ab which added a linear
time computation for accessing sections after fields.
Update typelib validator to also ensure n_field_callbacks is properly set.

Notes:
I verified the PyGObject test suite works well with this: Regress.TestObj is 
heavily relied on and problems here causes everything to break. Still if 
this approach seems ok, it would be a good idea to add more callback fields 
to TestObj which are also interleaved with regular fields to be more 
thorough.
Comment 9 André Klapper 2015-02-07 17:17:27 UTC
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]
Comment 10 Giovanni Campagna 2015-10-10 21:21:22 UTC
Review of attachment 270526 [details] [review]:

(Sorry I never got around to review this, in more than one year...)

I think this makes sense to me.
Comment 11 Colin Walters 2015-10-10 21:23:38 UTC
Review of attachment 270526 [details] [review]:

::: girepository/giobjectinfo.c
@@ -77,3 @@
-      if (field_blob->has_embedded_type)
-        offset += header->callback_blob_size;
-    }

Can we preserve this function, just make it constant time again?  Would reduce the diff noise.
Comment 12 Colin Walters 2015-10-10 21:32:58 UTC
Actually nevermind, that previous comment doesn't really make sense.

But...we aren't handling the case where there are intermixed fields and callbacks, right?

struct foo {
  guint x;
  void (*foo) (void);
  guint y;
}

?

There's not really a good reason to do this.  I suspect it exists though.  Could possibly query gir files for this.
Comment 13 Colin Walters 2015-10-10 22:03:49 UTC
Review of attachment 270526 [details] [review]:

OK, I reworked this patch to preserve the get_field_offset() for field lookups, but return everything else to constant time.   https://git.gnome.org/browse/gobject-introspection/commit/?id=df21d1f362a810f48a23b7c121bf09ce398539c7
Comment 14 Simon Feltman 2015-10-12 01:07:43 UTC
(In reply to Colin Walters from comment #12)
> Actually nevermind, that previous comment doesn't really make sense.
> 
> But...we aren't handling the case where there are intermixed fields and
> callbacks, right?
> 
> struct foo {
>   guint x;
>   void (*foo) (void);
>   guint y;
> }

Indeed this was a bug, nice catch.
Comment 15 Simon Feltman 2015-10-12 01:11:32 UTC
At this point the patch may cause a compatibility problem. Note from comment #7:

"This could work now in a compatible way since callback fields crashed the compiler prior to bug 725198 being fixed anyhow..."

That statement is no longer true since over a year has passed. typelib files created between then and now with field callbacks will have n_field_callbacks set to zero. Skipping over the fields section worked due to the linear search for fields with "has_embedded_type". With this removed, the typelibs will not be compatible with new versions of gi which are expecting n_field_callbacks to be correct.

Sorry for not giving a clearer warning in the original patch. Does this need to be backed out or can we bump the typelib version and add backwards compatibility?
Comment 16 Colin Walters 2015-10-12 14:16:20 UTC
(In reply to Simon Feltman from comment #15)
> At this point the patch may cause a compatibility problem. Note from comment
> #7:
> 
> "This could work now in a compatible way since callback fields crashed the
> compiler prior to bug 725198 being fixed anyhow..."
> 
> That statement is no longer true since over a year has passed. typelib files
> created between then and now with field callbacks will have
> n_field_callbacks set to zero. Skipping over the fields section worked due
> to the linear search for fields with "has_embedded_type". With this removed,
> the typelibs will not be compatible with new versions of gi which are
> expecting n_field_callbacks to be correct.

Oh, ugh.  Maybe we can support both typelib formats, and increment the minor version?

We don't have any really good way to test this stuff at the moment =/  Maybe --format-version=4.0 for g-ir-compiler?
Comment 17 Colin Walters 2015-10-13 14:08:26 UTC
Simon, do you want to take this?  I can take a look possibly if not.
Comment 18 Simon Feltman 2015-10-14 07:07:13 UTC
(In reply to Colin Walters from comment #17)
> Simon, do you want to take this?  I can take a look possibly if not.

Sure, I can take a look. Is idea with "--format-version" that we would be able to write out the earlier version in our test suite, then verify it loads and offset calculations work correctly?
Comment 19 Colin Walters 2015-10-20 18:20:00 UTC
(In reply to Simon Feltman from comment #18)
> (In reply to Colin Walters from comment #17)
> > Simon, do you want to take this?  I can take a look possibly if not.
> 
> Sure, I can take a look. Is idea with "--format-version" that we would be
> able to write out the earlier version in our test suite, then verify it
> loads and offset calculations work correctly?

Something like that; we don't necessarily have to do this now, it could be tested by hand (old copy of g-ir-compiler).
Comment 20 Torsten Schoenfeld 2016-10-23 17:42:04 UTC
It looks like g_struct_info_find_method is still broken for class structs due to the problems described here.  For example, it crashes when you try to find "find_style_property" on GtkWidgetClass.  I attach a patch that fixes the problem for me by mimicing what g_struct_info_get_method does (calling g_struct_get_field_offset).  But I don't know if this a complete fix; in particular, I don't have a clear understanding of the backwards compatibility concerns you discussed.
Comment 21 Torsten Schoenfeld 2016-10-23 17:42:30 UTC
Created attachment 338295 [details] [review]
g_struct_info_find_method: fix offset computation
Comment 22 GNOME Infrastructure Team 2018-02-08 12:22:28 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gobject-introspection/issues/86.