GNOME Bugzilla – Bug 710665
g-i uses wrong offsets if a struct contains a nested struct (not a struct *)
Last modified: 2018-02-08 12:25:38 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 ...
(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.)
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.
Forcing the nested struct to be (skip)'d is fine, as long as it's considered to take up the right number of bytes :-)
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]
-- 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.