1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 * GObject introspection: typelib validation, auxiliary functions
3 * related to the binary typelib format
5 * Copyright (C) 2005 Matthias Clasen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
29 #include "gitypelib-internal.h"
30 #include "glib-compat.h"
34 GSList *context_stack;
37 #define ALIGN_VALUE(this, boundary) \
38 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
41 push_context (ValidateContext *ctx, const char *name)
43 ctx->context_stack = g_slist_prepend (ctx->context_stack, (char*)name);
47 pop_context (ValidateContext *ctx)
49 g_assert (ctx->context_stack != NULL);
50 ctx->context_stack = g_slist_delete_link (ctx->context_stack,
55 validate_interface_blob (ValidateContext *ctx,
60 get_dir_entry_checked (GITypelib *typelib,
64 Header *header = (Header *)typelib->data;
67 if (index == 0 || index > header->n_entries)
71 G_TYPELIB_ERROR_INVALID_BLOB,
72 "Invalid directory index %d", index);
76 offset = header->directory + (index - 1) * header->entry_blob_size;
78 if (typelib->len < offset + sizeof (DirEntry))
82 G_TYPELIB_ERROR_INVALID,
83 "The buffer is too short");
87 return (DirEntry *)&typelib->data[offset];
92 get_blob (GITypelib *typelib,
96 if (typelib->len < offset + sizeof (CommonBlob))
100 G_TYPELIB_ERROR_INVALID,
101 "The buffer is too short");
104 return (CommonBlob *)&typelib->data[offset];
107 static InterfaceTypeBlob *
108 get_type_blob (GITypelib *typelib,
109 SimpleTypeBlob *simple,
112 if (simple->offset == 0)
116 G_TYPELIB_ERROR_INVALID,
117 "Expected blob for type");
121 if (simple->flags.reserved == 0 && simple->flags.reserved2 == 0)
125 G_TYPELIB_ERROR_INVALID,
126 "Expected non-basic type but got %d",
131 return (InterfaceTypeBlob*) get_blob (typelib, simple->offset, error);
135 g_typelib_get_dir_entry (GITypelib *typelib,
138 Header *header = (Header *)typelib->data;
140 return (DirEntry *)&typelib->data[header->directory + (index - 1) * header->entry_blob_size];
144 get_section_by_id (GITypelib *typelib,
145 SectionType section_type)
147 Header *header = (Header *)typelib->data;
150 if (header->sections == 0)
153 for (section = (Section*)&typelib->data[header->sections];
154 section->id != GI_SECTION_END;
157 if (section->id == section_type)
164 g_typelib_get_dir_entry_by_name (GITypelib *typelib,
169 const char *entry_name;
172 dirindex = get_section_by_id (typelib, GI_SECTION_DIRECTORY_INDEX);
174 if (dirindex == NULL)
176 gint n_entries = ((Header *)typelib->data)->n_local_entries;
177 for (i = 1; i <= n_entries; i++)
179 entry = g_typelib_get_dir_entry (typelib, i);
180 entry_name = g_typelib_get_string (typelib, entry->name);
181 if (strcmp (name, entry_name) == 0)
188 guint8 *hash = (guint8*) &typelib->data[dirindex->offset];
191 index = _gi_typelib_hash_search (hash, name);
192 entry = g_typelib_get_dir_entry (typelib, index + 1);
193 entry_name = g_typelib_get_string (typelib, entry->name);
194 if (strcmp (name, entry_name) == 0)
201 g_typelib_get_dir_entry_by_gtype (GITypelib *typelib,
205 Header *header = (Header *)typelib->data;
206 guint n_entries = header->n_local_entries;
207 const char *gtype_name = g_type_name (gtype);
210 const char *c_prefix;
212 /* There is a corner case regarding GdkRectangle. GdkRectangle is a
213 boxed type, but it is just an alias to boxed struct
214 CairoRectangleInt. Scanner automatically converts all references
215 to GdkRectangle to CairoRectangleInt, so GdkRectangle does not
216 appear in the typelibs at all, although user code might query it.
217 So if we get such query, we also change it to lookup of
219 https://bugzilla.gnome.org/show_bug.cgi?id=655423 */
220 if (!fastpass && !strcmp (gtype_name, "GdkRectangle"))
221 gtype_name = "CairoRectangleInt";
223 /* Inside each typelib, we include the "C prefix" which acts as
224 * a namespace mechanism. For GtkTreeView, the C prefix is Gtk.
225 * Given the assumption that GTypes for a library also use the
226 * C prefix, we know we can skip examining a typelib if our
227 * target type does not have this typelib's C prefix.
229 * However, not every class library necessarily conforms to this,
230 * e.g. Clutter has Cogl inside it. So, we split this into two
231 * passes. First we try a lookup, skipping things which don't
232 * have the prefix. If that fails then we try a global lookup,
233 * ignoring the prefix.
235 * See http://bugzilla.gnome.org/show_bug.cgi?id=564016
237 c_prefix = g_typelib_get_string (typelib, header->c_prefix);
238 if (fastpass && c_prefix != NULL)
240 if (g_ascii_strncasecmp (c_prefix, gtype_name, strlen (c_prefix)) != 0)
244 for (i = 1; i <= n_entries; i++)
246 RegisteredTypeBlob *blob;
249 entry = g_typelib_get_dir_entry (typelib, i);
250 if (!BLOB_IS_REGISTERED_TYPE (entry))
253 blob = (RegisteredTypeBlob *)(&typelib->data[entry->offset]);
254 if (!blob->gtype_name)
257 type = g_typelib_get_string (typelib, blob->gtype_name);
258 if (strcmp (type, gtype_name) == 0)
265 g_typelib_get_dir_entry_by_error_domain (GITypelib *typelib,
268 Header *header = (Header *)typelib->data;
269 guint n_entries = header->n_local_entries;
270 const char *domain_string = g_quark_to_string (error_domain);
274 for (i = 1; i <= n_entries; i++)
277 const char *enum_domain_string;
279 entry = g_typelib_get_dir_entry (typelib, i);
280 if (entry->blob_type != BLOB_TYPE_ENUM)
283 blob = (EnumBlob *)(&typelib->data[entry->offset]);
284 if (!blob->error_domain)
287 enum_domain_string = g_typelib_get_string (typelib, blob->error_domain);
288 if (strcmp (domain_string, enum_domain_string) == 0)
295 g_typelib_check_sanity (void)
297 /* Check that struct layout is as we expect */
299 gboolean size_check_ok = TRUE;
301 #define CHECK_SIZE(s,n) \
302 if (sizeof(s) != n) \
304 g_printerr ("sizeof("#s") is expected to be %d but is %"G_GSIZE_FORMAT".\n", \
306 size_check_ok = FALSE; \
309 /* When changing the size of a typelib structure, you are required to update
310 * the hardcoded size here. Do NOT change these to use sizeof(); these
311 * should match whatever is defined in the text specification and serve as
312 * a sanity check on structure modifications.
314 * Everything else in the code however should be using sizeof().
317 CHECK_SIZE (Header, 112);
318 CHECK_SIZE (DirEntry, 12);
319 CHECK_SIZE (SimpleTypeBlob, 4);
320 CHECK_SIZE (ArgBlob, 16);
321 CHECK_SIZE (SignatureBlob, 8);
322 CHECK_SIZE (CommonBlob, 8);
323 CHECK_SIZE (FunctionBlob, 20);
324 CHECK_SIZE (CallbackBlob, 12);
325 CHECK_SIZE (InterfaceTypeBlob, 4);
326 CHECK_SIZE (ArrayTypeBlob, 8);
327 CHECK_SIZE (ParamTypeBlob, 4);
328 CHECK_SIZE (ErrorTypeBlob, 4);
329 CHECK_SIZE (ValueBlob, 12);
330 CHECK_SIZE (FieldBlob, 16);
331 CHECK_SIZE (RegisteredTypeBlob, 16);
332 CHECK_SIZE (StructBlob, 32);
333 CHECK_SIZE (EnumBlob, 24);
334 CHECK_SIZE (PropertyBlob, 16);
335 CHECK_SIZE (SignalBlob, 16);
336 CHECK_SIZE (VFuncBlob, 20);
337 CHECK_SIZE (ObjectBlob, 60);
338 CHECK_SIZE (InterfaceBlob, 40);
339 CHECK_SIZE (ConstantBlob, 24);
340 CHECK_SIZE (AttributeBlob, 12);
341 CHECK_SIZE (UnionBlob, 40);
344 g_assert (size_check_ok);
349 is_aligned (guint32 offset)
351 return offset == ALIGN_VALUE (offset, 4);
354 #define MAX_NAME_LEN 200
357 get_string (GITypelib *typelib, guint32 offset, GError **error)
359 if (typelib->len < offset)
363 G_TYPELIB_ERROR_INVALID,
364 "Buffer is too short while looking up name");
368 return (const char*)&typelib->data[offset];
372 get_string_nofail (GITypelib *typelib, guint32 offset)
374 const char *ret = get_string (typelib, offset, NULL);
380 validate_name (GITypelib *typelib,
382 const guchar *data, guint32 offset,
387 name = get_string (typelib, offset, error);
391 if (!memchr (name, '\0', MAX_NAME_LEN))
395 G_TYPELIB_ERROR_INVALID,
396 "The %s is too long: %s",
401 if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
405 G_TYPELIB_ERROR_INVALID,
406 "The %s contains invalid characters: '%s'",
414 /* Fast path sanity check, operates on a memory blob */
416 validate_header_basic (const guint8 *memory,
420 Header *header = (Header *)memory;
422 if (len < sizeof (Header))
426 G_TYPELIB_ERROR_INVALID,
427 "The specified typelib length %" G_GSIZE_FORMAT " is too short",
432 if (strncmp (header->magic, G_IR_MAGIC, 16) != 0)
436 G_TYPELIB_ERROR_INVALID_HEADER,
437 "Invalid magic header");
442 if (header->major_version != 4)
446 G_TYPELIB_ERROR_INVALID_HEADER,
447 "Typelib version mismatch; expected 4, found %d",
448 header->major_version);
453 if (header->n_entries < header->n_local_entries)
457 G_TYPELIB_ERROR_INVALID_HEADER,
458 "Inconsistent entry counts");
462 if (header->size != len)
466 G_TYPELIB_ERROR_INVALID_HEADER,
467 "Typelib size %" G_GSIZE_FORMAT " does not match %" G_GSIZE_FORMAT,
468 (gsize) header->size, len);
472 /* This is a sanity check for a specific typelib; it
473 * prevents us from loading an incompatible typelib.
475 * The hardcoded checks in g_typelib_check_sanity to
476 * protect against inadvertent or buggy changes to the typelib format
480 if (header->entry_blob_size != sizeof (DirEntry) ||
481 header->function_blob_size != sizeof (FunctionBlob) ||
482 header->callback_blob_size != sizeof (CallbackBlob) ||
483 header->signal_blob_size != sizeof (SignalBlob) ||
484 header->vfunc_blob_size != sizeof (VFuncBlob) ||
485 header->arg_blob_size != sizeof (ArgBlob) ||
486 header->property_blob_size != sizeof (PropertyBlob) ||
487 header->field_blob_size != sizeof (FieldBlob) ||
488 header->value_blob_size != sizeof (ValueBlob) ||
489 header->constant_blob_size != sizeof (ConstantBlob) ||
490 header->attribute_blob_size != sizeof (AttributeBlob) ||
491 header->signature_blob_size != sizeof (SignatureBlob) ||
492 header->enum_blob_size != sizeof (EnumBlob) ||
493 header->struct_blob_size != sizeof (StructBlob) ||
494 header->object_blob_size != sizeof(ObjectBlob) ||
495 header->interface_blob_size != sizeof (InterfaceBlob) ||
496 header->union_blob_size != sizeof (UnionBlob))
500 G_TYPELIB_ERROR_INVALID_HEADER,
501 "Blob size mismatch");
505 if (!is_aligned (header->directory))
509 G_TYPELIB_ERROR_INVALID_HEADER,
510 "Misaligned directory");
514 if (!is_aligned (header->attributes))
518 G_TYPELIB_ERROR_INVALID_HEADER,
519 "Misaligned attributes");
523 if (header->attributes == 0 && header->n_attributes > 0)
527 G_TYPELIB_ERROR_INVALID_HEADER,
528 "Wrong number of attributes");
536 validate_header (ValidateContext *ctx,
539 GITypelib *typelib = ctx->typelib;
541 if (!validate_header_basic (typelib->data, typelib->len, error))
545 Header *header = (Header*)typelib->data;
546 if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
553 static gboolean validate_type_blob (GITypelib *typelib,
555 guint32 signature_offset,
556 gboolean return_type,
560 validate_array_type_blob (GITypelib *typelib,
562 guint32 signature_offset,
563 gboolean return_type,
566 /* FIXME validate length */
568 if (!validate_type_blob (typelib,
569 offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
577 validate_iface_type_blob (GITypelib *typelib,
579 guint32 signature_offset,
580 gboolean return_type,
583 InterfaceTypeBlob *blob;
584 InterfaceBlob *target;
586 blob = (InterfaceTypeBlob*)&typelib->data[offset];
588 target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
592 if (target->blob_type == 0) /* non-local */
599 validate_param_type_blob (GITypelib *typelib,
601 guint32 signature_offset,
602 gboolean return_type,
609 blob = (ParamTypeBlob*)&typelib->data[offset];
615 G_TYPELIB_ERROR_INVALID_BLOB,
616 "Pointer type exected for tag %d", blob->tag);
620 if (blob->n_types != n_params)
624 G_TYPELIB_ERROR_INVALID_BLOB,
625 "Parameter type number mismatch");
629 for (i = 0; i < n_params; i++)
631 if (!validate_type_blob (typelib,
632 offset + sizeof (ParamTypeBlob) +
633 i * sizeof (SimpleTypeBlob),
642 validate_error_type_blob (GITypelib *typelib,
644 guint32 signature_offset,
645 gboolean return_type,
650 blob = (ErrorTypeBlob*)&typelib->data[offset];
656 G_TYPELIB_ERROR_INVALID_BLOB,
657 "Pointer type exected for tag %d", blob->tag);
665 validate_type_blob (GITypelib *typelib,
667 guint32 signature_offset,
668 gboolean return_type,
671 SimpleTypeBlob *simple;
672 InterfaceTypeBlob *iface;
674 simple = (SimpleTypeBlob *)&typelib->data[offset];
676 if (simple->flags.reserved == 0 &&
677 simple->flags.reserved2 == 0)
679 if (!G_TYPE_TAG_IS_BASIC(simple->flags.tag))
683 G_TYPELIB_ERROR_INVALID_BLOB,
684 "Invalid non-basic tag %d in simple type", simple->flags.tag);
688 if (simple->flags.tag >= GI_TYPE_TAG_UTF8 &&
689 simple->flags.tag != GI_TYPE_TAG_UNICHAR &&
690 !simple->flags.pointer)
694 G_TYPELIB_ERROR_INVALID_BLOB,
695 "Pointer type exected for tag %d", simple->flags.tag);
702 iface = (InterfaceTypeBlob*)&typelib->data[simple->offset];
706 case GI_TYPE_TAG_ARRAY:
707 if (!validate_array_type_blob (typelib, simple->offset,
708 signature_offset, return_type, error))
711 case GI_TYPE_TAG_INTERFACE:
712 if (!validate_iface_type_blob (typelib, simple->offset,
713 signature_offset, return_type, error))
716 case GI_TYPE_TAG_GLIST:
717 case GI_TYPE_TAG_GSLIST:
718 if (!validate_param_type_blob (typelib, simple->offset,
719 signature_offset, return_type, 1, error))
722 case GI_TYPE_TAG_GHASH:
723 if (!validate_param_type_blob (typelib, simple->offset,
724 signature_offset, return_type, 2, error))
727 case GI_TYPE_TAG_ERROR:
728 if (!validate_error_type_blob (typelib, simple->offset,
729 signature_offset, return_type, error))
735 G_TYPELIB_ERROR_INVALID_BLOB,
736 "Wrong tag in complex type");
744 validate_arg_blob (GITypelib *typelib,
746 guint32 signature_offset,
751 if (typelib->len < offset + sizeof (ArgBlob))
755 G_TYPELIB_ERROR_INVALID,
756 "The buffer is too short");
760 blob = (ArgBlob*) &typelib->data[offset];
762 if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
765 if (!validate_type_blob (typelib,
766 offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
767 signature_offset, FALSE, error))
773 static SimpleTypeBlob *
774 return_type_from_signature (GITypelib *typelib,
779 if (typelib->len < offset + sizeof (SignatureBlob))
783 G_TYPELIB_ERROR_INVALID,
784 "The buffer is too short");
788 blob = (SignatureBlob*) &typelib->data[offset];
789 if (blob->return_type.offset == 0)
793 G_TYPELIB_ERROR_INVALID,
794 "No return type found in signature");
798 return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
802 validate_signature_blob (GITypelib *typelib,
809 if (typelib->len < offset + sizeof (SignatureBlob))
813 G_TYPELIB_ERROR_INVALID,
814 "The buffer is too short");
818 blob = (SignatureBlob*) &typelib->data[offset];
820 if (blob->return_type.offset != 0)
822 if (!validate_type_blob (typelib,
823 offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
824 offset, TRUE, error))
828 for (i = 0; i < blob->n_arguments; i++)
830 if (!validate_arg_blob (typelib,
831 offset + sizeof (SignatureBlob) +
832 i * sizeof (ArgBlob),
838 /* FIXME check constraints on return_value */
839 /* FIXME check array-length pairs */
844 validate_function_blob (ValidateContext *ctx,
846 guint16 container_type,
849 GITypelib *typelib = ctx->typelib;
852 if (typelib->len < offset + sizeof (FunctionBlob))
856 G_TYPELIB_ERROR_INVALID,
857 "The buffer is too short");
861 blob = (FunctionBlob*) &typelib->data[offset];
863 if (blob->blob_type != BLOB_TYPE_FUNCTION)
867 G_TYPELIB_ERROR_INVALID_BLOB,
868 "Wrong blob type %d, expected function", blob->blob_type);
872 if (!validate_name (typelib, "function", typelib->data, blob->name, error))
875 push_context (ctx, get_string_nofail (typelib, blob->name));
877 if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
880 if (blob->constructor)
882 switch (container_type)
884 case BLOB_TYPE_BOXED:
885 case BLOB_TYPE_STRUCT:
886 case BLOB_TYPE_UNION:
887 case BLOB_TYPE_OBJECT:
888 case BLOB_TYPE_INTERFACE:
893 G_TYPELIB_ERROR_INVALID_BLOB,
894 "Constructor not allowed");
899 if (blob->setter || blob->getter || blob->wraps_vfunc)
901 switch (container_type)
903 case BLOB_TYPE_OBJECT:
904 case BLOB_TYPE_INTERFACE:
909 G_TYPELIB_ERROR_INVALID_BLOB,
910 "Setter, getter or wrapper not allowed");
917 if (!(blob->setter || blob->getter || blob->wraps_vfunc))
921 G_TYPELIB_ERROR_INVALID_BLOB,
922 "Must be setter, getter or wrapper");
927 /* FIXME: validate index range */
929 if (!validate_signature_blob (typelib, blob->signature, error))
932 if (blob->constructor)
934 SimpleTypeBlob *simple = return_type_from_signature (typelib,
937 InterfaceTypeBlob *iface_type;
941 iface_type = get_type_blob (typelib, simple, error);
944 if (iface_type->tag != GI_TYPE_TAG_INTERFACE &&
945 (container_type == BLOB_TYPE_OBJECT ||
946 container_type == BLOB_TYPE_INTERFACE))
950 G_TYPELIB_ERROR_INVALID,
951 "Invalid return type '%s' for constructor '%s'",
952 g_type_tag_to_string (iface_type->tag),
953 get_string_nofail (typelib, blob->symbol));
964 validate_callback_blob (ValidateContext *ctx,
968 GITypelib *typelib = ctx->typelib;
971 if (typelib->len < offset + sizeof (CallbackBlob))
975 G_TYPELIB_ERROR_INVALID,
976 "The buffer is too short");
980 blob = (CallbackBlob*) &typelib->data[offset];
982 if (blob->blob_type != BLOB_TYPE_CALLBACK)
986 G_TYPELIB_ERROR_INVALID_BLOB,
991 if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
994 push_context (ctx, get_string_nofail (typelib, blob->name));
996 if (!validate_signature_blob (typelib, blob->signature, error))
1005 validate_constant_blob (GITypelib *typelib,
1009 guint value_size[] = {
1034 SimpleTypeBlob *type;
1036 g_assert (G_N_ELEMENTS (value_size) == GI_TYPE_TAG_N_TYPES);
1038 if (typelib->len < offset + sizeof (ConstantBlob))
1042 G_TYPELIB_ERROR_INVALID,
1043 "The buffer is too short");
1047 blob = (ConstantBlob*) &typelib->data[offset];
1049 if (blob->blob_type != BLOB_TYPE_CONSTANT)
1053 G_TYPELIB_ERROR_INVALID_BLOB,
1058 if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
1061 if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
1065 if (!is_aligned (blob->offset))
1069 G_TYPELIB_ERROR_INVALID_BLOB,
1070 "Misaligned constant value");
1074 type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
1075 if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
1077 if (type->flags.tag == 0)
1081 G_TYPELIB_ERROR_INVALID_BLOB,
1082 "Constant value type void");
1086 if (value_size[type->flags.tag] != 0 &&
1087 blob->size != value_size[type->flags.tag])
1091 G_TYPELIB_ERROR_INVALID_BLOB,
1092 "Constant value size mismatch");
1095 /* FIXME check string values */
1102 validate_value_blob (GITypelib *typelib,
1108 if (typelib->len < offset + sizeof (ValueBlob))
1112 G_TYPELIB_ERROR_INVALID,
1113 "The buffer is too short");
1117 blob = (ValueBlob*) &typelib->data[offset];
1119 if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1126 validate_field_blob (ValidateContext *ctx,
1130 GITypelib *typelib = ctx->typelib;
1131 Header *header = (Header *)typelib->data;
1134 if (typelib->len < offset + sizeof (FieldBlob))
1138 G_TYPELIB_ERROR_INVALID,
1139 "The buffer is too short");
1143 blob = (FieldBlob*) &typelib->data[offset];
1145 if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1148 if (blob->has_embedded_type)
1150 if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
1153 else if (!validate_type_blob (typelib,
1154 offset + G_STRUCT_OFFSET (FieldBlob, type),
1162 validate_property_blob (GITypelib *typelib,
1168 if (typelib->len < offset + sizeof (PropertyBlob))
1172 G_TYPELIB_ERROR_INVALID,
1173 "The buffer is too short");
1177 blob = (PropertyBlob*) &typelib->data[offset];
1179 if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1182 if (!validate_type_blob (typelib,
1183 offset + G_STRUCT_OFFSET (PropertyBlob, type),
1191 validate_signal_blob (GITypelib *typelib,
1193 guint32 container_offset,
1199 if (typelib->len < offset + sizeof (SignalBlob))
1203 G_TYPELIB_ERROR_INVALID,
1204 "The buffer is too short");
1208 blob = (SignalBlob*) &typelib->data[offset];
1210 if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1213 if ((blob->run_first != 0) +
1214 (blob->run_last != 0) +
1215 (blob->run_cleanup != 0) != 1)
1219 G_TYPELIB_ERROR_INVALID_BLOB,
1220 "Invalid signal run flags");
1224 if (blob->has_class_closure)
1226 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1230 object = (ObjectBlob*)&typelib->data[container_offset];
1232 n_signals = object->n_signals;
1236 InterfaceBlob *iface;
1238 iface = (InterfaceBlob*)&typelib->data[container_offset];
1240 n_signals = iface->n_signals;
1243 if (blob->class_closure >= n_signals)
1247 G_TYPELIB_ERROR_INVALID_BLOB,
1248 "Invalid class closure index");
1253 if (!validate_signature_blob (typelib, blob->signature, error))
1260 validate_vfunc_blob (GITypelib *typelib,
1262 guint32 container_offset,
1268 if (typelib->len < offset + sizeof (VFuncBlob))
1272 G_TYPELIB_ERROR_INVALID,
1273 "The buffer is too short");
1277 blob = (VFuncBlob*) &typelib->data[offset];
1279 if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1282 if (blob->class_closure)
1284 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1288 object = (ObjectBlob*)&typelib->data[container_offset];
1290 n_vfuncs = object->n_vfuncs;
1294 InterfaceBlob *iface;
1296 iface = (InterfaceBlob*)&typelib->data[container_offset];
1298 n_vfuncs = iface->n_vfuncs;
1301 if (blob->class_closure >= n_vfuncs)
1305 G_TYPELIB_ERROR_INVALID_BLOB,
1306 "Invalid class closure index");
1311 if (!validate_signature_blob (typelib, blob->signature, error))
1318 validate_struct_blob (ValidateContext *ctx,
1323 GITypelib *typelib = ctx->typelib;
1326 guint32 field_offset;
1328 if (typelib->len < offset + sizeof (StructBlob))
1332 G_TYPELIB_ERROR_INVALID,
1333 "The buffer is too short");
1337 blob = (StructBlob*) &typelib->data[offset];
1339 if (blob->blob_type != blob_type)
1343 G_TYPELIB_ERROR_INVALID_BLOB,
1348 if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1351 push_context (ctx, get_string_nofail (typelib, blob->name));
1353 if (!blob->unregistered)
1355 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1358 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1363 if (blob->gtype_name || blob->gtype_init)
1367 G_TYPELIB_ERROR_INVALID_BLOB,
1368 "Gtype data in struct");
1373 if (typelib->len < offset + sizeof (StructBlob) +
1374 blob->n_fields * sizeof (FieldBlob) +
1375 blob->n_methods * sizeof (FunctionBlob))
1379 G_TYPELIB_ERROR_INVALID,
1380 "The buffer is too short");
1384 field_offset = offset + sizeof (StructBlob);
1385 for (i = 0; i < blob->n_fields; i++)
1387 FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
1389 if (!validate_field_blob (ctx,
1394 field_offset += sizeof (FieldBlob);
1395 if (blob->has_embedded_type)
1396 field_offset += sizeof (CallbackBlob);
1399 for (i = 0; i < blob->n_methods; i++)
1401 if (!validate_function_blob (ctx,
1403 i * sizeof (FunctionBlob),
1415 validate_enum_blob (ValidateContext *ctx,
1420 GITypelib *typelib = ctx->typelib;
1425 if (typelib->len < offset + sizeof (EnumBlob))
1429 G_TYPELIB_ERROR_INVALID,
1430 "The buffer is too short");
1434 blob = (EnumBlob*) &typelib->data[offset];
1436 if (blob->blob_type != blob_type)
1440 G_TYPELIB_ERROR_INVALID_BLOB,
1445 if (!blob->unregistered)
1447 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1450 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1455 if (blob->gtype_name || blob->gtype_init)
1459 G_TYPELIB_ERROR_INVALID_BLOB,
1460 "Gtype data in unregistered enum");
1465 if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1468 if (typelib->len < offset + sizeof (EnumBlob) +
1469 blob->n_values * sizeof (ValueBlob) +
1470 blob->n_methods * sizeof (FunctionBlob))
1474 G_TYPELIB_ERROR_INVALID,
1475 "The buffer is too short");
1479 offset2 = offset + sizeof (EnumBlob);
1481 push_context (ctx, get_string_nofail (typelib, blob->name));
1483 for (i = 0; i < blob->n_values; i++, offset2 += sizeof (ValueBlob))
1485 if (!validate_value_blob (typelib,
1491 v1 = (ValueBlob *)&typelib->data[offset2];
1492 for (j = 0; j < i; j++)
1494 v2 = (ValueBlob *)&typelib->data[offset2 +
1495 j * sizeof (ValueBlob)];
1497 if (v1->value == v2->value)
1500 /* FIXME should this be an error ? */
1503 G_TYPELIB_ERROR_INVALID_BLOB,
1504 "Duplicate enum value");
1511 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1513 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_ENUM, error))
1523 validate_object_blob (ValidateContext *ctx,
1527 GITypelib *typelib = ctx->typelib;
1533 header = (Header *)typelib->data;
1535 if (typelib->len < offset + sizeof (ObjectBlob))
1539 G_TYPELIB_ERROR_INVALID,
1540 "The buffer is too short");
1544 blob = (ObjectBlob*) &typelib->data[offset];
1546 if (blob->blob_type != BLOB_TYPE_OBJECT)
1550 G_TYPELIB_ERROR_INVALID_BLOB,
1555 if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1558 if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1561 if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1564 if (blob->parent > header->n_entries)
1568 G_TYPELIB_ERROR_INVALID_BLOB,
1569 "Invalid parent index");
1573 if (blob->parent != 0)
1577 entry = get_dir_entry_checked (typelib, blob->parent, error);
1580 if (entry->blob_type != BLOB_TYPE_OBJECT &&
1581 (entry->local || entry->blob_type != 0))
1585 G_TYPELIB_ERROR_INVALID_BLOB,
1586 "Parent not object");
1591 if (blob->gtype_struct != 0)
1595 entry = get_dir_entry_checked (typelib, blob->gtype_struct, error);
1598 if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1602 G_TYPELIB_ERROR_INVALID_BLOB,
1603 "Class struct invalid type or not local");
1608 if (typelib->len < offset + sizeof (ObjectBlob) +
1609 (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1610 blob->n_fields * sizeof (FieldBlob) +
1611 blob->n_properties * sizeof (PropertyBlob) +
1612 blob->n_methods * sizeof (FunctionBlob) +
1613 blob->n_signals * sizeof (SignalBlob) +
1614 blob->n_vfuncs * sizeof (VFuncBlob) +
1615 blob->n_constants * sizeof (ConstantBlob))
1620 G_TYPELIB_ERROR_INVALID,
1621 "The buffer is too short");
1625 offset2 = offset + sizeof (ObjectBlob);
1627 for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1632 iface = *(guint16*)&typelib->data[offset2];
1633 if (iface == 0 || iface > header->n_entries)
1637 G_TYPELIB_ERROR_INVALID_BLOB,
1638 "Invalid interface index");
1642 entry = get_dir_entry_checked (typelib, iface, error);
1646 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1647 (entry->local || entry->blob_type != 0))
1651 G_TYPELIB_ERROR_INVALID_BLOB,
1652 "Not an interface");
1657 offset2 += 2 * (blob->n_interfaces %2);
1659 push_context (ctx, get_string_nofail (typelib, blob->name));
1661 for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1663 if (!validate_field_blob (ctx, offset2, error))
1667 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1669 if (!validate_property_blob (typelib, offset2, error))
1673 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1675 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1679 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1681 if (!validate_signal_blob (typelib, offset2, offset, error))
1685 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1687 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1691 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1693 if (!validate_constant_blob (typelib, offset2, error))
1703 validate_interface_blob (ValidateContext *ctx,
1707 GITypelib *typelib = ctx->typelib;
1709 InterfaceBlob *blob;
1713 header = (Header *)typelib->data;
1715 if (typelib->len < offset + sizeof (InterfaceBlob))
1719 G_TYPELIB_ERROR_INVALID,
1720 "The buffer is too short");
1724 blob = (InterfaceBlob*) &typelib->data[offset];
1726 if (blob->blob_type != BLOB_TYPE_INTERFACE)
1730 G_TYPELIB_ERROR_INVALID_BLOB,
1731 "Wrong blob type; expected interface, got %d", blob->blob_type);
1735 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1738 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1741 if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1744 if (typelib->len < offset + sizeof (InterfaceBlob) +
1745 (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1746 blob->n_properties * sizeof (PropertyBlob) +
1747 blob->n_methods * sizeof (FunctionBlob) +
1748 blob->n_signals * sizeof (SignalBlob) +
1749 blob->n_vfuncs * sizeof (VFuncBlob) +
1750 blob->n_constants * sizeof (ConstantBlob))
1755 G_TYPELIB_ERROR_INVALID,
1756 "The buffer is too short");
1760 offset2 = offset + sizeof (InterfaceBlob);
1762 for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1767 req = *(guint16*)&typelib->data[offset2];
1768 if (req == 0 || req > header->n_entries)
1772 G_TYPELIB_ERROR_INVALID_BLOB,
1773 "Invalid prerequisite index");
1777 entry = g_typelib_get_dir_entry (typelib, req);
1778 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1779 entry->blob_type != BLOB_TYPE_OBJECT &&
1780 (entry->local || entry->blob_type != 0))
1784 G_TYPELIB_ERROR_INVALID_BLOB,
1785 "Not an interface or object");
1790 offset2 += 2 * (blob->n_prerequisites % 2);
1792 push_context (ctx, get_string_nofail (typelib, blob->name));
1794 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1796 if (!validate_property_blob (typelib, offset2, error))
1800 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1802 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1806 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1808 if (!validate_signal_blob (typelib, offset2, offset, error))
1812 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1814 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1818 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1820 if (!validate_constant_blob (typelib, offset2, error))
1830 validate_union_blob (GITypelib *typelib,
1838 validate_blob (ValidateContext *ctx,
1842 GITypelib *typelib = ctx->typelib;
1845 if (typelib->len < offset + sizeof (CommonBlob))
1849 G_TYPELIB_ERROR_INVALID,
1850 "The buffer is too short");
1854 common = (CommonBlob*)&typelib->data[offset];
1856 switch (common->blob_type)
1858 case BLOB_TYPE_FUNCTION:
1859 if (!validate_function_blob (ctx, offset, 0, error))
1862 case BLOB_TYPE_CALLBACK:
1863 if (!validate_callback_blob (ctx, offset, error))
1866 case BLOB_TYPE_STRUCT:
1867 case BLOB_TYPE_BOXED:
1868 if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1871 case BLOB_TYPE_ENUM:
1872 case BLOB_TYPE_FLAGS:
1873 if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1876 case BLOB_TYPE_OBJECT:
1877 if (!validate_object_blob (ctx, offset, error))
1880 case BLOB_TYPE_INTERFACE:
1881 if (!validate_interface_blob (ctx, offset, error))
1884 case BLOB_TYPE_CONSTANT:
1885 if (!validate_constant_blob (typelib, offset, error))
1888 case BLOB_TYPE_UNION:
1889 if (!validate_union_blob (typelib, offset, error))
1895 G_TYPELIB_ERROR_INVALID_ENTRY,
1896 "Invalid blob type");
1904 validate_directory (ValidateContext *ctx,
1907 GITypelib *typelib = ctx->typelib;
1908 Header *header = (Header *)typelib->data;
1912 if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1916 G_TYPELIB_ERROR_INVALID,
1917 "The buffer is too short");
1921 for (i = 0; i < header->n_entries; i++)
1923 entry = g_typelib_get_dir_entry (typelib, i + 1);
1925 if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1928 if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1929 entry->blob_type > BLOB_TYPE_UNION)
1933 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1934 "Invalid entry type");
1938 if (i < header->n_local_entries)
1944 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1945 "Too few local directory entries");
1949 if (!is_aligned (entry->offset))
1953 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1954 "Misaligned entry");
1958 if (!validate_blob (ctx, entry->offset, error))
1967 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1968 "Too many local directory entries");
1972 if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1981 validate_attributes (ValidateContext *ctx,
1984 GITypelib *typelib = ctx->typelib;
1985 Header *header = (Header *)typelib->data;
1987 if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
1991 G_TYPELIB_ERROR_INVALID,
1992 "The buffer is too short");
2000 prefix_with_context (GError **error,
2001 const char *section,
2002 ValidateContext *ctx)
2004 GString *str = g_string_new (NULL);
2008 link = ctx->context_stack;
2011 g_prefix_error (error, "In %s:", section);
2015 for (; link; link = link->next)
2017 g_string_append (str, link->data);
2019 g_string_append_c (str, '/');
2021 g_string_append_c (str, ')');
2022 buf = g_string_free (str, FALSE);
2023 g_prefix_error (error, "In %s (Context: %s): ", section, buf);
2028 g_typelib_validate (GITypelib *typelib,
2031 ValidateContext ctx;
2032 ctx.typelib = typelib;
2033 ctx.context_stack = NULL;
2035 if (!validate_header (&ctx, error))
2037 prefix_with_context (error, "In header", &ctx);
2041 if (!validate_directory (&ctx, error))
2043 prefix_with_context (error, "directory", &ctx);
2047 if (!validate_attributes (&ctx, error))
2049 prefix_with_context (error, "attributes", &ctx);
2057 g_typelib_error_quark (void)
2059 static GQuark quark = 0;
2061 quark = g_quark_from_static_string ("g-typelib-error-quark");
2066 _g_typelib_do_dlopen (GITypelib *typelib)
2069 const char *shlib_str;
2071 header = (Header *) typelib->data;
2072 /* note that NULL shlib means to open the main app, which is allowed */
2073 if (header->shared_library)
2074 shlib_str = g_typelib_get_string (typelib, header->shared_library);
2078 if (shlib_str != NULL && shlib_str[0] != '\0')
2083 /* shared-library is a comma-separated list of libraries */
2084 shlibs = g_strsplit (shlib_str, ",", 0);
2086 /* We load all passed libs unconditionally as if the same library is loaded
2087 * again with g_module_open(), the same file handle will be returned. See bug:
2088 * http://bugzilla.gnome.org/show_bug.cgi?id=555294
2090 for (i = 0; shlibs[i]; i++)
2094 /* Glade's autoconnect feature and OpenGL's extension mechanism
2095 * as used by Clutter rely on g_module_open(NULL) to work as a means of
2096 * accessing the app's symbols. This keeps us from using
2097 * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
2098 * in general libraries are not expecting multiple copies of
2099 * themselves and are not expecting to be unloaded. So we just
2100 * load modules globally for now.
2103 module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
2107 GString *shlib_full = g_string_new (shlibs[i]);
2109 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2112 g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
2113 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2116 g_string_free (shlib_full, TRUE);
2121 g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2122 shlibs[i], g_module_error ());
2126 typelib->modules = g_list_append (typelib->modules, module);
2130 g_strfreev (shlibs);
2134 /* If there's no shared-library entry for this module, assume that
2135 * the module is for the application. Some of the hand-written .gir files
2136 * in gobject-introspection don't have shared-library entries, but no one
2137 * is really going to be calling g_module_symbol on them either.
2139 GModule *module = g_module_open (NULL, 0);
2141 g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
2143 typelib->modules = g_list_prepend (typelib->modules, module);
2148 _g_typelib_ensure_open (GITypelib *typelib)
2150 if (typelib->open_attempted)
2152 typelib->open_attempted = TRUE;
2153 _g_typelib_do_dlopen (typelib);
2157 * g_typelib_new_from_memory: (skip)
2158 * @memory: address of memory chunk containing the typelib
2159 * @len: length of memory chunk containing the typelib
2162 * Creates a new #GITypelib from a memory location. The memory block
2163 * pointed to by @typelib will be automatically g_free()d when the
2164 * repository is destroyed.
2166 * Return value: the new #GITypelib
2169 g_typelib_new_from_memory (guint8 *memory,
2175 if (!validate_header_basic (memory, len, error))
2178 meta = g_slice_new0 (GITypelib);
2179 meta->data = memory;
2181 meta->owns_memory = TRUE;
2182 meta->modules = NULL;
2188 * g_typelib_new_from_const_memory: (skip)
2189 * @memory: address of memory chunk containing the typelib
2190 * @len: length of memory chunk containing the typelib
2193 * Creates a new #GITypelib from a memory location.
2195 * Return value: the new #GITypelib
2198 g_typelib_new_from_const_memory (const guchar *memory,
2204 if (!validate_header_basic (memory, len, error))
2207 meta = g_slice_new0 (GITypelib);
2208 meta->data = (guchar *) memory;
2210 meta->owns_memory = FALSE;
2211 meta->modules = NULL;
2217 * g_typelib_new_from_mapped_file: (skip)
2218 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2221 * Creates a new #GITypelib from a #GMappedFile.
2223 * Return value: the new #GITypelib
2226 g_typelib_new_from_mapped_file (GMappedFile *mfile,
2230 guint8 *data = (guint8 *) g_mapped_file_get_contents (mfile);
2231 gsize len = g_mapped_file_get_length (mfile);
2233 if (!validate_header_basic (data, len, error))
2236 meta = g_slice_new0 (GITypelib);
2237 meta->mfile = mfile;
2238 meta->owns_memory = FALSE;
2247 * @typelib: a #GITypelib
2249 * Free a #GITypelib.
2252 g_typelib_free (GITypelib *typelib)
2255 g_mapped_file_unref (typelib->mfile);
2257 if (typelib->owns_memory)
2258 g_free (typelib->data);
2259 if (typelib->modules)
2261 g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2262 g_list_free (typelib->modules);
2264 g_slice_free (GITypelib, typelib);
2268 g_typelib_get_namespace (GITypelib *typelib)
2270 return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2275 * @typelib: the typelib
2276 * @symbol_name: name of symbol to be loaded
2277 * @symbol: returns a pointer to the symbol value
2279 * Loads a symbol from #GITypelib.
2281 * Return value: #TRUE on success
2284 g_typelib_symbol (GITypelib *typelib, const char *symbol_name, gpointer *symbol)
2288 _g_typelib_ensure_open (typelib);
2291 * The reason for having multiple modules dates from gir-repository
2292 * when it was desired to inject code (accessors, etc.) into an
2293 * existing library. In that situation, the first module listed
2294 * will be the custom one, which overrides the main one. A bit
2295 * inefficient, but the problem will go away when gir-repository
2298 * For modules with no shared library, we dlopen'd the current
2301 for (l = typelib->modules; l; l = l->next)
2303 GModule *module = l->data;
2305 if (g_module_symbol (module, symbol_name, symbol))