1 /* GObject introspection: typelib validation, auxiliary functions
2 * related to the binary typelib format
4 * Copyright (C) 2005 Matthias Clasen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
32 GSList *context_stack;
35 #define ALIGN_VALUE(this, boundary) \
36 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
39 push_context (ValidateContext *ctx, const char *name)
41 ctx->context_stack = g_slist_prepend (ctx->context_stack, (char*)name);
45 pop_context (ValidateContext *ctx)
47 g_assert (ctx->context_stack != NULL);
48 ctx->context_stack = g_slist_delete_link (ctx->context_stack,
53 validate_interface_blob (ValidateContext *ctx,
58 get_dir_entry_checked (GTypelib *typelib,
62 Header *header = (Header *)typelib->data;
65 if (index == 0 || index > header->n_entries)
69 G_TYPELIB_ERROR_INVALID_BLOB,
70 "Invalid directory index %d", index);
74 offset = header->directory + (index - 1) * header->entry_blob_size;
76 if (typelib->len < offset + sizeof (DirEntry))
80 G_TYPELIB_ERROR_INVALID,
81 "The buffer is too short");
85 return (DirEntry *)&typelib->data[offset];
90 get_blob (GTypelib *typelib,
94 if (typelib->len < offset + sizeof (CommonBlob))
98 G_TYPELIB_ERROR_INVALID,
99 "The buffer is too short");
102 return (CommonBlob *)&typelib->data[offset];
105 static InterfaceTypeBlob *
106 get_type_blob (GTypelib *typelib,
107 SimpleTypeBlob *simple,
110 if (simple->offset == 0)
114 G_TYPELIB_ERROR_INVALID,
115 "Expected blob for type");
119 if (simple->reserved == 0 && simple->reserved2 == 0)
123 G_TYPELIB_ERROR_INVALID,
124 "Expected non-basic type but got %d",
129 return (InterfaceTypeBlob*) get_blob (typelib, simple->offset, error);
133 g_typelib_get_dir_entry (GTypelib *typelib,
136 Header *header = (Header *)typelib->data;
138 return (DirEntry *)&typelib->data[header->directory + (index - 1) * header->entry_blob_size];
142 g_typelib_check_sanity (void)
144 /* Check that struct layout is as we expect */
146 gboolean size_check_ok = TRUE;
148 #define CHECK_SIZE(s,n) \
149 if (sizeof(s) != n) \
151 g_printerr ("sizeof("#s") is expected to be %d but is %"G_GSIZE_FORMAT".\n", \
153 size_check_ok = FALSE; \
156 /* When changing the size of a typelib structure, you are required to update
157 * the hardcoded size here. Do NOT change these to use sizeof(); these
158 * should match whatever is defined in the text specification and serve as
159 * a sanity check on structure modifications.
161 * Everything else in the code however should be using sizeof().
164 CHECK_SIZE (Header, 108);
165 CHECK_SIZE (DirEntry, 12);
166 CHECK_SIZE (SimpleTypeBlob, 4);
167 CHECK_SIZE (ArgBlob, 16);
168 CHECK_SIZE (SignatureBlob, 8);
169 CHECK_SIZE (CommonBlob, 8);
170 CHECK_SIZE (FunctionBlob, 20);
171 CHECK_SIZE (CallbackBlob, 12);
172 CHECK_SIZE (InterfaceTypeBlob, 4);
173 CHECK_SIZE (ArrayTypeBlob, 8);
174 CHECK_SIZE (ParamTypeBlob, 4);
175 CHECK_SIZE (ErrorTypeBlob, 4);
176 CHECK_SIZE (ErrorDomainBlob, 16);
177 CHECK_SIZE (ValueBlob, 12);
178 CHECK_SIZE (FieldBlob, 12);
179 CHECK_SIZE (RegisteredTypeBlob, 16);
180 CHECK_SIZE (StructBlob, 24);
181 CHECK_SIZE (EnumBlob, 20);
182 CHECK_SIZE (PropertyBlob, 12);
183 CHECK_SIZE (SignalBlob, 12);
184 CHECK_SIZE (VFuncBlob, 16);
185 CHECK_SIZE (ObjectBlob, 36);
186 CHECK_SIZE (InterfaceBlob, 28);
187 CHECK_SIZE (ConstantBlob, 20);
188 CHECK_SIZE (AnnotationBlob, 12);
189 CHECK_SIZE (UnionBlob, 32);
192 g_assert (size_check_ok);
197 is_aligned (guint32 offset)
199 return offset == ALIGN_VALUE (offset, 4);
202 #define MAX_NAME_LEN 200
205 get_string (GTypelib *typelib, guint32 offset, GError **error)
207 if (typelib->len < offset)
211 G_TYPELIB_ERROR_INVALID,
212 "Buffer is too short while looking up name");
216 return (const char*)&typelib->data[offset];
220 get_string_nofail (GTypelib *typelib, guint32 offset)
222 const char *ret = get_string (typelib, offset, NULL);
228 validate_name (GTypelib *typelib,
230 const guchar *data, guint32 offset,
235 name = get_string (typelib, offset, error);
239 if (!memchr (name, '\0', MAX_NAME_LEN))
243 G_TYPELIB_ERROR_INVALID,
244 "The %s is too long: %s",
249 if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
253 G_TYPELIB_ERROR_INVALID,
254 "The %s is contains invalid characters: %s",
263 validate_header (ValidateContext *ctx,
266 GTypelib *typelib = ctx->typelib;
269 if (typelib->len < sizeof (Header))
273 G_TYPELIB_ERROR_INVALID,
274 "The buffer is too short");
278 header = (Header *)typelib->data;
280 if (strncmp (header->magic, G_IR_MAGIC, 16) != 0)
284 G_TYPELIB_ERROR_INVALID_HEADER,
285 "Magic string not found");
290 if (header->major_version != 2 || header->minor_version != 0)
294 G_TYPELIB_ERROR_INVALID_HEADER,
300 if (header->n_entries < header->n_local_entries)
304 G_TYPELIB_ERROR_INVALID_HEADER,
305 "Inconsistent entry counts");
309 if (header->size != typelib->len)
313 G_TYPELIB_ERROR_INVALID_HEADER,
314 "Typelib size mismatch");
318 /* This is a sanity check for a specific typelib; it
319 * prevents us from loading an incompatible typelib.
321 * The hardcoded checks in g_typelib_check_sanity to
322 * protect against inadvertent or buggy changes to the typelib format
326 if (header->entry_blob_size != sizeof (DirEntry) ||
327 header->function_blob_size != sizeof (FunctionBlob) ||
328 header->callback_blob_size != sizeof (CallbackBlob) ||
329 header->signal_blob_size != sizeof (SignalBlob) ||
330 header->vfunc_blob_size != sizeof (VFuncBlob) ||
331 header->arg_blob_size != sizeof (ArgBlob) ||
332 header->property_blob_size != sizeof (PropertyBlob) ||
333 header->field_blob_size != sizeof (FieldBlob) ||
334 header->value_blob_size != sizeof (ValueBlob) ||
335 header->constant_blob_size != sizeof (ConstantBlob) ||
336 header->error_domain_blob_size != sizeof (ErrorDomainBlob) ||
337 header->annotation_blob_size != sizeof (AnnotationBlob) ||
338 header->signature_blob_size != sizeof (SignatureBlob) ||
339 header->enum_blob_size != sizeof (EnumBlob) ||
340 header->struct_blob_size != sizeof (StructBlob) ||
341 header->object_blob_size != sizeof(ObjectBlob) ||
342 header->interface_blob_size != sizeof (InterfaceBlob) ||
343 header->union_blob_size != sizeof (UnionBlob))
347 G_TYPELIB_ERROR_INVALID_HEADER,
348 "Blob size mismatch");
352 if (!is_aligned (header->directory))
356 G_TYPELIB_ERROR_INVALID_HEADER,
357 "Misaligned directory");
361 if (!is_aligned (header->annotations))
365 G_TYPELIB_ERROR_INVALID_HEADER,
366 "Misaligned annotations");
370 if (header->annotations == 0 && header->n_annotations > 0)
374 G_TYPELIB_ERROR_INVALID_HEADER,
375 "Wrong number of annotations");
379 if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
385 static gboolean validate_type_blob (GTypelib *typelib,
387 guint32 signature_offset,
388 gboolean return_type,
392 validate_array_type_blob (GTypelib *typelib,
394 guint32 signature_offset,
395 gboolean return_type,
400 blob = (ArrayTypeBlob*)&typelib->data[offset];
406 G_TYPELIB_ERROR_INVALID_BLOB,
407 "Pointer type exected for tag %d", blob->tag);
411 /* FIXME validate length */
413 if (!validate_type_blob (typelib,
414 offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
422 validate_iface_type_blob (GTypelib *typelib,
424 guint32 signature_offset,
425 gboolean return_type,
428 InterfaceTypeBlob *blob;
429 InterfaceBlob *target;
431 blob = (InterfaceTypeBlob*)&typelib->data[offset];
433 target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
437 if (target->blob_type == 0) /* non-local */
444 validate_param_type_blob (GTypelib *typelib,
446 guint32 signature_offset,
447 gboolean return_type,
454 blob = (ParamTypeBlob*)&typelib->data[offset];
460 G_TYPELIB_ERROR_INVALID_BLOB,
461 "Pointer type exected for tag %d", blob->tag);
465 if (blob->n_types != n_params)
469 G_TYPELIB_ERROR_INVALID_BLOB,
470 "Parameter type number mismatch");
474 for (i = 0; i < n_params; i++)
476 if (!validate_type_blob (typelib,
477 offset + sizeof (ParamTypeBlob) +
478 i * sizeof (SimpleTypeBlob),
487 validate_error_type_blob (GTypelib *typelib,
489 guint32 signature_offset,
490 gboolean return_type,
498 blob = (ErrorTypeBlob*)&typelib->data[offset];
500 header = (Header *)typelib->data;
506 G_TYPELIB_ERROR_INVALID_BLOB,
507 "Pointer type exected for tag %d", blob->tag);
511 for (i = 0; i < blob->n_domains; i++)
513 if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
517 G_TYPELIB_ERROR_INVALID_BLOB,
518 "Invalid directory index %d", blob->domains[i]);
522 entry = g_typelib_get_dir_entry (typelib, blob->domains[i]);
524 if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
525 (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
529 G_TYPELIB_ERROR_INVALID_BLOB,
539 validate_type_blob (GTypelib *typelib,
541 guint32 signature_offset,
542 gboolean return_type,
545 SimpleTypeBlob *simple;
546 InterfaceTypeBlob *iface;
548 simple = (SimpleTypeBlob *)&typelib->data[offset];
550 if (simple->reserved == 0 &&
551 simple->reserved2 == 0)
553 if (simple->tag >= GI_TYPE_TAG_ARRAY)
557 G_TYPELIB_ERROR_INVALID_BLOB,
558 "Wrong tag in simple type");
562 if (simple->tag >= GI_TYPE_TAG_UTF8 &&
567 G_TYPELIB_ERROR_INVALID_BLOB,
568 "Pointer type exected for tag %d", simple->tag);
575 iface = (InterfaceTypeBlob*)&typelib->data[simple->offset];
579 case GI_TYPE_TAG_ARRAY:
580 if (!validate_array_type_blob (typelib, simple->offset,
581 signature_offset, return_type, error))
584 case GI_TYPE_TAG_INTERFACE:
585 if (!validate_iface_type_blob (typelib, simple->offset,
586 signature_offset, return_type, error))
589 case GI_TYPE_TAG_GLIST:
590 case GI_TYPE_TAG_GSLIST:
591 if (!validate_param_type_blob (typelib, simple->offset,
592 signature_offset, return_type, 1, error))
595 case GI_TYPE_TAG_GHASH:
596 if (!validate_param_type_blob (typelib, simple->offset,
597 signature_offset, return_type, 2, error))
600 case GI_TYPE_TAG_ERROR:
601 if (!validate_error_type_blob (typelib, simple->offset,
602 signature_offset, return_type, error))
608 G_TYPELIB_ERROR_INVALID_BLOB,
609 "Wrong tag in complex type");
617 validate_arg_blob (GTypelib *typelib,
619 guint32 signature_offset,
624 if (typelib->len < offset + sizeof (ArgBlob))
628 G_TYPELIB_ERROR_INVALID,
629 "The buffer is too short");
633 blob = (ArgBlob*) &typelib->data[offset];
635 if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
638 if (!validate_type_blob (typelib,
639 offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
640 signature_offset, FALSE, error))
646 static SimpleTypeBlob *
647 return_type_from_signature (GTypelib *typelib,
652 if (typelib->len < offset + sizeof (SignatureBlob))
656 G_TYPELIB_ERROR_INVALID,
657 "The buffer is too short");
661 blob = (SignatureBlob*) &typelib->data[offset];
662 if (blob->return_type.offset == 0)
666 G_TYPELIB_ERROR_INVALID,
667 "No return type found in signature");
671 return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
675 validate_signature_blob (GTypelib *typelib,
682 if (typelib->len < offset + sizeof (SignatureBlob))
686 G_TYPELIB_ERROR_INVALID,
687 "The buffer is too short");
691 blob = (SignatureBlob*) &typelib->data[offset];
693 if (blob->return_type.offset != 0)
695 if (!validate_type_blob (typelib,
696 offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
697 offset, TRUE, error))
701 for (i = 0; i < blob->n_arguments; i++)
703 if (!validate_arg_blob (typelib,
704 offset + sizeof (SignatureBlob) +
705 i * sizeof (ArgBlob),
711 /* FIXME check constraints on return_value */
712 /* FIXME check array-length pairs */
717 validate_function_blob (ValidateContext *ctx,
719 guint16 container_type,
722 GTypelib *typelib = ctx->typelib;
724 SignatureBlob *sigblob;
727 if (typelib->len < offset + sizeof (FunctionBlob))
731 G_TYPELIB_ERROR_INVALID,
732 "The buffer is too short");
736 blob = (FunctionBlob*) &typelib->data[offset];
738 if (blob->blob_type != BLOB_TYPE_FUNCTION)
742 G_TYPELIB_ERROR_INVALID_BLOB,
743 "Wrong blob type %d, expected function", blob->blob_type);
747 if (!validate_name (typelib, "function", typelib->data, blob->name, error))
750 push_context (ctx, get_string_nofail (typelib, blob->name));
752 if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
755 switch (container_type)
757 case BLOB_TYPE_BOXED:
758 case BLOB_TYPE_STRUCT:
759 case BLOB_TYPE_UNION:
760 case BLOB_TYPE_OBJECT:
761 case BLOB_TYPE_INTERFACE:
762 is_method = !(blob->constructor || blob->setter || blob->getter || blob->wraps_vfunc);
768 if (blob->constructor)
770 switch (container_type)
772 case BLOB_TYPE_BOXED:
773 case BLOB_TYPE_STRUCT:
774 case BLOB_TYPE_UNION:
775 case BLOB_TYPE_OBJECT:
776 case BLOB_TYPE_INTERFACE:
781 G_TYPELIB_ERROR_INVALID_BLOB,
782 "Constructor not allowed");
787 if (blob->setter || blob->getter || blob->wraps_vfunc)
789 switch (container_type)
791 case BLOB_TYPE_OBJECT:
792 case BLOB_TYPE_INTERFACE:
797 G_TYPELIB_ERROR_INVALID_BLOB,
798 "Setter, getter or wrapper not allowed");
805 if (!(blob->setter || blob->getter || blob->wraps_vfunc))
809 G_TYPELIB_ERROR_INVALID_BLOB,
810 "Must be setter, getter or wrapper");
815 /* FIXME: validate index range */
817 if (!validate_signature_blob (typelib, blob->signature, error))
820 sigblob = (SignatureBlob*) &typelib->data[blob->signature];
822 if (blob->constructor)
824 SimpleTypeBlob *simple = return_type_from_signature (typelib,
827 InterfaceTypeBlob *iface_type;
831 iface_type = get_type_blob (typelib, simple, error);
834 if (!(iface_type->tag == GI_TYPE_TAG_INTERFACE))
838 G_TYPELIB_ERROR_INVALID,
839 "Invalid return type %d for constructor",
851 validate_callback_blob (ValidateContext *ctx,
855 GTypelib *typelib = ctx->typelib;
858 if (typelib->len < offset + sizeof (CallbackBlob))
862 G_TYPELIB_ERROR_INVALID,
863 "The buffer is too short");
867 blob = (CallbackBlob*) &typelib->data[offset];
869 if (blob->blob_type != BLOB_TYPE_CALLBACK)
873 G_TYPELIB_ERROR_INVALID_BLOB,
878 if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
881 push_context (ctx, get_string_nofail (typelib, blob->name));
883 if (!validate_signature_blob (typelib, blob->signature, error))
892 validate_constant_blob (GTypelib *typelib,
896 guint value_size[] = {
927 SimpleTypeBlob *type;
929 if (typelib->len < offset + sizeof (ConstantBlob))
933 G_TYPELIB_ERROR_INVALID,
934 "The buffer is too short");
938 blob = (ConstantBlob*) &typelib->data[offset];
940 if (blob->blob_type != BLOB_TYPE_CONSTANT)
944 G_TYPELIB_ERROR_INVALID_BLOB,
949 if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
952 if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
956 if (!is_aligned (blob->offset))
960 G_TYPELIB_ERROR_INVALID_BLOB,
961 "Misaligned constant value");
965 type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
966 if (type->reserved == 0 && type->reserved2 == 0)
972 G_TYPELIB_ERROR_INVALID_BLOB,
973 "Constant value type void");
977 if (value_size[type->tag] != 0 &&
978 blob->size != value_size[type->tag])
982 G_TYPELIB_ERROR_INVALID_BLOB,
983 "Constant value size mismatch");
986 /* FIXME check string values */
993 validate_value_blob (GTypelib *typelib,
999 if (typelib->len < offset + sizeof (ValueBlob))
1003 G_TYPELIB_ERROR_INVALID,
1004 "The buffer is too short");
1008 blob = (ValueBlob*) &typelib->data[offset];
1010 if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1017 validate_field_blob (GTypelib *typelib,
1023 if (typelib->len < offset + sizeof (FieldBlob))
1027 G_TYPELIB_ERROR_INVALID,
1028 "The buffer is too short");
1032 blob = (FieldBlob*) &typelib->data[offset];
1034 if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1037 if (!validate_type_blob (typelib,
1038 offset + G_STRUCT_OFFSET (FieldBlob, type),
1046 validate_property_blob (GTypelib *typelib,
1052 if (typelib->len < offset + sizeof (PropertyBlob))
1056 G_TYPELIB_ERROR_INVALID,
1057 "The buffer is too short");
1061 blob = (PropertyBlob*) &typelib->data[offset];
1063 if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1066 if (!validate_type_blob (typelib,
1067 offset + G_STRUCT_OFFSET (PropertyBlob, type),
1075 validate_signal_blob (GTypelib *typelib,
1077 guint32 container_offset,
1083 if (typelib->len < offset + sizeof (SignalBlob))
1087 G_TYPELIB_ERROR_INVALID,
1088 "The buffer is too short");
1092 blob = (SignalBlob*) &typelib->data[offset];
1094 if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1097 if ((blob->run_first != 0) +
1098 (blob->run_last != 0) +
1099 (blob->run_cleanup != 0) != 1)
1103 G_TYPELIB_ERROR_INVALID_BLOB,
1104 "Invalid signal run flags");
1108 if (blob->has_class_closure)
1110 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1114 object = (ObjectBlob*)&typelib->data[container_offset];
1116 n_signals = object->n_signals;
1120 InterfaceBlob *iface;
1122 iface = (InterfaceBlob*)&typelib->data[container_offset];
1124 n_signals = iface->n_signals;
1127 if (blob->class_closure >= n_signals)
1131 G_TYPELIB_ERROR_INVALID_BLOB,
1132 "Invalid class closure index");
1137 if (!validate_signature_blob (typelib, blob->signature, error))
1144 validate_vfunc_blob (GTypelib *typelib,
1146 guint32 container_offset,
1152 if (typelib->len < offset + sizeof (VFuncBlob))
1156 G_TYPELIB_ERROR_INVALID,
1157 "The buffer is too short");
1161 blob = (VFuncBlob*) &typelib->data[offset];
1163 if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1166 if (blob->class_closure)
1168 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1172 object = (ObjectBlob*)&typelib->data[container_offset];
1174 n_vfuncs = object->n_vfuncs;
1178 InterfaceBlob *iface;
1180 iface = (InterfaceBlob*)&typelib->data[container_offset];
1182 n_vfuncs = iface->n_vfuncs;
1185 if (blob->class_closure >= n_vfuncs)
1189 G_TYPELIB_ERROR_INVALID_BLOB,
1190 "Invalid class closure index");
1195 if (!validate_signature_blob (typelib, blob->signature, error))
1202 validate_struct_blob (ValidateContext *ctx,
1207 GTypelib *typelib = ctx->typelib;
1211 if (typelib->len < offset + sizeof (StructBlob))
1215 G_TYPELIB_ERROR_INVALID,
1216 "The buffer is too short");
1220 blob = (StructBlob*) &typelib->data[offset];
1222 if (blob->blob_type != blob_type)
1226 G_TYPELIB_ERROR_INVALID_BLOB,
1231 if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1234 push_context (ctx, get_string_nofail (typelib, blob->name));
1236 if (!blob->unregistered)
1238 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1241 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1246 if (blob->gtype_name || blob->gtype_init)
1250 G_TYPELIB_ERROR_INVALID_BLOB,
1251 "Gtype data in struct");
1256 if (typelib->len < offset + sizeof (StructBlob) +
1257 blob->n_fields * sizeof (FieldBlob) +
1258 blob->n_methods * sizeof (FunctionBlob))
1262 G_TYPELIB_ERROR_INVALID,
1263 "The buffer is too short");
1267 for (i = 0; i < blob->n_fields; i++)
1269 if (!validate_field_blob (typelib,
1270 offset + sizeof (StructBlob) +
1271 i * sizeof (FieldBlob),
1276 for (i = 0; i < blob->n_methods; i++)
1278 if (!validate_function_blob (ctx,
1279 offset + sizeof (StructBlob) +
1280 blob->n_fields * sizeof (FieldBlob) +
1281 i * sizeof (FunctionBlob),
1293 validate_enum_blob (ValidateContext *ctx,
1298 GTypelib *typelib = ctx->typelib;
1302 if (typelib->len < offset + sizeof (EnumBlob))
1306 G_TYPELIB_ERROR_INVALID,
1307 "The buffer is too short");
1311 blob = (EnumBlob*) &typelib->data[offset];
1313 if (blob->blob_type != blob_type)
1317 G_TYPELIB_ERROR_INVALID_BLOB,
1322 if (!blob->unregistered)
1324 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1327 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1332 if (blob->gtype_name || blob->gtype_init)
1336 G_TYPELIB_ERROR_INVALID_BLOB,
1337 "Gtype data in unregistered enum");
1342 if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1345 if (typelib->len < offset + sizeof (EnumBlob) +
1346 blob->n_values * sizeof (ValueBlob))
1350 G_TYPELIB_ERROR_INVALID,
1351 "The buffer is too short");
1355 push_context (ctx, get_string_nofail (typelib, blob->name));
1357 for (i = 0; i < blob->n_values; i++)
1359 if (!validate_value_blob (typelib,
1360 offset + sizeof (EnumBlob) +
1361 i * sizeof (ValueBlob),
1366 v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1367 i * sizeof (ValueBlob)];
1368 for (j = 0; j < i; j++)
1370 v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1371 j * sizeof (ValueBlob)];
1373 if (v1->value == v2->value)
1376 /* FIXME should this be an error ? */
1379 G_TYPELIB_ERROR_INVALID_BLOB,
1380 "Duplicate enum value");
1393 validate_object_blob (ValidateContext *ctx,
1397 GTypelib *typelib = ctx->typelib;
1403 header = (Header *)typelib->data;
1405 if (typelib->len < offset + sizeof (ObjectBlob))
1409 G_TYPELIB_ERROR_INVALID,
1410 "The buffer is too short");
1414 blob = (ObjectBlob*) &typelib->data[offset];
1416 if (blob->blob_type != BLOB_TYPE_OBJECT)
1420 G_TYPELIB_ERROR_INVALID_BLOB,
1425 if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1428 if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1431 if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1434 if (blob->parent > header->n_entries)
1438 G_TYPELIB_ERROR_INVALID_BLOB,
1439 "Invalid parent index");
1443 if (blob->parent != 0)
1447 entry = get_dir_entry_checked (typelib, blob->parent, error);
1450 if (entry->blob_type != BLOB_TYPE_OBJECT &&
1451 (entry->local || entry->blob_type != 0))
1455 G_TYPELIB_ERROR_INVALID_BLOB,
1456 "Parent not object");
1461 if (blob->class_struct != 0)
1465 entry = get_dir_entry_checked (typelib, blob->class_struct, error);
1468 if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1472 G_TYPELIB_ERROR_INVALID_BLOB,
1473 "Class struct invalid type or not local");
1478 if (typelib->len < offset + sizeof (ObjectBlob) +
1479 (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1480 blob->n_fields * sizeof (FieldBlob) +
1481 blob->n_properties * sizeof (PropertyBlob) +
1482 blob->n_methods * sizeof (FunctionBlob) +
1483 blob->n_signals * sizeof (SignalBlob) +
1484 blob->n_vfuncs * sizeof (VFuncBlob) +
1485 blob->n_constants * sizeof (ConstantBlob))
1490 G_TYPELIB_ERROR_INVALID,
1491 "The buffer is too short");
1495 offset2 = offset + sizeof (ObjectBlob);
1497 for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1502 iface = *(guint16*)&typelib->data[offset2];
1503 if (iface == 0 || iface > header->n_entries)
1507 G_TYPELIB_ERROR_INVALID_BLOB,
1508 "Invalid interface index");
1512 entry = get_dir_entry_checked (typelib, iface, error);
1516 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1517 (entry->local || entry->blob_type != 0))
1521 G_TYPELIB_ERROR_INVALID_BLOB,
1522 "Not an interface");
1527 offset2 += 2 * (blob->n_interfaces %2);
1529 push_context (ctx, get_string_nofail (typelib, blob->name));
1531 for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1533 if (!validate_field_blob (typelib, offset2, error))
1537 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1539 if (!validate_property_blob (typelib, offset2, error))
1543 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1545 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1549 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1551 if (!validate_signal_blob (typelib, offset2, offset, error))
1555 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1557 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1561 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1563 if (!validate_constant_blob (typelib, offset2, error))
1573 validate_interface_blob (ValidateContext *ctx,
1577 GTypelib *typelib = ctx->typelib;
1579 InterfaceBlob *blob;
1583 header = (Header *)typelib->data;
1585 if (typelib->len < offset + sizeof (InterfaceBlob))
1589 G_TYPELIB_ERROR_INVALID,
1590 "The buffer is too short");
1594 blob = (InterfaceBlob*) &typelib->data[offset];
1596 if (blob->blob_type != BLOB_TYPE_INTERFACE)
1600 G_TYPELIB_ERROR_INVALID_BLOB,
1601 "Wrong blob type; expected interface, got %d", blob->blob_type);
1605 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1608 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1611 if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1614 if (typelib->len < offset + sizeof (InterfaceBlob) +
1615 (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1616 blob->n_properties * sizeof (PropertyBlob) +
1617 blob->n_methods * sizeof (FunctionBlob) +
1618 blob->n_signals * sizeof (SignalBlob) +
1619 blob->n_vfuncs * sizeof (VFuncBlob) +
1620 blob->n_constants * sizeof (ConstantBlob))
1625 G_TYPELIB_ERROR_INVALID,
1626 "The buffer is too short");
1630 offset2 = offset + sizeof (InterfaceBlob);
1632 for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1637 req = *(guint16*)&typelib->data[offset2];
1638 if (req == 0 || req > header->n_entries)
1642 G_TYPELIB_ERROR_INVALID_BLOB,
1643 "Invalid prerequisite index");
1647 entry = g_typelib_get_dir_entry (typelib, req);
1648 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1649 entry->blob_type != BLOB_TYPE_OBJECT &&
1650 (entry->local || entry->blob_type != 0))
1654 G_TYPELIB_ERROR_INVALID_BLOB,
1655 "Not an interface or object");
1660 offset2 += 2 * (blob->n_prerequisites % 2);
1662 push_context (ctx, get_string_nofail (typelib, blob->name));
1664 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1666 if (!validate_property_blob (typelib, offset2, error))
1670 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1672 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1676 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1678 if (!validate_signal_blob (typelib, offset2, offset, error))
1682 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1684 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1688 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1690 if (!validate_constant_blob (typelib, offset2, error))
1700 validate_errordomain_blob (GTypelib *typelib,
1708 validate_union_blob (GTypelib *typelib,
1716 validate_blob (ValidateContext *ctx,
1720 GTypelib *typelib = ctx->typelib;
1723 if (typelib->len < offset + sizeof (CommonBlob))
1727 G_TYPELIB_ERROR_INVALID,
1728 "The buffer is too short");
1732 common = (CommonBlob*)&typelib->data[offset];
1734 switch (common->blob_type)
1736 case BLOB_TYPE_FUNCTION:
1737 if (!validate_function_blob (ctx, offset, 0, error))
1740 case BLOB_TYPE_CALLBACK:
1741 if (!validate_callback_blob (ctx, offset, error))
1744 case BLOB_TYPE_STRUCT:
1745 case BLOB_TYPE_BOXED:
1746 if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1749 case BLOB_TYPE_ENUM:
1750 case BLOB_TYPE_FLAGS:
1751 if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1754 case BLOB_TYPE_OBJECT:
1755 if (!validate_object_blob (ctx, offset, error))
1758 case BLOB_TYPE_INTERFACE:
1759 if (!validate_interface_blob (ctx, offset, error))
1762 case BLOB_TYPE_CONSTANT:
1763 if (!validate_constant_blob (typelib, offset, error))
1766 case BLOB_TYPE_ERROR_DOMAIN:
1767 if (!validate_errordomain_blob (typelib, offset, error))
1770 case BLOB_TYPE_UNION:
1771 if (!validate_union_blob (typelib, offset, error))
1777 G_TYPELIB_ERROR_INVALID_ENTRY,
1778 "Invalid blob type");
1786 validate_directory (ValidateContext *ctx,
1789 GTypelib *typelib = ctx->typelib;
1790 Header *header = (Header *)typelib->data;
1794 if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1798 G_TYPELIB_ERROR_INVALID,
1799 "The buffer is too short");
1803 for (i = 0; i < header->n_entries; i++)
1805 entry = g_typelib_get_dir_entry (typelib, i + 1);
1807 if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1810 if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1811 entry->blob_type > BLOB_TYPE_UNION)
1815 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1816 "Invalid entry type");
1820 if (i < header->n_local_entries)
1826 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1827 "Too few local directory entries");
1831 if (!is_aligned (entry->offset))
1835 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1836 "Misaligned entry");
1840 if (!validate_blob (ctx, entry->offset, error))
1849 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1850 "Too many local directory entries");
1854 if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1863 validate_annotations (ValidateContext *ctx,
1866 GTypelib *typelib = ctx->typelib;
1867 Header *header = (Header *)typelib->data;
1869 if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
1873 G_TYPELIB_ERROR_INVALID,
1874 "The buffer is too short");
1882 prefix_with_context (GError **error,
1883 const char *section,
1884 ValidateContext *ctx)
1886 GString *str = g_string_new (NULL);
1890 link = ctx->context_stack;
1893 g_prefix_error (error, "In %s:", section);
1897 for (; link; link = link->next)
1899 g_string_append (str, link->data);
1901 g_string_append_c (str, '/');
1903 g_string_append_c (str, ')');
1904 buf = g_string_free (str, FALSE);
1905 g_prefix_error (error, "In %s (Context: %s): ", section, buf);
1910 g_typelib_validate (GTypelib *typelib,
1913 ValidateContext ctx;
1914 ctx.typelib = typelib;
1915 ctx.context_stack = NULL;
1917 if (!validate_header (&ctx, error))
1919 prefix_with_context (error, "In header", &ctx);
1923 if (!validate_directory (&ctx, error))
1925 prefix_with_context (error, "directory", &ctx);
1929 if (!validate_annotations (&ctx, error))
1931 prefix_with_context (error, "annotations", &ctx);
1939 g_typelib_error_quark (void)
1941 static GQuark quark = 0;
1943 quark = g_quark_from_static_string ("g-typelib-error-quark");
1948 _g_typelib_init (GTypelib *typelib)
1952 header = (Header *) typelib->data;
1953 if (header->shared_library)
1955 const gchar *shlib_str;
1956 GModule *app_module = NULL;
1958 shlib_str = g_typelib_get_string (typelib, header->shared_library);
1959 /* note that NULL shlib means to open the main app, which is allowed */
1961 if (shlib_str != NULL)
1966 /* shared-library is a comma-separated list of libraries */
1967 shlibs = g_strsplit (shlib_str, ",", 0);
1969 /* We load all passed libs unconditionally as if the same library is loaded
1970 * again with dlopen(), the same file handle will be returned. See bug:
1971 * http://bugzilla.gnome.org/show_bug.cgi?id=555294
1973 for (i = 0; shlibs[i]; i++)
1977 /* Glade's autoconnect feature and OpenGL's extension mechanism
1978 * as used by Clutter rely on dlopen(NULL) to work as a means of
1979 * accessing the app's symbols. This keeps us from using
1980 * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
1981 * in general libraries are not expecting multiple copies of
1982 * themselves and are not expecting to be unloaded. So we just
1983 * load modules globally for now.
1986 module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
1990 GString *shlib_full = g_string_new (shlibs[i]);
1992 /* Prefix with "lib", try both .la and .so */
1993 if (!g_str_has_prefix (shlib_full->str, "lib"))
1994 g_string_prepend (shlib_full, "lib");
1995 g_string_append (shlib_full, ".la");
1996 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
1998 g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
1999 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2001 g_string_free (shlib_full, TRUE);
2006 g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2007 shlibs[i], g_module_error ());
2011 typelib->modules = g_list_append (typelib->modules, module);
2015 g_strfreev (shlibs);
2018 /* we should make sure the app_module in the end of list so that
2019 * it's last symbol source when loading any symbols from modules.
2020 * See comments in g_typelib_symbol */
2021 app_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
2023 typelib->modules = g_list_append (typelib->modules, app_module);
2028 * g_typelib_new_from_memory:
2029 * @memory: address of memory chunk containing the typelib
2030 * @len: length of memory chunk containing the typelib
2032 * Creates a new #GTypelib from a memory location. The memory block
2033 * pointed to by @typelib will be automatically g_free()d when the
2034 * repository is destroyed.
2036 * Return value: the new #GTypelib
2039 g_typelib_new_from_memory (guchar *memory, gsize len)
2043 meta = g_new0 (GTypelib, 1);
2044 meta->data = memory;
2046 meta->owns_memory = TRUE;
2047 meta->modules = NULL;
2048 _g_typelib_init (meta);
2053 * g_typelib_new_from_const_memory:
2054 * @memory: address of memory chunk containing the typelib
2055 * @len: length of memory chunk containing the typelib
2057 * Creates a new #GTypelib from a memory location.
2059 * Return value: the new #GTypelib
2062 g_typelib_new_from_const_memory (const guchar *memory, gsize len)
2066 meta = g_new0 (GTypelib, 1);
2067 meta->data = (guchar *) memory;
2069 meta->owns_memory = FALSE;
2070 meta->modules = NULL;
2071 _g_typelib_init (meta);
2076 * g_typelib_new_from_mapped_file:
2077 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2079 * Creates a new #GTypelib from a #GMappedFile.
2081 * Return value: the new #GTypelib
2084 g_typelib_new_from_mapped_file (GMappedFile *mfile)
2088 meta = g_new0 (GTypelib, 1);
2089 meta->mfile = mfile;
2090 meta->owns_memory = FALSE;
2091 meta->data = (guchar *) g_mapped_file_get_contents (mfile);
2092 meta->len = g_mapped_file_get_length (mfile);
2093 _g_typelib_init (meta);
2099 * @typelib: a #GTypelib
2104 g_typelib_free (GTypelib *typelib)
2107 g_mapped_file_free (typelib->mfile);
2109 if (typelib->owns_memory)
2110 g_free (typelib->data);
2111 if (typelib->modules)
2113 g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2114 g_list_free (typelib->modules);
2120 g_typelib_get_namespace (GTypelib *typelib)
2122 return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2127 * @typelib: the typelib
2128 * @symbol_name: name of symbol to be loaded
2129 * @symbol: returns a pointer to the symbol value
2131 * Loads a symbol from #GTypelib.
2133 * Return value: #TRUE on success
2136 g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
2141 * We want to be able to add symbols to an app or an auxiliary
2142 * library to fill in gaps in an introspected library. However,
2143 * normally we would only look for symbols in the main library
2144 * (the first items in typelib->modules).
2146 * A more elaborate solution is probably possible, but as a
2147 * simple approach for now, if we fail to find a symbol we look
2148 * for it in the global module (the last item in type->modules).
2150 * This would not be very efficient if it happened often, since
2151 * we always do the failed lookup above first, but very few
2152 * symbols should be outside of the main libraries in
2153 * typelib->modules so it doesn't matter.
2155 for (l = typelib->modules; l; l = l->next)
2157 GModule *module = l->data;
2159 if (g_module_symbol (module, symbol_name, symbol))