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.
29 #include "glib-compat.h"
33 GSList *context_stack;
36 #define ALIGN_VALUE(this, boundary) \
37 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
40 push_context (ValidateContext *ctx, const char *name)
42 ctx->context_stack = g_slist_prepend (ctx->context_stack, (char*)name);
46 pop_context (ValidateContext *ctx)
48 g_assert (ctx->context_stack != NULL);
49 ctx->context_stack = g_slist_delete_link (ctx->context_stack,
54 validate_interface_blob (ValidateContext *ctx,
59 get_dir_entry_checked (GTypelib *typelib,
63 Header *header = (Header *)typelib->data;
66 if (index == 0 || index > header->n_entries)
70 G_TYPELIB_ERROR_INVALID_BLOB,
71 "Invalid directory index %d", index);
75 offset = header->directory + (index - 1) * header->entry_blob_size;
77 if (typelib->len < offset + sizeof (DirEntry))
81 G_TYPELIB_ERROR_INVALID,
82 "The buffer is too short");
86 return (DirEntry *)&typelib->data[offset];
91 get_blob (GTypelib *typelib,
95 if (typelib->len < offset + sizeof (CommonBlob))
99 G_TYPELIB_ERROR_INVALID,
100 "The buffer is too short");
103 return (CommonBlob *)&typelib->data[offset];
106 static InterfaceTypeBlob *
107 get_type_blob (GTypelib *typelib,
108 SimpleTypeBlob *simple,
111 if (simple->offset == 0)
115 G_TYPELIB_ERROR_INVALID,
116 "Expected blob for type");
120 if (simple->flags.reserved == 0 && simple->flags.reserved2 == 0)
124 G_TYPELIB_ERROR_INVALID,
125 "Expected non-basic type but got %d",
130 return (InterfaceTypeBlob*) get_blob (typelib, simple->offset, error);
134 g_typelib_get_dir_entry (GTypelib *typelib,
137 Header *header = (Header *)typelib->data;
139 return (DirEntry *)&typelib->data[header->directory + (index - 1) * header->entry_blob_size];
143 g_typelib_check_sanity (void)
145 /* Check that struct layout is as we expect */
147 gboolean size_check_ok = TRUE;
149 #define CHECK_SIZE(s,n) \
150 if (sizeof(s) != n) \
152 g_printerr ("sizeof("#s") is expected to be %d but is %"G_GSIZE_FORMAT".\n", \
154 size_check_ok = FALSE; \
157 /* When changing the size of a typelib structure, you are required to update
158 * the hardcoded size here. Do NOT change these to use sizeof(); these
159 * should match whatever is defined in the text specification and serve as
160 * a sanity check on structure modifications.
162 * Everything else in the code however should be using sizeof().
165 CHECK_SIZE (Header, 112);
166 CHECK_SIZE (DirEntry, 12);
167 CHECK_SIZE (SimpleTypeBlob, 4);
168 CHECK_SIZE (ArgBlob, 16);
169 CHECK_SIZE (SignatureBlob, 8);
170 CHECK_SIZE (CommonBlob, 8);
171 CHECK_SIZE (FunctionBlob, 20);
172 CHECK_SIZE (CallbackBlob, 12);
173 CHECK_SIZE (InterfaceTypeBlob, 4);
174 CHECK_SIZE (ArrayTypeBlob, 8);
175 CHECK_SIZE (ParamTypeBlob, 4);
176 CHECK_SIZE (ErrorTypeBlob, 4);
177 CHECK_SIZE (ErrorDomainBlob, 16);
178 CHECK_SIZE (ValueBlob, 12);
179 CHECK_SIZE (FieldBlob, 16);
180 CHECK_SIZE (RegisteredTypeBlob, 16);
181 CHECK_SIZE (StructBlob, 32);
182 CHECK_SIZE (EnumBlob, 24);
183 CHECK_SIZE (PropertyBlob, 16);
184 CHECK_SIZE (SignalBlob, 16);
185 CHECK_SIZE (VFuncBlob, 20);
186 CHECK_SIZE (ObjectBlob, 44);
187 CHECK_SIZE (InterfaceBlob, 40);
188 CHECK_SIZE (ConstantBlob, 24);
189 CHECK_SIZE (AttributeBlob, 12);
190 CHECK_SIZE (UnionBlob, 40);
193 g_assert (size_check_ok);
198 is_aligned (guint32 offset)
200 return offset == ALIGN_VALUE (offset, 4);
203 #define MAX_NAME_LEN 200
206 get_string (GTypelib *typelib, guint32 offset, GError **error)
208 if (typelib->len < offset)
212 G_TYPELIB_ERROR_INVALID,
213 "Buffer is too short while looking up name");
217 return (const char*)&typelib->data[offset];
221 get_string_nofail (GTypelib *typelib, guint32 offset)
223 const char *ret = get_string (typelib, offset, NULL);
229 validate_name (GTypelib *typelib,
231 const guchar *data, guint32 offset,
236 name = get_string (typelib, offset, error);
240 if (!memchr (name, '\0', MAX_NAME_LEN))
244 G_TYPELIB_ERROR_INVALID,
245 "The %s is too long: %s",
250 if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
254 G_TYPELIB_ERROR_INVALID,
255 "The %s contains invalid characters: '%s'",
264 validate_header (ValidateContext *ctx,
267 GTypelib *typelib = ctx->typelib;
270 if (typelib->len < sizeof (Header))
274 G_TYPELIB_ERROR_INVALID,
275 "The buffer is too short");
279 header = (Header *)typelib->data;
281 if (strncmp (header->magic, G_IR_MAGIC, 16) != 0)
285 G_TYPELIB_ERROR_INVALID_HEADER,
286 "Magic string not found");
291 if (header->major_version != 2 || header->minor_version != 0)
295 G_TYPELIB_ERROR_INVALID_HEADER,
301 if (header->n_entries < header->n_local_entries)
305 G_TYPELIB_ERROR_INVALID_HEADER,
306 "Inconsistent entry counts");
310 if (header->size != typelib->len)
314 G_TYPELIB_ERROR_INVALID_HEADER,
315 "Typelib size mismatch");
319 /* This is a sanity check for a specific typelib; it
320 * prevents us from loading an incompatible typelib.
322 * The hardcoded checks in g_typelib_check_sanity to
323 * protect against inadvertent or buggy changes to the typelib format
327 if (header->entry_blob_size != sizeof (DirEntry) ||
328 header->function_blob_size != sizeof (FunctionBlob) ||
329 header->callback_blob_size != sizeof (CallbackBlob) ||
330 header->signal_blob_size != sizeof (SignalBlob) ||
331 header->vfunc_blob_size != sizeof (VFuncBlob) ||
332 header->arg_blob_size != sizeof (ArgBlob) ||
333 header->property_blob_size != sizeof (PropertyBlob) ||
334 header->field_blob_size != sizeof (FieldBlob) ||
335 header->value_blob_size != sizeof (ValueBlob) ||
336 header->constant_blob_size != sizeof (ConstantBlob) ||
337 header->error_domain_blob_size != sizeof (ErrorDomainBlob) ||
338 header->attribute_blob_size != sizeof (AttributeBlob) ||
339 header->signature_blob_size != sizeof (SignatureBlob) ||
340 header->enum_blob_size != sizeof (EnumBlob) ||
341 header->struct_blob_size != sizeof (StructBlob) ||
342 header->object_blob_size != sizeof(ObjectBlob) ||
343 header->interface_blob_size != sizeof (InterfaceBlob) ||
344 header->union_blob_size != sizeof (UnionBlob))
348 G_TYPELIB_ERROR_INVALID_HEADER,
349 "Blob size mismatch");
353 if (!is_aligned (header->directory))
357 G_TYPELIB_ERROR_INVALID_HEADER,
358 "Misaligned directory");
362 if (!is_aligned (header->attributes))
366 G_TYPELIB_ERROR_INVALID_HEADER,
367 "Misaligned attributes");
371 if (header->attributes == 0 && header->n_attributes > 0)
375 G_TYPELIB_ERROR_INVALID_HEADER,
376 "Wrong number of attributes");
380 if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
386 static gboolean validate_type_blob (GTypelib *typelib,
388 guint32 signature_offset,
389 gboolean return_type,
393 validate_array_type_blob (GTypelib *typelib,
395 guint32 signature_offset,
396 gboolean return_type,
401 blob = (ArrayTypeBlob*)&typelib->data[offset];
407 G_TYPELIB_ERROR_INVALID_BLOB,
408 "Pointer type exected for tag %d", blob->tag);
412 /* FIXME validate length */
414 if (!validate_type_blob (typelib,
415 offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
423 validate_iface_type_blob (GTypelib *typelib,
425 guint32 signature_offset,
426 gboolean return_type,
429 InterfaceTypeBlob *blob;
430 InterfaceBlob *target;
432 blob = (InterfaceTypeBlob*)&typelib->data[offset];
434 target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
438 if (target->blob_type == 0) /* non-local */
445 validate_param_type_blob (GTypelib *typelib,
447 guint32 signature_offset,
448 gboolean return_type,
455 blob = (ParamTypeBlob*)&typelib->data[offset];
461 G_TYPELIB_ERROR_INVALID_BLOB,
462 "Pointer type exected for tag %d", blob->tag);
466 if (blob->n_types != n_params)
470 G_TYPELIB_ERROR_INVALID_BLOB,
471 "Parameter type number mismatch");
475 for (i = 0; i < n_params; i++)
477 if (!validate_type_blob (typelib,
478 offset + sizeof (ParamTypeBlob) +
479 i * sizeof (SimpleTypeBlob),
488 validate_error_type_blob (GTypelib *typelib,
490 guint32 signature_offset,
491 gboolean return_type,
499 blob = (ErrorTypeBlob*)&typelib->data[offset];
501 header = (Header *)typelib->data;
507 G_TYPELIB_ERROR_INVALID_BLOB,
508 "Pointer type exected for tag %d", blob->tag);
512 for (i = 0; i < blob->n_domains; i++)
514 if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
518 G_TYPELIB_ERROR_INVALID_BLOB,
519 "Invalid directory index %d", blob->domains[i]);
523 entry = g_typelib_get_dir_entry (typelib, blob->domains[i]);
525 if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
526 (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
530 G_TYPELIB_ERROR_INVALID_BLOB,
540 validate_type_blob (GTypelib *typelib,
542 guint32 signature_offset,
543 gboolean return_type,
546 SimpleTypeBlob *simple;
547 InterfaceTypeBlob *iface;
549 simple = (SimpleTypeBlob *)&typelib->data[offset];
551 if (simple->flags.reserved == 0 &&
552 simple->flags.reserved2 == 0)
554 if (simple->flags.tag >= GI_TYPE_TAG_ARRAY)
558 G_TYPELIB_ERROR_INVALID_BLOB,
559 "Wrong tag in simple type");
563 if (simple->flags.tag >= GI_TYPE_TAG_UTF8 &&
564 !simple->flags.pointer)
568 G_TYPELIB_ERROR_INVALID_BLOB,
569 "Pointer type exected for tag %d", simple->flags.tag);
576 iface = (InterfaceTypeBlob*)&typelib->data[simple->offset];
580 case GI_TYPE_TAG_ARRAY:
581 if (!validate_array_type_blob (typelib, simple->offset,
582 signature_offset, return_type, error))
585 case GI_TYPE_TAG_INTERFACE:
586 if (!validate_iface_type_blob (typelib, simple->offset,
587 signature_offset, return_type, error))
590 case GI_TYPE_TAG_GLIST:
591 case GI_TYPE_TAG_GSLIST:
592 if (!validate_param_type_blob (typelib, simple->offset,
593 signature_offset, return_type, 1, error))
596 case GI_TYPE_TAG_GHASH:
597 if (!validate_param_type_blob (typelib, simple->offset,
598 signature_offset, return_type, 2, error))
601 case GI_TYPE_TAG_ERROR:
602 if (!validate_error_type_blob (typelib, simple->offset,
603 signature_offset, return_type, error))
609 G_TYPELIB_ERROR_INVALID_BLOB,
610 "Wrong tag in complex type");
618 validate_arg_blob (GTypelib *typelib,
620 guint32 signature_offset,
625 if (typelib->len < offset + sizeof (ArgBlob))
629 G_TYPELIB_ERROR_INVALID,
630 "The buffer is too short");
634 blob = (ArgBlob*) &typelib->data[offset];
636 if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
639 if (!validate_type_blob (typelib,
640 offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
641 signature_offset, FALSE, error))
647 static SimpleTypeBlob *
648 return_type_from_signature (GTypelib *typelib,
653 if (typelib->len < offset + sizeof (SignatureBlob))
657 G_TYPELIB_ERROR_INVALID,
658 "The buffer is too short");
662 blob = (SignatureBlob*) &typelib->data[offset];
663 if (blob->return_type.offset == 0)
667 G_TYPELIB_ERROR_INVALID,
668 "No return type found in signature");
672 return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
676 validate_signature_blob (GTypelib *typelib,
683 if (typelib->len < offset + sizeof (SignatureBlob))
687 G_TYPELIB_ERROR_INVALID,
688 "The buffer is too short");
692 blob = (SignatureBlob*) &typelib->data[offset];
694 if (blob->return_type.offset != 0)
696 if (!validate_type_blob (typelib,
697 offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
698 offset, TRUE, error))
702 for (i = 0; i < blob->n_arguments; i++)
704 if (!validate_arg_blob (typelib,
705 offset + sizeof (SignatureBlob) +
706 i * sizeof (ArgBlob),
712 /* FIXME check constraints on return_value */
713 /* FIXME check array-length pairs */
718 validate_function_blob (ValidateContext *ctx,
720 guint16 container_type,
723 GTypelib *typelib = ctx->typelib;
725 SignatureBlob *sigblob;
728 if (typelib->len < offset + sizeof (FunctionBlob))
732 G_TYPELIB_ERROR_INVALID,
733 "The buffer is too short");
737 blob = (FunctionBlob*) &typelib->data[offset];
739 if (blob->blob_type != BLOB_TYPE_FUNCTION)
743 G_TYPELIB_ERROR_INVALID_BLOB,
744 "Wrong blob type %d, expected function", blob->blob_type);
748 if (!validate_name (typelib, "function", typelib->data, blob->name, error))
751 push_context (ctx, get_string_nofail (typelib, blob->name));
753 if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
756 switch (container_type)
758 case BLOB_TYPE_BOXED:
759 case BLOB_TYPE_STRUCT:
760 case BLOB_TYPE_UNION:
761 case BLOB_TYPE_OBJECT:
762 case BLOB_TYPE_INTERFACE:
763 is_method = !(blob->constructor || blob->setter || blob->getter || blob->wraps_vfunc);
769 if (blob->constructor)
771 switch (container_type)
773 case BLOB_TYPE_BOXED:
774 case BLOB_TYPE_STRUCT:
775 case BLOB_TYPE_UNION:
776 case BLOB_TYPE_OBJECT:
777 case BLOB_TYPE_INTERFACE:
782 G_TYPELIB_ERROR_INVALID_BLOB,
783 "Constructor not allowed");
788 if (blob->setter || blob->getter || blob->wraps_vfunc)
790 switch (container_type)
792 case BLOB_TYPE_OBJECT:
793 case BLOB_TYPE_INTERFACE:
798 G_TYPELIB_ERROR_INVALID_BLOB,
799 "Setter, getter or wrapper not allowed");
806 if (!(blob->setter || blob->getter || blob->wraps_vfunc))
810 G_TYPELIB_ERROR_INVALID_BLOB,
811 "Must be setter, getter or wrapper");
816 /* FIXME: validate index range */
818 if (!validate_signature_blob (typelib, blob->signature, error))
821 sigblob = (SignatureBlob*) &typelib->data[blob->signature];
823 if (blob->constructor)
825 SimpleTypeBlob *simple = return_type_from_signature (typelib,
828 InterfaceTypeBlob *iface_type;
832 iface_type = get_type_blob (typelib, simple, error);
835 if (!(iface_type->tag == GI_TYPE_TAG_INTERFACE))
839 G_TYPELIB_ERROR_INVALID,
840 "Invalid return type %d for constructor",
852 validate_callback_blob (ValidateContext *ctx,
856 GTypelib *typelib = ctx->typelib;
859 if (typelib->len < offset + sizeof (CallbackBlob))
863 G_TYPELIB_ERROR_INVALID,
864 "The buffer is too short");
868 blob = (CallbackBlob*) &typelib->data[offset];
870 if (blob->blob_type != BLOB_TYPE_CALLBACK)
874 G_TYPELIB_ERROR_INVALID_BLOB,
879 if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
882 push_context (ctx, get_string_nofail (typelib, blob->name));
884 if (!validate_signature_blob (typelib, blob->signature, error))
893 validate_constant_blob (GTypelib *typelib,
897 guint value_size[] = {
930 SimpleTypeBlob *type;
932 if (typelib->len < offset + sizeof (ConstantBlob))
936 G_TYPELIB_ERROR_INVALID,
937 "The buffer is too short");
941 blob = (ConstantBlob*) &typelib->data[offset];
943 if (blob->blob_type != BLOB_TYPE_CONSTANT)
947 G_TYPELIB_ERROR_INVALID_BLOB,
952 if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
955 if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
959 if (!is_aligned (blob->offset))
963 G_TYPELIB_ERROR_INVALID_BLOB,
964 "Misaligned constant value");
968 type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
969 if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
971 if (type->flags.tag == 0)
975 G_TYPELIB_ERROR_INVALID_BLOB,
976 "Constant value type void");
980 if (value_size[type->flags.tag] != 0 &&
981 blob->size != value_size[type->flags.tag])
985 G_TYPELIB_ERROR_INVALID_BLOB,
986 "Constant value size mismatch");
989 /* FIXME check string values */
996 validate_value_blob (GTypelib *typelib,
1002 if (typelib->len < offset + sizeof (ValueBlob))
1006 G_TYPELIB_ERROR_INVALID,
1007 "The buffer is too short");
1011 blob = (ValueBlob*) &typelib->data[offset];
1013 if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1020 validate_field_blob (ValidateContext *ctx,
1024 GTypelib *typelib = ctx->typelib;
1025 Header *header = (Header *)typelib->data;
1028 if (typelib->len < offset + sizeof (FieldBlob))
1032 G_TYPELIB_ERROR_INVALID,
1033 "The buffer is too short");
1037 blob = (FieldBlob*) &typelib->data[offset];
1039 if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1042 if (blob->has_embedded_type)
1044 if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
1047 else if (!validate_type_blob (typelib,
1048 offset + G_STRUCT_OFFSET (FieldBlob, type),
1056 validate_property_blob (GTypelib *typelib,
1062 if (typelib->len < offset + sizeof (PropertyBlob))
1066 G_TYPELIB_ERROR_INVALID,
1067 "The buffer is too short");
1071 blob = (PropertyBlob*) &typelib->data[offset];
1073 if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1076 if (!validate_type_blob (typelib,
1077 offset + G_STRUCT_OFFSET (PropertyBlob, type),
1085 validate_signal_blob (GTypelib *typelib,
1087 guint32 container_offset,
1093 if (typelib->len < offset + sizeof (SignalBlob))
1097 G_TYPELIB_ERROR_INVALID,
1098 "The buffer is too short");
1102 blob = (SignalBlob*) &typelib->data[offset];
1104 if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1107 if ((blob->run_first != 0) +
1108 (blob->run_last != 0) +
1109 (blob->run_cleanup != 0) != 1)
1113 G_TYPELIB_ERROR_INVALID_BLOB,
1114 "Invalid signal run flags");
1118 if (blob->has_class_closure)
1120 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1124 object = (ObjectBlob*)&typelib->data[container_offset];
1126 n_signals = object->n_signals;
1130 InterfaceBlob *iface;
1132 iface = (InterfaceBlob*)&typelib->data[container_offset];
1134 n_signals = iface->n_signals;
1137 if (blob->class_closure >= n_signals)
1141 G_TYPELIB_ERROR_INVALID_BLOB,
1142 "Invalid class closure index");
1147 if (!validate_signature_blob (typelib, blob->signature, error))
1154 validate_vfunc_blob (GTypelib *typelib,
1156 guint32 container_offset,
1162 if (typelib->len < offset + sizeof (VFuncBlob))
1166 G_TYPELIB_ERROR_INVALID,
1167 "The buffer is too short");
1171 blob = (VFuncBlob*) &typelib->data[offset];
1173 if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1176 if (blob->class_closure)
1178 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1182 object = (ObjectBlob*)&typelib->data[container_offset];
1184 n_vfuncs = object->n_vfuncs;
1188 InterfaceBlob *iface;
1190 iface = (InterfaceBlob*)&typelib->data[container_offset];
1192 n_vfuncs = iface->n_vfuncs;
1195 if (blob->class_closure >= n_vfuncs)
1199 G_TYPELIB_ERROR_INVALID_BLOB,
1200 "Invalid class closure index");
1205 if (!validate_signature_blob (typelib, blob->signature, error))
1212 validate_struct_blob (ValidateContext *ctx,
1217 GTypelib *typelib = ctx->typelib;
1220 guint32 field_offset;
1222 if (typelib->len < offset + sizeof (StructBlob))
1226 G_TYPELIB_ERROR_INVALID,
1227 "The buffer is too short");
1231 blob = (StructBlob*) &typelib->data[offset];
1233 if (blob->blob_type != blob_type)
1237 G_TYPELIB_ERROR_INVALID_BLOB,
1242 if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1245 push_context (ctx, get_string_nofail (typelib, blob->name));
1247 if (!blob->unregistered)
1249 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1252 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1257 if (blob->gtype_name || blob->gtype_init)
1261 G_TYPELIB_ERROR_INVALID_BLOB,
1262 "Gtype data in struct");
1267 if (typelib->len < offset + sizeof (StructBlob) +
1268 blob->n_fields * sizeof (FieldBlob) +
1269 blob->n_methods * sizeof (FunctionBlob))
1273 G_TYPELIB_ERROR_INVALID,
1274 "The buffer is too short");
1278 field_offset = offset + sizeof (StructBlob);
1279 for (i = 0; i < blob->n_fields; i++)
1281 FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
1283 if (!validate_field_blob (ctx,
1288 field_offset += sizeof (FieldBlob);
1289 if (blob->has_embedded_type)
1290 field_offset += sizeof (CallbackBlob);
1293 for (i = 0; i < blob->n_methods; i++)
1295 if (!validate_function_blob (ctx,
1297 i * sizeof (FunctionBlob),
1309 validate_enum_blob (ValidateContext *ctx,
1314 GTypelib *typelib = ctx->typelib;
1318 if (typelib->len < offset + sizeof (EnumBlob))
1322 G_TYPELIB_ERROR_INVALID,
1323 "The buffer is too short");
1327 blob = (EnumBlob*) &typelib->data[offset];
1329 if (blob->blob_type != blob_type)
1333 G_TYPELIB_ERROR_INVALID_BLOB,
1338 if (!blob->unregistered)
1340 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1343 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1348 if (blob->gtype_name || blob->gtype_init)
1352 G_TYPELIB_ERROR_INVALID_BLOB,
1353 "Gtype data in unregistered enum");
1358 if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1361 if (typelib->len < offset + sizeof (EnumBlob) +
1362 blob->n_values * sizeof (ValueBlob))
1366 G_TYPELIB_ERROR_INVALID,
1367 "The buffer is too short");
1371 push_context (ctx, get_string_nofail (typelib, blob->name));
1373 for (i = 0; i < blob->n_values; i++)
1375 if (!validate_value_blob (typelib,
1376 offset + sizeof (EnumBlob) +
1377 i * sizeof (ValueBlob),
1382 v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1383 i * sizeof (ValueBlob)];
1384 for (j = 0; j < i; j++)
1386 v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1387 j * sizeof (ValueBlob)];
1389 if (v1->value == v2->value)
1392 /* FIXME should this be an error ? */
1395 G_TYPELIB_ERROR_INVALID_BLOB,
1396 "Duplicate enum value");
1409 validate_object_blob (ValidateContext *ctx,
1413 GTypelib *typelib = ctx->typelib;
1419 header = (Header *)typelib->data;
1421 if (typelib->len < offset + sizeof (ObjectBlob))
1425 G_TYPELIB_ERROR_INVALID,
1426 "The buffer is too short");
1430 blob = (ObjectBlob*) &typelib->data[offset];
1432 if (blob->blob_type != BLOB_TYPE_OBJECT)
1436 G_TYPELIB_ERROR_INVALID_BLOB,
1441 if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1444 if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1447 if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1450 if (blob->parent > header->n_entries)
1454 G_TYPELIB_ERROR_INVALID_BLOB,
1455 "Invalid parent index");
1459 if (blob->parent != 0)
1463 entry = get_dir_entry_checked (typelib, blob->parent, error);
1466 if (entry->blob_type != BLOB_TYPE_OBJECT &&
1467 (entry->local || entry->blob_type != 0))
1471 G_TYPELIB_ERROR_INVALID_BLOB,
1472 "Parent not object");
1477 if (blob->gtype_struct != 0)
1481 entry = get_dir_entry_checked (typelib, blob->gtype_struct, error);
1484 if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1488 G_TYPELIB_ERROR_INVALID_BLOB,
1489 "Class struct invalid type or not local");
1494 if (typelib->len < offset + sizeof (ObjectBlob) +
1495 (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1496 blob->n_fields * sizeof (FieldBlob) +
1497 blob->n_properties * sizeof (PropertyBlob) +
1498 blob->n_methods * sizeof (FunctionBlob) +
1499 blob->n_signals * sizeof (SignalBlob) +
1500 blob->n_vfuncs * sizeof (VFuncBlob) +
1501 blob->n_constants * sizeof (ConstantBlob))
1506 G_TYPELIB_ERROR_INVALID,
1507 "The buffer is too short");
1511 offset2 = offset + sizeof (ObjectBlob);
1513 for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1518 iface = *(guint16*)&typelib->data[offset2];
1519 if (iface == 0 || iface > header->n_entries)
1523 G_TYPELIB_ERROR_INVALID_BLOB,
1524 "Invalid interface index");
1528 entry = get_dir_entry_checked (typelib, iface, error);
1532 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1533 (entry->local || entry->blob_type != 0))
1537 G_TYPELIB_ERROR_INVALID_BLOB,
1538 "Not an interface");
1543 offset2 += 2 * (blob->n_interfaces %2);
1545 push_context (ctx, get_string_nofail (typelib, blob->name));
1547 for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1549 if (!validate_field_blob (ctx, offset2, error))
1553 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1555 if (!validate_property_blob (typelib, offset2, error))
1559 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1561 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1565 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1567 if (!validate_signal_blob (typelib, offset2, offset, error))
1571 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1573 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1577 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1579 if (!validate_constant_blob (typelib, offset2, error))
1589 validate_interface_blob (ValidateContext *ctx,
1593 GTypelib *typelib = ctx->typelib;
1595 InterfaceBlob *blob;
1599 header = (Header *)typelib->data;
1601 if (typelib->len < offset + sizeof (InterfaceBlob))
1605 G_TYPELIB_ERROR_INVALID,
1606 "The buffer is too short");
1610 blob = (InterfaceBlob*) &typelib->data[offset];
1612 if (blob->blob_type != BLOB_TYPE_INTERFACE)
1616 G_TYPELIB_ERROR_INVALID_BLOB,
1617 "Wrong blob type; expected interface, got %d", blob->blob_type);
1621 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1624 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1627 if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1630 if (typelib->len < offset + sizeof (InterfaceBlob) +
1631 (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1632 blob->n_properties * sizeof (PropertyBlob) +
1633 blob->n_methods * sizeof (FunctionBlob) +
1634 blob->n_signals * sizeof (SignalBlob) +
1635 blob->n_vfuncs * sizeof (VFuncBlob) +
1636 blob->n_constants * sizeof (ConstantBlob))
1641 G_TYPELIB_ERROR_INVALID,
1642 "The buffer is too short");
1646 offset2 = offset + sizeof (InterfaceBlob);
1648 for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1653 req = *(guint16*)&typelib->data[offset2];
1654 if (req == 0 || req > header->n_entries)
1658 G_TYPELIB_ERROR_INVALID_BLOB,
1659 "Invalid prerequisite index");
1663 entry = g_typelib_get_dir_entry (typelib, req);
1664 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1665 entry->blob_type != BLOB_TYPE_OBJECT &&
1666 (entry->local || entry->blob_type != 0))
1670 G_TYPELIB_ERROR_INVALID_BLOB,
1671 "Not an interface or object");
1676 offset2 += 2 * (blob->n_prerequisites % 2);
1678 push_context (ctx, get_string_nofail (typelib, blob->name));
1680 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1682 if (!validate_property_blob (typelib, offset2, error))
1686 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1688 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1692 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1694 if (!validate_signal_blob (typelib, offset2, offset, error))
1698 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1700 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1704 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1706 if (!validate_constant_blob (typelib, offset2, error))
1716 validate_errordomain_blob (GTypelib *typelib,
1724 validate_union_blob (GTypelib *typelib,
1732 validate_blob (ValidateContext *ctx,
1736 GTypelib *typelib = ctx->typelib;
1739 if (typelib->len < offset + sizeof (CommonBlob))
1743 G_TYPELIB_ERROR_INVALID,
1744 "The buffer is too short");
1748 common = (CommonBlob*)&typelib->data[offset];
1750 switch (common->blob_type)
1752 case BLOB_TYPE_FUNCTION:
1753 if (!validate_function_blob (ctx, offset, 0, error))
1756 case BLOB_TYPE_CALLBACK:
1757 if (!validate_callback_blob (ctx, offset, error))
1760 case BLOB_TYPE_STRUCT:
1761 case BLOB_TYPE_BOXED:
1762 if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1765 case BLOB_TYPE_ENUM:
1766 case BLOB_TYPE_FLAGS:
1767 if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1770 case BLOB_TYPE_OBJECT:
1771 if (!validate_object_blob (ctx, offset, error))
1774 case BLOB_TYPE_INTERFACE:
1775 if (!validate_interface_blob (ctx, offset, error))
1778 case BLOB_TYPE_CONSTANT:
1779 if (!validate_constant_blob (typelib, offset, error))
1782 case BLOB_TYPE_ERROR_DOMAIN:
1783 if (!validate_errordomain_blob (typelib, offset, error))
1786 case BLOB_TYPE_UNION:
1787 if (!validate_union_blob (typelib, offset, error))
1793 G_TYPELIB_ERROR_INVALID_ENTRY,
1794 "Invalid blob type");
1802 validate_directory (ValidateContext *ctx,
1805 GTypelib *typelib = ctx->typelib;
1806 Header *header = (Header *)typelib->data;
1810 if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1814 G_TYPELIB_ERROR_INVALID,
1815 "The buffer is too short");
1819 for (i = 0; i < header->n_entries; i++)
1821 entry = g_typelib_get_dir_entry (typelib, i + 1);
1823 if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1826 if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1827 entry->blob_type > BLOB_TYPE_UNION)
1831 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1832 "Invalid entry type");
1836 if (i < header->n_local_entries)
1842 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1843 "Too few local directory entries");
1847 if (!is_aligned (entry->offset))
1851 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1852 "Misaligned entry");
1856 if (!validate_blob (ctx, entry->offset, error))
1865 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1866 "Too many local directory entries");
1870 if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1879 validate_attributes (ValidateContext *ctx,
1882 GTypelib *typelib = ctx->typelib;
1883 Header *header = (Header *)typelib->data;
1885 if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
1889 G_TYPELIB_ERROR_INVALID,
1890 "The buffer is too short");
1898 prefix_with_context (GError **error,
1899 const char *section,
1900 ValidateContext *ctx)
1902 GString *str = g_string_new (NULL);
1906 link = ctx->context_stack;
1909 g_prefix_error (error, "In %s:", section);
1913 for (; link; link = link->next)
1915 g_string_append (str, link->data);
1917 g_string_append_c (str, '/');
1919 g_string_append_c (str, ')');
1920 buf = g_string_free (str, FALSE);
1921 g_prefix_error (error, "In %s (Context: %s): ", section, buf);
1926 g_typelib_validate (GTypelib *typelib,
1929 ValidateContext ctx;
1930 ctx.typelib = typelib;
1931 ctx.context_stack = NULL;
1933 if (!validate_header (&ctx, error))
1935 prefix_with_context (error, "In header", &ctx);
1939 if (!validate_directory (&ctx, error))
1941 prefix_with_context (error, "directory", &ctx);
1945 if (!validate_attributes (&ctx, error))
1947 prefix_with_context (error, "attributes", &ctx);
1955 g_typelib_error_quark (void)
1957 static GQuark quark = 0;
1959 quark = g_quark_from_static_string ("g-typelib-error-quark");
1964 _g_typelib_do_dlopen (GTypelib *typelib)
1967 const char *shlib_str;
1969 header = (Header *) typelib->data;
1970 /* note that NULL shlib means to open the main app, which is allowed */
1971 if (header->shared_library)
1972 shlib_str = g_typelib_get_string (typelib, header->shared_library);
1976 if (shlib_str != NULL && shlib_str[0] != '\0')
1981 /* shared-library is a comma-separated list of libraries */
1982 shlibs = g_strsplit (shlib_str, ",", 0);
1984 /* We load all passed libs unconditionally as if the same library is loaded
1985 * again with dlopen(), the same file handle will be returned. See bug:
1986 * http://bugzilla.gnome.org/show_bug.cgi?id=555294
1988 for (i = 0; shlibs[i]; i++)
1992 /* Glade's autoconnect feature and OpenGL's extension mechanism
1993 * as used by Clutter rely on dlopen(NULL) to work as a means of
1994 * accessing the app's symbols. This keeps us from using
1995 * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
1996 * in general libraries are not expecting multiple copies of
1997 * themselves and are not expecting to be unloaded. So we just
1998 * load modules globally for now.
2001 module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
2005 GString *shlib_full = g_string_new (shlibs[i]);
2007 /* Prefix with "lib", try both .la and .so */
2008 if (!g_str_has_prefix (shlib_full->str, "lib"))
2009 g_string_prepend (shlib_full, "lib");
2010 g_string_append (shlib_full, ".la");
2011 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2014 g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
2015 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2018 g_string_free (shlib_full, TRUE);
2023 g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2024 shlibs[i], g_module_error ());
2028 typelib->modules = g_list_append (typelib->modules, module);
2032 g_strfreev (shlibs);
2036 /* If there's no shared-library entry for this module, assume that
2037 * the module is for the application. Some of the hand-written .gir files
2038 * in gobject-introspection don't have shared-library entries, but no one
2039 * is really going to be calling g_module_symbol on them either.
2041 GModule *module = g_module_open (NULL, 0);
2043 g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
2045 typelib->modules = g_list_prepend (typelib->modules, module);
2050 _g_typelib_ensure_open (GTypelib *typelib)
2052 if (typelib->open_attempted)
2054 typelib->open_attempted = TRUE;
2055 _g_typelib_do_dlopen (typelib);
2059 * g_typelib_new_from_memory:
2060 * @memory: address of memory chunk containing the typelib
2061 * @len: length of memory chunk containing the typelib
2063 * Creates a new #GTypelib from a memory location. The memory block
2064 * pointed to by @typelib will be automatically g_free()d when the
2065 * repository is destroyed.
2067 * Return value: the new #GTypelib
2070 g_typelib_new_from_memory (guchar *memory, gsize len)
2074 meta = g_new0 (GTypelib, 1);
2075 meta->data = memory;
2077 meta->owns_memory = TRUE;
2078 meta->modules = NULL;
2084 * g_typelib_new_from_const_memory:
2085 * @memory: address of memory chunk containing the typelib
2086 * @len: length of memory chunk containing the typelib
2088 * Creates a new #GTypelib from a memory location.
2090 * Return value: the new #GTypelib
2093 g_typelib_new_from_const_memory (const guchar *memory, gsize len)
2097 meta = g_new0 (GTypelib, 1);
2098 meta->data = (guchar *) memory;
2100 meta->owns_memory = FALSE;
2101 meta->modules = NULL;
2107 * g_typelib_new_from_mapped_file:
2108 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2110 * Creates a new #GTypelib from a #GMappedFile.
2112 * Return value: the new #GTypelib
2115 g_typelib_new_from_mapped_file (GMappedFile *mfile)
2119 meta = g_new0 (GTypelib, 1);
2120 meta->mfile = mfile;
2121 meta->owns_memory = FALSE;
2122 meta->data = (guchar *) g_mapped_file_get_contents (mfile);
2123 meta->len = g_mapped_file_get_length (mfile);
2130 * @typelib: a #GTypelib
2135 g_typelib_free (GTypelib *typelib)
2138 g_mapped_file_unref (typelib->mfile);
2140 if (typelib->owns_memory)
2141 g_free (typelib->data);
2142 if (typelib->modules)
2144 g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2145 g_list_free (typelib->modules);
2151 g_typelib_get_namespace (GTypelib *typelib)
2153 return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2158 * @typelib: the typelib
2159 * @symbol_name: name of symbol to be loaded
2160 * @symbol: returns a pointer to the symbol value
2162 * Loads a symbol from #GTypelib.
2164 * Return value: #TRUE on success
2167 g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
2171 _g_typelib_ensure_open (typelib);
2174 * The reason for having multiple modules dates from gir-repository
2175 * when it was desired to inject code (accessors, etc.) into an
2176 * existing library. In that situation, the first module listed
2177 * will be the custom one, which overrides the main one. A bit
2178 * inefficient, but the problem will go away when gir-repository
2181 * For modules with no shared library, we dlopen'd the current
2184 for (l = typelib->modules; l; l = l->next)
2186 GModule *module = l->data;
2188 if (g_module_symbol (module, symbol_name, symbol))