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 710665 - g-i uses wrong offsets if a struct contains a nested struct (not a struct *)
g-i uses wrong offsets if a struct contains a nested struct (not a struct *)
Status: RESOLVED OBSOLETE
Product: gobject-introspection
Classification: Platform
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gobject-introspection Maintainer(s)
gobject-introspection Maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2013-10-22 16:45 UTC by Simon McVittie
Modified: 2018-02-08 12:25 UTC
See Also:
GNOME target: ---
GNOME version: 3.7/3.8



Description Simon McVittie 2013-10-22 16:45:35 UTC
This is with Debian's gobject-introspection 1.36.0-2+b1.

When I scanned the structs below and implemented the dup_parameters_array() vfunc, pygi and gjs wrongly placed the pointer in the identify_account() field - that's 56 bytes too early. That error would be consistent with g-i thinking the TpDBusPropertiesMixinClass (64 bytes) was a TpDBusPropertiesMixinClass* (8 bytes) when it calculated the offsets of the vfuncs.

-----------------------------

Faulty structs:

typedef struct _TpDBusPropertiesMixinClass TpDBusPropertiesMixinClass;

struct _TpDBusPropertiesMixinClass {
    TpDBusPropertiesMixinIfaceImpl *interfaces;
    /*<private>*/
    gpointer _1;
    gpointer _2;
    gpointer _3;
    gpointer _4;
    gpointer _5;
    gpointer _6;
    gpointer _7;
};

struct _TpBaseProtocolClass
{
  GObjectClass parent_class;

  TpDBusPropertiesMixinClass dbus_properties_class;

  gboolean is_stub;
  const TpCMParamSpec *(*get_parameters) (TpBaseProtocol *self);
  TpBaseConnection *(*new_connection) (TpBaseProtocol *self,
      GHashTable *asv,
      GError **error);

  gchar *(*normalize_contact) (TpBaseProtocol *self,
      const gchar *contact,
      GError **error);
  gchar *(*identify_account) (TpBaseProtocol *self,
      GHashTable *asv,
      GError **error);

  /*<private>*/
  GStrv (*_TP_SEAL (get_interfaces)) (TpBaseProtocol *self);
  /*<public>*/

  void (*get_connection_details) (TpBaseProtocol *self,
      GStrv *connection_interfaces,
      GType **channel_manager_types,
      gchar **icon_name,
      gchar **english_name,
      gchar **vcard_field);

  const TpPresenceStatusSpec * (*get_statuses) (TpBaseProtocol *self);

  void (*get_avatar_details) (TpBaseProtocol *self,
      GStrv *supported_mime_types,
      guint *min_height,
      guint *min_width,
      guint *rec_height,
      guint *rec_width,
      guint *max_height,
      guint *max_width,
      guint *max_bytes);

  GStrv (*dup_authentication_types) (TpBaseProtocol *self);

  GPtrArray * (*get_interfaces_array) (TpBaseProtocol *self);

  GPtrArray *(*dup_parameters_array) (TpBaseProtocol *self);

  /*<private>*/
  GCallback padding[3];
  TpBaseProtocolClassPrivate *priv;
};

-----------------------------

Workaround:

#ifndef __GI_SCANNER__
#ifndef __GTK_DOC_IGNORE__
/* See below. If this assertion fails on your platform, you'll have to
 * do something clever. */
G_STATIC_ASSERT (sizeof (gpointer[8]) == sizeof (TpDBusPropertiesMixinClass));
#endif
#endif

struct _TpBaseProtocolClass
{
  GObjectClass parent_class;

#ifdef __GI_SCANNER__
#ifndef __GTK_DOC_IGNORE__
  /* g-i gets confused and thinks TpDBusPropertiesMixinClass is only
   * one pointer long (as if it was a TpDBusPropertiesMixinClass *),
   * resulting in everything after this point being off-by-56 on x86-64.
   * Trick it into choosing the right offset - it does understand
   * arrays, so we can use one of those. */
  gpointer dbus_properties_class[8];
#endif
#else
  TpDBusPropertiesMixinClass dbus_properties_class;
#endif
...
Comment 1 Simon McVittie 2013-10-22 16:46:26 UTC
(Yes I know it'd be better if I didn't have nested structs, but for backwards compatibility, it's hard to get rid of.)
Comment 2 Colin Walters 2013-10-30 20:15:30 UTC
Yeah, sorry...the g-i code in this respect is a bit of a mess because long ago I made a decision *not* to support "arbitrary" C code.  For example, you can't introspect APIs which pass structures by value (and nor can you arbitrarily double indirect).

We probably do need to at least internally record the levels of indirection per type more robustly, at least for the purposes of providing warnings.
Comment 3 Simon McVittie 2013-10-31 12:32:47 UTC
Forcing the nested struct to be (skip)'d is fine, as long as it's considered to take up the right number of bytes :-)
Comment 4 André Klapper 2015-02-07 17:18:40 UTC
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]
Comment 5 GNOME Infrastructure Team 2018-02-08 12:25:38 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/99.