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->flags.reserved == 0 && simple->flags.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, 112);
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, 16);
179 CHECK_SIZE (RegisteredTypeBlob, 16);
180 CHECK_SIZE (StructBlob, 32);
181 CHECK_SIZE (EnumBlob, 24);
182 CHECK_SIZE (PropertyBlob, 16);
183 CHECK_SIZE (SignalBlob, 16);
184 CHECK_SIZE (VFuncBlob, 20);
185 CHECK_SIZE (ObjectBlob, 44);
186 CHECK_SIZE (InterfaceBlob, 40);
187 CHECK_SIZE (ConstantBlob, 24);
188 CHECK_SIZE (AttributeBlob, 12);
189 CHECK_SIZE (UnionBlob, 40);
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 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->attribute_blob_size != sizeof (AttributeBlob) ||
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->attributes))
365 G_TYPELIB_ERROR_INVALID_HEADER,
366 "Misaligned attributes");
370 if (header->attributes == 0 && header->n_attributes > 0)
374 G_TYPELIB_ERROR_INVALID_HEADER,
375 "Wrong number of attributes");
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->flags.reserved == 0 &&
551 simple->flags.reserved2 == 0)
553 if (simple->flags.tag >= GI_TYPE_TAG_ARRAY)
557 G_TYPELIB_ERROR_INVALID_BLOB,
558 "Wrong tag in simple type");
562 if (simple->flags.tag >= GI_TYPE_TAG_UTF8 &&
563 !simple->flags.pointer)
567 G_TYPELIB_ERROR_INVALID_BLOB,
568 "Pointer type exected for tag %d", simple->flags.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[] = {
929 SimpleTypeBlob *type;
931 if (typelib->len < offset + sizeof (ConstantBlob))
935 G_TYPELIB_ERROR_INVALID,
936 "The buffer is too short");
940 blob = (ConstantBlob*) &typelib->data[offset];
942 if (blob->blob_type != BLOB_TYPE_CONSTANT)
946 G_TYPELIB_ERROR_INVALID_BLOB,
951 if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
954 if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
958 if (!is_aligned (blob->offset))
962 G_TYPELIB_ERROR_INVALID_BLOB,
963 "Misaligned constant value");
967 type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
968 if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
970 if (type->flags.tag == 0)
974 G_TYPELIB_ERROR_INVALID_BLOB,
975 "Constant value type void");
979 if (value_size[type->flags.tag] != 0 &&
980 blob->size != value_size[type->flags.tag])
984 G_TYPELIB_ERROR_INVALID_BLOB,
985 "Constant value size mismatch");
988 /* FIXME check string values */
995 validate_value_blob (GTypelib *typelib,
1001 if (typelib->len < offset + sizeof (ValueBlob))
1005 G_TYPELIB_ERROR_INVALID,
1006 "The buffer is too short");
1010 blob = (ValueBlob*) &typelib->data[offset];
1012 if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1019 validate_field_blob (ValidateContext *ctx,
1023 GTypelib *typelib = ctx->typelib;
1024 Header *header = (Header *)typelib->data;
1027 if (typelib->len < offset + sizeof (FieldBlob))
1031 G_TYPELIB_ERROR_INVALID,
1032 "The buffer is too short");
1036 blob = (FieldBlob*) &typelib->data[offset];
1038 if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1041 if (blob->has_embedded_type)
1043 if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
1046 else if (!validate_type_blob (typelib,
1047 offset + G_STRUCT_OFFSET (FieldBlob, type),
1055 validate_property_blob (GTypelib *typelib,
1061 if (typelib->len < offset + sizeof (PropertyBlob))
1065 G_TYPELIB_ERROR_INVALID,
1066 "The buffer is too short");
1070 blob = (PropertyBlob*) &typelib->data[offset];
1072 if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1075 if (!validate_type_blob (typelib,
1076 offset + G_STRUCT_OFFSET (PropertyBlob, type),
1084 validate_signal_blob (GTypelib *typelib,
1086 guint32 container_offset,
1092 if (typelib->len < offset + sizeof (SignalBlob))
1096 G_TYPELIB_ERROR_INVALID,
1097 "The buffer is too short");
1101 blob = (SignalBlob*) &typelib->data[offset];
1103 if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1106 if ((blob->run_first != 0) +
1107 (blob->run_last != 0) +
1108 (blob->run_cleanup != 0) != 1)
1112 G_TYPELIB_ERROR_INVALID_BLOB,
1113 "Invalid signal run flags");
1117 if (blob->has_class_closure)
1119 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1123 object = (ObjectBlob*)&typelib->data[container_offset];
1125 n_signals = object->n_signals;
1129 InterfaceBlob *iface;
1131 iface = (InterfaceBlob*)&typelib->data[container_offset];
1133 n_signals = iface->n_signals;
1136 if (blob->class_closure >= n_signals)
1140 G_TYPELIB_ERROR_INVALID_BLOB,
1141 "Invalid class closure index");
1146 if (!validate_signature_blob (typelib, blob->signature, error))
1153 validate_vfunc_blob (GTypelib *typelib,
1155 guint32 container_offset,
1161 if (typelib->len < offset + sizeof (VFuncBlob))
1165 G_TYPELIB_ERROR_INVALID,
1166 "The buffer is too short");
1170 blob = (VFuncBlob*) &typelib->data[offset];
1172 if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1175 if (blob->class_closure)
1177 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1181 object = (ObjectBlob*)&typelib->data[container_offset];
1183 n_vfuncs = object->n_vfuncs;
1187 InterfaceBlob *iface;
1189 iface = (InterfaceBlob*)&typelib->data[container_offset];
1191 n_vfuncs = iface->n_vfuncs;
1194 if (blob->class_closure >= n_vfuncs)
1198 G_TYPELIB_ERROR_INVALID_BLOB,
1199 "Invalid class closure index");
1204 if (!validate_signature_blob (typelib, blob->signature, error))
1211 validate_struct_blob (ValidateContext *ctx,
1216 GTypelib *typelib = ctx->typelib;
1219 guint32 field_offset;
1221 if (typelib->len < offset + sizeof (StructBlob))
1225 G_TYPELIB_ERROR_INVALID,
1226 "The buffer is too short");
1230 blob = (StructBlob*) &typelib->data[offset];
1232 if (blob->blob_type != blob_type)
1236 G_TYPELIB_ERROR_INVALID_BLOB,
1241 if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1244 push_context (ctx, get_string_nofail (typelib, blob->name));
1246 if (!blob->unregistered)
1248 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1251 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1256 if (blob->gtype_name || blob->gtype_init)
1260 G_TYPELIB_ERROR_INVALID_BLOB,
1261 "Gtype data in struct");
1266 if (typelib->len < offset + sizeof (StructBlob) +
1267 blob->n_fields * sizeof (FieldBlob) +
1268 blob->n_methods * sizeof (FunctionBlob))
1272 G_TYPELIB_ERROR_INVALID,
1273 "The buffer is too short");
1277 field_offset = offset + sizeof (StructBlob);
1278 for (i = 0; i < blob->n_fields; i++)
1280 FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
1282 if (!validate_field_blob (ctx,
1287 field_offset += sizeof (FieldBlob);
1288 if (blob->has_embedded_type)
1289 field_offset += sizeof (CallbackBlob);
1292 for (i = 0; i < blob->n_methods; i++)
1294 if (!validate_function_blob (ctx,
1296 i * sizeof (FunctionBlob),
1308 validate_enum_blob (ValidateContext *ctx,
1313 GTypelib *typelib = ctx->typelib;
1317 if (typelib->len < offset + sizeof (EnumBlob))
1321 G_TYPELIB_ERROR_INVALID,
1322 "The buffer is too short");
1326 blob = (EnumBlob*) &typelib->data[offset];
1328 if (blob->blob_type != blob_type)
1332 G_TYPELIB_ERROR_INVALID_BLOB,
1337 if (!blob->unregistered)
1339 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1342 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1347 if (blob->gtype_name || blob->gtype_init)
1351 G_TYPELIB_ERROR_INVALID_BLOB,
1352 "Gtype data in unregistered enum");
1357 if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1360 if (typelib->len < offset + sizeof (EnumBlob) +
1361 blob->n_values * sizeof (ValueBlob))
1365 G_TYPELIB_ERROR_INVALID,
1366 "The buffer is too short");
1370 push_context (ctx, get_string_nofail (typelib, blob->name));
1372 for (i = 0; i < blob->n_values; i++)
1374 if (!validate_value_blob (typelib,
1375 offset + sizeof (EnumBlob) +
1376 i * sizeof (ValueBlob),
1381 v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1382 i * sizeof (ValueBlob)];
1383 for (j = 0; j < i; j++)
1385 v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1386 j * sizeof (ValueBlob)];
1388 if (v1->value == v2->value)
1391 /* FIXME should this be an error ? */
1394 G_TYPELIB_ERROR_INVALID_BLOB,
1395 "Duplicate enum value");
1408 validate_object_blob (ValidateContext *ctx,
1412 GTypelib *typelib = ctx->typelib;
1418 header = (Header *)typelib->data;
1420 if (typelib->len < offset + sizeof (ObjectBlob))
1424 G_TYPELIB_ERROR_INVALID,
1425 "The buffer is too short");
1429 blob = (ObjectBlob*) &typelib->data[offset];
1431 if (blob->blob_type != BLOB_TYPE_OBJECT)
1435 G_TYPELIB_ERROR_INVALID_BLOB,
1440 if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1443 if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1446 if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1449 if (blob->parent > header->n_entries)
1453 G_TYPELIB_ERROR_INVALID_BLOB,
1454 "Invalid parent index");
1458 if (blob->parent != 0)
1462 entry = get_dir_entry_checked (typelib, blob->parent, error);
1465 if (entry->blob_type != BLOB_TYPE_OBJECT &&
1466 (entry->local || entry->blob_type != 0))
1470 G_TYPELIB_ERROR_INVALID_BLOB,
1471 "Parent not object");
1476 if (blob->gtype_struct != 0)
1480 entry = get_dir_entry_checked (typelib, blob->gtype_struct, error);
1483 if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1487 G_TYPELIB_ERROR_INVALID_BLOB,
1488 "Class struct invalid type or not local");
1493 if (typelib->len < offset + sizeof (ObjectBlob) +
1494 (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1495 blob->n_fields * sizeof (FieldBlob) +
1496 blob->n_properties * sizeof (PropertyBlob) +
1497 blob->n_methods * sizeof (FunctionBlob) +
1498 blob->n_signals * sizeof (SignalBlob) +
1499 blob->n_vfuncs * sizeof (VFuncBlob) +
1500 blob->n_constants * sizeof (ConstantBlob))
1505 G_TYPELIB_ERROR_INVALID,
1506 "The buffer is too short");
1510 offset2 = offset + sizeof (ObjectBlob);
1512 for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1517 iface = *(guint16*)&typelib->data[offset2];
1518 if (iface == 0 || iface > header->n_entries)
1522 G_TYPELIB_ERROR_INVALID_BLOB,
1523 "Invalid interface index");
1527 entry = get_dir_entry_checked (typelib, iface, error);
1531 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1532 (entry->local || entry->blob_type != 0))
1536 G_TYPELIB_ERROR_INVALID_BLOB,
1537 "Not an interface");
1542 offset2 += 2 * (blob->n_interfaces %2);
1544 push_context (ctx, get_string_nofail (typelib, blob->name));
1546 for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1548 if (!validate_field_blob (ctx, offset2, error))
1552 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1554 if (!validate_property_blob (typelib, offset2, error))
1558 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1560 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1564 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1566 if (!validate_signal_blob (typelib, offset2, offset, error))
1570 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1572 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1576 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1578 if (!validate_constant_blob (typelib, offset2, error))
1588 validate_interface_blob (ValidateContext *ctx,
1592 GTypelib *typelib = ctx->typelib;
1594 InterfaceBlob *blob;
1598 header = (Header *)typelib->data;
1600 if (typelib->len < offset + sizeof (InterfaceBlob))
1604 G_TYPELIB_ERROR_INVALID,
1605 "The buffer is too short");
1609 blob = (InterfaceBlob*) &typelib->data[offset];
1611 if (blob->blob_type != BLOB_TYPE_INTERFACE)
1615 G_TYPELIB_ERROR_INVALID_BLOB,
1616 "Wrong blob type; expected interface, got %d", blob->blob_type);
1620 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1623 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1626 if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1629 if (typelib->len < offset + sizeof (InterfaceBlob) +
1630 (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1631 blob->n_properties * sizeof (PropertyBlob) +
1632 blob->n_methods * sizeof (FunctionBlob) +
1633 blob->n_signals * sizeof (SignalBlob) +
1634 blob->n_vfuncs * sizeof (VFuncBlob) +
1635 blob->n_constants * sizeof (ConstantBlob))
1640 G_TYPELIB_ERROR_INVALID,
1641 "The buffer is too short");
1645 offset2 = offset + sizeof (InterfaceBlob);
1647 for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1652 req = *(guint16*)&typelib->data[offset2];
1653 if (req == 0 || req > header->n_entries)
1657 G_TYPELIB_ERROR_INVALID_BLOB,
1658 "Invalid prerequisite index");
1662 entry = g_typelib_get_dir_entry (typelib, req);
1663 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1664 entry->blob_type != BLOB_TYPE_OBJECT &&
1665 (entry->local || entry->blob_type != 0))
1669 G_TYPELIB_ERROR_INVALID_BLOB,
1670 "Not an interface or object");
1675 offset2 += 2 * (blob->n_prerequisites % 2);
1677 push_context (ctx, get_string_nofail (typelib, blob->name));
1679 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1681 if (!validate_property_blob (typelib, offset2, error))
1685 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1687 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1691 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1693 if (!validate_signal_blob (typelib, offset2, offset, error))
1697 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1699 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1703 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1705 if (!validate_constant_blob (typelib, offset2, error))
1715 validate_errordomain_blob (GTypelib *typelib,
1723 validate_union_blob (GTypelib *typelib,
1731 validate_blob (ValidateContext *ctx,
1735 GTypelib *typelib = ctx->typelib;
1738 if (typelib->len < offset + sizeof (CommonBlob))
1742 G_TYPELIB_ERROR_INVALID,
1743 "The buffer is too short");
1747 common = (CommonBlob*)&typelib->data[offset];
1749 switch (common->blob_type)
1751 case BLOB_TYPE_FUNCTION:
1752 if (!validate_function_blob (ctx, offset, 0, error))
1755 case BLOB_TYPE_CALLBACK:
1756 if (!validate_callback_blob (ctx, offset, error))
1759 case BLOB_TYPE_STRUCT:
1760 case BLOB_TYPE_BOXED:
1761 if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1764 case BLOB_TYPE_ENUM:
1765 case BLOB_TYPE_FLAGS:
1766 if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1769 case BLOB_TYPE_OBJECT:
1770 if (!validate_object_blob (ctx, offset, error))
1773 case BLOB_TYPE_INTERFACE:
1774 if (!validate_interface_blob (ctx, offset, error))
1777 case BLOB_TYPE_CONSTANT:
1778 if (!validate_constant_blob (typelib, offset, error))
1781 case BLOB_TYPE_ERROR_DOMAIN:
1782 if (!validate_errordomain_blob (typelib, offset, error))
1785 case BLOB_TYPE_UNION:
1786 if (!validate_union_blob (typelib, offset, error))
1792 G_TYPELIB_ERROR_INVALID_ENTRY,
1793 "Invalid blob type");
1801 validate_directory (ValidateContext *ctx,
1804 GTypelib *typelib = ctx->typelib;
1805 Header *header = (Header *)typelib->data;
1809 if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1813 G_TYPELIB_ERROR_INVALID,
1814 "The buffer is too short");
1818 for (i = 0; i < header->n_entries; i++)
1820 entry = g_typelib_get_dir_entry (typelib, i + 1);
1822 if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1825 if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1826 entry->blob_type > BLOB_TYPE_UNION)
1830 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1831 "Invalid entry type");
1835 if (i < header->n_local_entries)
1841 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1842 "Too few local directory entries");
1846 if (!is_aligned (entry->offset))
1850 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1851 "Misaligned entry");
1855 if (!validate_blob (ctx, entry->offset, error))
1864 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1865 "Too many local directory entries");
1869 if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1878 validate_attributes (ValidateContext *ctx,
1881 GTypelib *typelib = ctx->typelib;
1882 Header *header = (Header *)typelib->data;
1884 if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
1888 G_TYPELIB_ERROR_INVALID,
1889 "The buffer is too short");
1897 prefix_with_context (GError **error,
1898 const char *section,
1899 ValidateContext *ctx)
1901 GString *str = g_string_new (NULL);
1905 link = ctx->context_stack;
1908 g_prefix_error (error, "In %s:", section);
1912 for (; link; link = link->next)
1914 g_string_append (str, link->data);
1916 g_string_append_c (str, '/');
1918 g_string_append_c (str, ')');
1919 buf = g_string_free (str, FALSE);
1920 g_prefix_error (error, "In %s (Context: %s): ", section, buf);
1925 g_typelib_validate (GTypelib *typelib,
1928 ValidateContext ctx;
1929 ctx.typelib = typelib;
1930 ctx.context_stack = NULL;
1932 if (!validate_header (&ctx, error))
1934 prefix_with_context (error, "In header", &ctx);
1938 if (!validate_directory (&ctx, error))
1940 prefix_with_context (error, "directory", &ctx);
1944 if (!validate_attributes (&ctx, error))
1946 prefix_with_context (error, "attributes", &ctx);
1954 g_typelib_error_quark (void)
1956 static GQuark quark = 0;
1958 quark = g_quark_from_static_string ("g-typelib-error-quark");
1963 _g_typelib_do_dlopen (GTypelib *typelib)
1966 const char *shlib_str;
1968 header = (Header *) typelib->data;
1969 /* note that NULL shlib means to open the main app, which is allowed */
1970 if (header->shared_library)
1971 shlib_str = g_typelib_get_string (typelib, header->shared_library);
1975 if (shlib_str != NULL && shlib_str[0] != '\0')
1980 /* shared-library is a comma-separated list of libraries */
1981 shlibs = g_strsplit (shlib_str, ",", 0);
1983 /* We load all passed libs unconditionally as if the same library is loaded
1984 * again with dlopen(), the same file handle will be returned. See bug:
1985 * http://bugzilla.gnome.org/show_bug.cgi?id=555294
1987 for (i = 0; shlibs[i]; i++)
1991 /* Glade's autoconnect feature and OpenGL's extension mechanism
1992 * as used by Clutter rely on dlopen(NULL) to work as a means of
1993 * accessing the app's symbols. This keeps us from using
1994 * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
1995 * in general libraries are not expecting multiple copies of
1996 * themselves and are not expecting to be unloaded. So we just
1997 * load modules globally for now.
2000 module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
2004 GString *shlib_full = g_string_new (shlibs[i]);
2006 /* Prefix with "lib", try both .la and .so */
2007 if (!g_str_has_prefix (shlib_full->str, "lib"))
2008 g_string_prepend (shlib_full, "lib");
2009 g_string_append (shlib_full, ".la");
2010 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2013 g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
2014 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2017 g_string_free (shlib_full, TRUE);
2022 g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2023 shlibs[i], g_module_error ());
2027 typelib->modules = g_list_append (typelib->modules, module);
2031 g_strfreev (shlibs);
2035 /* If there's no shared-library entry for this module, assume that
2036 * the module is for the application. Some of the hand-written .gir files
2037 * in gobject-introspection don't have shared-library entries, but no one
2038 * is really going to be calling g_module_symbol on them either.
2040 GModule *module = g_module_open (NULL, 0);
2042 g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
2044 typelib->modules = g_list_prepend (typelib->modules, module);
2049 _g_typelib_ensure_open (GTypelib *typelib)
2051 if (typelib->open_attempted)
2053 typelib->open_attempted = TRUE;
2054 _g_typelib_do_dlopen (typelib);
2058 * g_typelib_new_from_memory:
2059 * @memory: address of memory chunk containing the typelib
2060 * @len: length of memory chunk containing the typelib
2062 * Creates a new #GTypelib from a memory location. The memory block
2063 * pointed to by @typelib will be automatically g_free()d when the
2064 * repository is destroyed.
2066 * Return value: the new #GTypelib
2069 g_typelib_new_from_memory (guchar *memory, gsize len)
2073 meta = g_new0 (GTypelib, 1);
2074 meta->data = memory;
2076 meta->owns_memory = TRUE;
2077 meta->modules = NULL;
2083 * g_typelib_new_from_const_memory:
2084 * @memory: address of memory chunk containing the typelib
2085 * @len: length of memory chunk containing the typelib
2087 * Creates a new #GTypelib from a memory location.
2089 * Return value: the new #GTypelib
2092 g_typelib_new_from_const_memory (const guchar *memory, gsize len)
2096 meta = g_new0 (GTypelib, 1);
2097 meta->data = (guchar *) memory;
2099 meta->owns_memory = FALSE;
2100 meta->modules = NULL;
2106 * g_typelib_new_from_mapped_file:
2107 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2109 * Creates a new #GTypelib from a #GMappedFile.
2111 * Return value: the new #GTypelib
2114 g_typelib_new_from_mapped_file (GMappedFile *mfile)
2118 meta = g_new0 (GTypelib, 1);
2119 meta->mfile = mfile;
2120 meta->owns_memory = FALSE;
2121 meta->data = (guchar *) g_mapped_file_get_contents (mfile);
2122 meta->len = g_mapped_file_get_length (mfile);
2129 * @typelib: a #GTypelib
2134 g_typelib_free (GTypelib *typelib)
2137 g_mapped_file_free (typelib->mfile);
2139 if (typelib->owns_memory)
2140 g_free (typelib->data);
2141 if (typelib->modules)
2143 g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2144 g_list_free (typelib->modules);
2150 g_typelib_get_namespace (GTypelib *typelib)
2152 return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2157 * @typelib: the typelib
2158 * @symbol_name: name of symbol to be loaded
2159 * @symbol: returns a pointer to the symbol value
2161 * Loads a symbol from #GTypelib.
2163 * Return value: #TRUE on success
2166 g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
2170 _g_typelib_ensure_open (typelib);
2173 * The reason for having multiple modules dates from gir-repository
2174 * when it was desired to inject code (accessors, etc.) into an
2175 * existing library. In that situation, the first module listed
2176 * will be the custom one, which overrides the main one. A bit
2177 * inefficient, but the problem will go away when gir-repository
2180 * For modules with no shared library, we dlopen'd the current
2183 for (l = typelib->modules; l; l = l->next)
2185 GModule *module = l->data;
2187 if (g_module_symbol (module, symbol_name, symbol))