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 CHECK_SIZE (Header, 104);
157 CHECK_SIZE (DirEntry, 12);
158 CHECK_SIZE (SimpleTypeBlob, 4);
159 CHECK_SIZE (ArgBlob, 12);
160 CHECK_SIZE (SignatureBlob, 8);
161 CHECK_SIZE (CommonBlob, 8);
162 CHECK_SIZE (FunctionBlob, 16);
163 CHECK_SIZE (InterfaceTypeBlob, 4);
164 CHECK_SIZE (ArrayTypeBlob, 8);
165 CHECK_SIZE (ParamTypeBlob, 4);
166 CHECK_SIZE (ErrorTypeBlob, 4);
167 CHECK_SIZE (ErrorDomainBlob, 16);
168 CHECK_SIZE (ValueBlob, 12);
169 CHECK_SIZE (FieldBlob, 12);
170 CHECK_SIZE (RegisteredTypeBlob, 16);
171 CHECK_SIZE (StructBlob, 20);
172 CHECK_SIZE (EnumBlob, 20);
173 CHECK_SIZE (PropertyBlob, 12);
174 CHECK_SIZE (SignalBlob, 12);
175 CHECK_SIZE (VFuncBlob, 16);
176 CHECK_SIZE (ObjectBlob, 32);
177 CHECK_SIZE (InterfaceBlob, 28);
178 CHECK_SIZE (ConstantBlob, 20);
179 CHECK_SIZE (AnnotationBlob, 12);
180 CHECK_SIZE (UnionBlob, 28);
183 g_assert (size_check_ok);
188 is_aligned (guint32 offset)
190 return offset == ALIGN_VALUE (offset, 4);
193 #define MAX_NAME_LEN 200
196 get_string (GTypelib *typelib, guint32 offset, GError **error)
198 if (typelib->len < offset)
202 G_TYPELIB_ERROR_INVALID,
203 "Buffer is too short while looking up name");
207 return (const char*)&typelib->data[offset];
211 get_string_nofail (GTypelib *typelib, guint32 offset)
213 const char *ret = get_string (typelib, offset, NULL);
219 validate_name (GTypelib *typelib,
221 const guchar *data, guint32 offset,
226 name = get_string (typelib, offset, error);
230 if (!memchr (name, '\0', MAX_NAME_LEN))
234 G_TYPELIB_ERROR_INVALID,
235 "The %s is too long: %s",
240 if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
244 G_TYPELIB_ERROR_INVALID,
245 "The %s is contains invalid characters: %s",
254 validate_header (ValidateContext *ctx,
257 GTypelib *typelib = ctx->typelib;
260 if (typelib->len < sizeof (Header))
264 G_TYPELIB_ERROR_INVALID,
265 "The buffer is too short");
269 header = (Header *)typelib->data;
271 if (strncmp (header->magic, G_IR_MAGIC, 16) != 0)
275 G_TYPELIB_ERROR_INVALID_HEADER,
276 "Magic string not found");
281 if (header->major_version != 1 || header->minor_version != 0)
285 G_TYPELIB_ERROR_INVALID_HEADER,
291 if (header->n_entries < header->n_local_entries)
295 G_TYPELIB_ERROR_INVALID_HEADER,
296 "Inconsistent entry counts");
300 if (header->size != typelib->len)
304 G_TYPELIB_ERROR_INVALID_HEADER,
305 "Typelib size mismatch");
309 if (header->entry_blob_size != 12 ||
310 header->function_blob_size != 16 ||
311 header->callback_blob_size != 12 ||
312 header->signal_blob_size != 12 ||
313 header->vfunc_blob_size != 16 ||
314 header->arg_blob_size != 12 ||
315 header->property_blob_size != 12 ||
316 header->field_blob_size != 12 ||
317 header->value_blob_size != 12 ||
318 header->constant_blob_size != 20 ||
319 header->error_domain_blob_size != 16 ||
320 header->annotation_blob_size != 12 ||
321 header->signature_blob_size != 8 ||
322 header->enum_blob_size != 20 ||
323 header->struct_blob_size != 20 ||
324 header->object_blob_size != 32 ||
325 header->interface_blob_size != 28 ||
326 header->union_blob_size != 28)
330 G_TYPELIB_ERROR_INVALID_HEADER,
331 "Blob size mismatch");
335 if (!is_aligned (header->directory))
339 G_TYPELIB_ERROR_INVALID_HEADER,
340 "Misaligned directory");
344 if (!is_aligned (header->annotations))
348 G_TYPELIB_ERROR_INVALID_HEADER,
349 "Misaligned annotations");
353 if (header->annotations == 0 && header->n_annotations > 0)
357 G_TYPELIB_ERROR_INVALID_HEADER,
358 "Wrong number of annotations");
362 if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
368 static gboolean validate_type_blob (GTypelib *typelib,
370 guint32 signature_offset,
371 gboolean return_type,
375 validate_array_type_blob (GTypelib *typelib,
377 guint32 signature_offset,
378 gboolean return_type,
383 blob = (ArrayTypeBlob*)&typelib->data[offset];
389 G_TYPELIB_ERROR_INVALID_BLOB,
390 "Pointer type exected for tag %d", blob->tag);
394 /* FIXME validate length */
396 if (!validate_type_blob (typelib,
397 offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
405 validate_iface_type_blob (GTypelib *typelib,
407 guint32 signature_offset,
408 gboolean return_type,
411 InterfaceTypeBlob *blob;
412 InterfaceBlob *target;
414 blob = (InterfaceTypeBlob*)&typelib->data[offset];
416 target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
420 if (target->blob_type == 0) /* non-local */
427 validate_param_type_blob (GTypelib *typelib,
429 guint32 signature_offset,
430 gboolean return_type,
437 blob = (ParamTypeBlob*)&typelib->data[offset];
443 G_TYPELIB_ERROR_INVALID_BLOB,
444 "Pointer type exected for tag %d", blob->tag);
448 if (blob->n_types != n_params)
452 G_TYPELIB_ERROR_INVALID_BLOB,
453 "Parameter type number mismatch");
457 for (i = 0; i < n_params; i++)
459 if (!validate_type_blob (typelib,
460 offset + sizeof (ParamTypeBlob) +
461 i * sizeof (SimpleTypeBlob),
470 validate_error_type_blob (GTypelib *typelib,
472 guint32 signature_offset,
473 gboolean return_type,
481 blob = (ErrorTypeBlob*)&typelib->data[offset];
483 header = (Header *)typelib->data;
489 G_TYPELIB_ERROR_INVALID_BLOB,
490 "Pointer type exected for tag %d", blob->tag);
494 for (i = 0; i < blob->n_domains; i++)
496 if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
500 G_TYPELIB_ERROR_INVALID_BLOB,
501 "Invalid directory index %d", blob->domains[i]);
505 entry = g_typelib_get_dir_entry (typelib, blob->domains[i]);
507 if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
508 (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
512 G_TYPELIB_ERROR_INVALID_BLOB,
522 validate_type_blob (GTypelib *typelib,
524 guint32 signature_offset,
525 gboolean return_type,
528 SimpleTypeBlob *simple;
529 InterfaceTypeBlob *iface;
531 simple = (SimpleTypeBlob *)&typelib->data[offset];
533 if (simple->reserved == 0 &&
534 simple->reserved2 == 0)
536 if (simple->tag >= GI_TYPE_TAG_ARRAY)
540 G_TYPELIB_ERROR_INVALID_BLOB,
541 "Wrong tag in simple type");
545 if (simple->tag >= GI_TYPE_TAG_UTF8 &&
550 G_TYPELIB_ERROR_INVALID_BLOB,
551 "Pointer type exected for tag %d", simple->tag);
558 iface = (InterfaceTypeBlob*)&typelib->data[simple->offset];
562 case GI_TYPE_TAG_ARRAY:
563 if (!validate_array_type_blob (typelib, simple->offset,
564 signature_offset, return_type, error))
567 case GI_TYPE_TAG_INTERFACE:
568 if (!validate_iface_type_blob (typelib, simple->offset,
569 signature_offset, return_type, error))
572 case GI_TYPE_TAG_GLIST:
573 case GI_TYPE_TAG_GSLIST:
574 if (!validate_param_type_blob (typelib, simple->offset,
575 signature_offset, return_type, 1, error))
578 case GI_TYPE_TAG_GHASH:
579 if (!validate_param_type_blob (typelib, simple->offset,
580 signature_offset, return_type, 2, error))
583 case GI_TYPE_TAG_ERROR:
584 if (!validate_error_type_blob (typelib, simple->offset,
585 signature_offset, return_type, error))
591 G_TYPELIB_ERROR_INVALID_BLOB,
592 "Wrong tag in complex type");
600 validate_arg_blob (GTypelib *typelib,
602 guint32 signature_offset,
607 if (typelib->len < offset + sizeof (ArgBlob))
611 G_TYPELIB_ERROR_INVALID,
612 "The buffer is too short");
616 blob = (ArgBlob*) &typelib->data[offset];
618 if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
621 if (!validate_type_blob (typelib,
622 offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
623 signature_offset, FALSE, error))
629 static SimpleTypeBlob *
630 return_type_from_signature (GTypelib *typelib,
635 if (typelib->len < offset + sizeof (SignatureBlob))
639 G_TYPELIB_ERROR_INVALID,
640 "The buffer is too short");
644 blob = (SignatureBlob*) &typelib->data[offset];
645 if (blob->return_type.offset == 0)
649 G_TYPELIB_ERROR_INVALID,
650 "No return type found in signature");
654 return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
658 validate_signature_blob (GTypelib *typelib,
665 if (typelib->len < offset + sizeof (SignatureBlob))
669 G_TYPELIB_ERROR_INVALID,
670 "The buffer is too short");
674 blob = (SignatureBlob*) &typelib->data[offset];
676 if (blob->return_type.offset != 0)
678 if (!validate_type_blob (typelib,
679 offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
680 offset, TRUE, error))
684 for (i = 0; i < blob->n_arguments; i++)
686 if (!validate_arg_blob (typelib,
687 offset + sizeof (SignatureBlob) +
688 i * sizeof (ArgBlob),
694 /* FIXME check constraints on return_value */
695 /* FIXME check array-length pairs */
700 validate_function_blob (ValidateContext *ctx,
702 guint16 container_type,
705 GTypelib *typelib = ctx->typelib;
707 SignatureBlob *sigblob;
710 if (typelib->len < offset + sizeof (FunctionBlob))
714 G_TYPELIB_ERROR_INVALID,
715 "The buffer is too short");
719 blob = (FunctionBlob*) &typelib->data[offset];
721 if (blob->blob_type != BLOB_TYPE_FUNCTION)
725 G_TYPELIB_ERROR_INVALID_BLOB,
730 if (!validate_name (typelib, "function", typelib->data, blob->name, error))
733 push_context (ctx, get_string_nofail (typelib, blob->name));
735 if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
738 switch (container_type)
740 case BLOB_TYPE_BOXED:
741 case BLOB_TYPE_STRUCT:
742 case BLOB_TYPE_UNION:
743 case BLOB_TYPE_OBJECT:
744 case BLOB_TYPE_INTERFACE:
745 is_method = !(blob->constructor || blob->setter || blob->getter || blob->wraps_vfunc);
751 if (blob->constructor)
753 switch (container_type)
755 case BLOB_TYPE_BOXED:
756 case BLOB_TYPE_STRUCT:
757 case BLOB_TYPE_UNION:
758 case BLOB_TYPE_OBJECT:
759 case BLOB_TYPE_INTERFACE:
764 G_TYPELIB_ERROR_INVALID_BLOB,
765 "Constructor not allowed");
770 if (blob->setter || blob->getter || blob->wraps_vfunc)
772 switch (container_type)
774 case BLOB_TYPE_OBJECT:
775 case BLOB_TYPE_INTERFACE:
780 G_TYPELIB_ERROR_INVALID_BLOB,
781 "Setter, getter or wrapper not allowed");
788 if (!(blob->setter || blob->getter || blob->wraps_vfunc))
792 G_TYPELIB_ERROR_INVALID_BLOB,
793 "Must be setter, getter or wrapper");
798 /* FIXME: validate index range */
800 if (!validate_signature_blob (typelib, blob->signature, error))
803 sigblob = (SignatureBlob*) &typelib->data[blob->signature];
805 if (blob->constructor)
807 SimpleTypeBlob *simple = return_type_from_signature (typelib,
810 InterfaceTypeBlob *iface_type;
811 InterfaceBlob *iface;
815 iface_type = get_type_blob (typelib, simple, error);
818 if (!(iface_type->tag == GI_TYPE_TAG_INTERFACE))
822 G_TYPELIB_ERROR_INVALID,
823 "Invalid return type %d for constructor",
835 validate_callback_blob (ValidateContext *ctx,
839 GTypelib *typelib = ctx->typelib;
842 if (typelib->len < offset + sizeof (CallbackBlob))
846 G_TYPELIB_ERROR_INVALID,
847 "The buffer is too short");
851 blob = (CallbackBlob*) &typelib->data[offset];
853 if (blob->blob_type != BLOB_TYPE_CALLBACK)
857 G_TYPELIB_ERROR_INVALID_BLOB,
862 if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
865 push_context (ctx, get_string_nofail (typelib, blob->name));
867 if (!validate_signature_blob (typelib, blob->signature, error))
876 validate_constant_blob (GTypelib *typelib,
880 gint value_size[] = {
881 0, 4, 1, 1, 2, 2, 4, 4, 8, 8,
882 sizeof (gint), sizeof (guint),
883 sizeof (glong), sizeof (gulong),
884 sizeof (gssize), sizeof (gsize),
885 sizeof (gfloat), sizeof (gdouble),
889 SimpleTypeBlob *type;
891 if (typelib->len < offset + sizeof (ConstantBlob))
895 G_TYPELIB_ERROR_INVALID,
896 "The buffer is too short");
900 blob = (ConstantBlob*) &typelib->data[offset];
902 if (blob->blob_type != BLOB_TYPE_CONSTANT)
906 G_TYPELIB_ERROR_INVALID_BLOB,
911 if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
914 if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
918 if (!is_aligned (blob->offset))
922 G_TYPELIB_ERROR_INVALID_BLOB,
923 "Misaligned constant value");
927 type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
928 if (type->reserved == 0 && type->reserved2 == 0)
934 G_TYPELIB_ERROR_INVALID_BLOB,
935 "Constant value type void");
939 if (value_size[type->tag] != 0 &&
940 blob->size != value_size[type->tag])
944 G_TYPELIB_ERROR_INVALID_BLOB,
945 "Constant value size mismatch");
948 /* FIXME check string values */
955 validate_value_blob (GTypelib *typelib,
961 if (typelib->len < offset + sizeof (ValueBlob))
965 G_TYPELIB_ERROR_INVALID,
966 "The buffer is too short");
970 blob = (ValueBlob*) &typelib->data[offset];
972 if (!validate_name (typelib, "value", typelib->data, blob->name, error))
979 validate_field_blob (GTypelib *typelib,
985 if (typelib->len < offset + sizeof (FieldBlob))
989 G_TYPELIB_ERROR_INVALID,
990 "The buffer is too short");
994 blob = (FieldBlob*) &typelib->data[offset];
996 if (!validate_name (typelib, "field", typelib->data, blob->name, error))
999 if (!validate_type_blob (typelib,
1000 offset + G_STRUCT_OFFSET (FieldBlob, type),
1008 validate_property_blob (GTypelib *typelib,
1014 if (typelib->len < offset + sizeof (PropertyBlob))
1018 G_TYPELIB_ERROR_INVALID,
1019 "The buffer is too short");
1023 blob = (PropertyBlob*) &typelib->data[offset];
1025 if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1028 if (!validate_type_blob (typelib,
1029 offset + G_STRUCT_OFFSET (PropertyBlob, type),
1037 validate_signal_blob (GTypelib *typelib,
1039 guint32 container_offset,
1045 if (typelib->len < offset + sizeof (SignalBlob))
1049 G_TYPELIB_ERROR_INVALID,
1050 "The buffer is too short");
1054 blob = (SignalBlob*) &typelib->data[offset];
1056 if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1059 if ((blob->run_first != 0) +
1060 (blob->run_last != 0) +
1061 (blob->run_cleanup != 0) != 1)
1065 G_TYPELIB_ERROR_INVALID_BLOB,
1066 "Invalid signal run flags");
1070 if (blob->has_class_closure)
1072 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1076 object = (ObjectBlob*)&typelib->data[container_offset];
1078 n_signals = object->n_signals;
1082 InterfaceBlob *iface;
1084 iface = (InterfaceBlob*)&typelib->data[container_offset];
1086 n_signals = iface->n_signals;
1089 if (blob->class_closure >= n_signals)
1093 G_TYPELIB_ERROR_INVALID_BLOB,
1094 "Invalid class closure index");
1099 if (!validate_signature_blob (typelib, blob->signature, error))
1106 validate_vfunc_blob (GTypelib *typelib,
1108 guint32 container_offset,
1114 if (typelib->len < offset + sizeof (VFuncBlob))
1118 G_TYPELIB_ERROR_INVALID,
1119 "The buffer is too short");
1123 blob = (VFuncBlob*) &typelib->data[offset];
1125 if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1128 if (blob->class_closure)
1130 if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1134 object = (ObjectBlob*)&typelib->data[container_offset];
1136 n_vfuncs = object->n_vfuncs;
1140 InterfaceBlob *iface;
1142 iface = (InterfaceBlob*)&typelib->data[container_offset];
1144 n_vfuncs = iface->n_vfuncs;
1147 if (blob->class_closure >= n_vfuncs)
1151 G_TYPELIB_ERROR_INVALID_BLOB,
1152 "Invalid class closure index");
1157 if (!validate_signature_blob (typelib, blob->signature, error))
1164 validate_struct_blob (ValidateContext *ctx,
1169 GTypelib *typelib = ctx->typelib;
1173 if (typelib->len < offset + sizeof (StructBlob))
1177 G_TYPELIB_ERROR_INVALID,
1178 "The buffer is too short");
1182 blob = (StructBlob*) &typelib->data[offset];
1184 if (blob->blob_type != blob_type)
1188 G_TYPELIB_ERROR_INVALID_BLOB,
1193 if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1196 push_context (ctx, get_string_nofail (typelib, blob->name));
1198 if (!blob->unregistered)
1200 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1203 if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1208 if (blob->gtype_name || blob->gtype_init)
1212 G_TYPELIB_ERROR_INVALID_BLOB,
1213 "Gtype data in struct");
1218 if (typelib->len < offset + sizeof (StructBlob) +
1219 blob->n_fields * sizeof (FieldBlob) +
1220 blob->n_methods * sizeof (FunctionBlob))
1224 G_TYPELIB_ERROR_INVALID,
1225 "The buffer is too short");
1229 for (i = 0; i < blob->n_fields; i++)
1231 if (!validate_field_blob (typelib,
1232 offset + sizeof (StructBlob) +
1233 i * sizeof (FieldBlob),
1238 for (i = 0; i < blob->n_methods; i++)
1240 if (!validate_function_blob (ctx,
1241 offset + sizeof (StructBlob) +
1242 blob->n_fields * sizeof (FieldBlob) +
1243 i * sizeof (FunctionBlob),
1255 validate_enum_blob (ValidateContext *ctx,
1260 GTypelib *typelib = ctx->typelib;
1265 if (typelib->len < offset + sizeof (EnumBlob))
1269 G_TYPELIB_ERROR_INVALID,
1270 "The buffer is too short");
1274 blob = (EnumBlob*) &typelib->data[offset];
1276 if (blob->blob_type != blob_type)
1280 G_TYPELIB_ERROR_INVALID_BLOB,
1285 if (!blob->unregistered)
1287 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1290 if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1295 if (blob->gtype_name || blob->gtype_init)
1299 G_TYPELIB_ERROR_INVALID_BLOB,
1300 "Gtype data in unregistered enum");
1305 if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1308 if (typelib->len < offset + sizeof (EnumBlob) +
1309 blob->n_values * sizeof (ValueBlob))
1313 G_TYPELIB_ERROR_INVALID,
1314 "The buffer is too short");
1318 push_context (ctx, get_string_nofail (typelib, blob->name));
1320 for (i = 0; i < blob->n_values; i++)
1322 if (!validate_value_blob (typelib,
1323 offset + sizeof (EnumBlob) +
1324 i * sizeof (ValueBlob),
1329 v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1330 i * sizeof (ValueBlob)];
1331 for (j = 0; j < i; j++)
1333 v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
1334 j * sizeof (ValueBlob)];
1336 if (v1->value == v2->value)
1339 /* FIXME should this be an error ? */
1342 G_TYPELIB_ERROR_INVALID_BLOB,
1343 "Duplicate enum value");
1356 validate_object_blob (ValidateContext *ctx,
1360 GTypelib *typelib = ctx->typelib;
1366 header = (Header *)typelib->data;
1368 if (typelib->len < offset + sizeof (ObjectBlob))
1372 G_TYPELIB_ERROR_INVALID,
1373 "The buffer is too short");
1377 blob = (ObjectBlob*) &typelib->data[offset];
1379 if (blob->blob_type != BLOB_TYPE_OBJECT)
1383 G_TYPELIB_ERROR_INVALID_BLOB,
1388 if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1391 if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1394 if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1397 if (blob->parent > header->n_entries)
1401 G_TYPELIB_ERROR_INVALID_BLOB,
1402 "Invalid parent index");
1406 if (blob->parent != 0)
1410 entry = g_typelib_get_dir_entry (typelib, blob->parent);
1411 if (entry->blob_type != BLOB_TYPE_OBJECT &&
1412 (entry->local || entry->blob_type != 0))
1416 G_TYPELIB_ERROR_INVALID_BLOB,
1417 "Parent not object");
1422 if (typelib->len < offset + sizeof (ObjectBlob) +
1423 (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1424 blob->n_fields * sizeof (FieldBlob) +
1425 blob->n_properties * sizeof (PropertyBlob) +
1426 blob->n_methods * sizeof (FunctionBlob) +
1427 blob->n_signals * sizeof (SignalBlob) +
1428 blob->n_vfuncs * sizeof (VFuncBlob) +
1429 blob->n_constants * sizeof (ConstantBlob))
1434 G_TYPELIB_ERROR_INVALID,
1435 "The buffer is too short");
1439 offset2 = offset + sizeof (ObjectBlob);
1441 for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1446 iface = *(guint16*)&typelib->data[offset2];
1447 if (iface == 0 || iface > header->n_entries)
1451 G_TYPELIB_ERROR_INVALID_BLOB,
1452 "Invalid interface index");
1456 entry = g_typelib_get_dir_entry (typelib, iface);
1458 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1459 (entry->local || entry->blob_type != 0))
1463 G_TYPELIB_ERROR_INVALID_BLOB,
1464 "Not an interface");
1469 offset2 += 2 * (blob->n_interfaces %2);
1471 push_context (ctx, get_string_nofail (typelib, blob->name));
1473 for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1475 if (!validate_field_blob (typelib, offset2, error))
1479 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1481 if (!validate_property_blob (typelib, offset2, error))
1485 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1487 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1491 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1493 if (!validate_signal_blob (typelib, offset2, offset, error))
1497 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1499 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1503 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1505 if (!validate_constant_blob (typelib, offset2, error))
1515 validate_interface_blob (ValidateContext *ctx,
1519 GTypelib *typelib = ctx->typelib;
1521 InterfaceBlob *blob;
1525 header = (Header *)typelib->data;
1527 if (typelib->len < offset + sizeof (InterfaceBlob))
1531 G_TYPELIB_ERROR_INVALID,
1532 "The buffer is too short");
1536 blob = (InterfaceBlob*) &typelib->data[offset];
1538 if (blob->blob_type != BLOB_TYPE_INTERFACE)
1542 G_TYPELIB_ERROR_INVALID_BLOB,
1543 "Wrong blob type; expected interface, got %d", blob->blob_type);
1547 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1550 if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1553 if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1556 if (typelib->len < offset + sizeof (InterfaceBlob) +
1557 (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1558 blob->n_properties * sizeof (PropertyBlob) +
1559 blob->n_methods * sizeof (FunctionBlob) +
1560 blob->n_signals * sizeof (SignalBlob) +
1561 blob->n_vfuncs * sizeof (VFuncBlob) +
1562 blob->n_constants * sizeof (ConstantBlob))
1567 G_TYPELIB_ERROR_INVALID,
1568 "The buffer is too short");
1572 offset2 = offset + sizeof (InterfaceBlob);
1574 for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1579 req = *(guint16*)&typelib->data[offset2];
1580 if (req == 0 || req > header->n_entries)
1584 G_TYPELIB_ERROR_INVALID_BLOB,
1585 "Invalid prerequisite index");
1589 entry = g_typelib_get_dir_entry (typelib, req);
1590 if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1591 entry->blob_type != BLOB_TYPE_OBJECT &&
1592 (entry->local || entry->blob_type != 0))
1596 G_TYPELIB_ERROR_INVALID_BLOB,
1597 "Not an interface or object");
1602 offset2 += 2 * (blob->n_prerequisites % 2);
1604 push_context (ctx, get_string_nofail (typelib, blob->name));
1606 for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1608 if (!validate_property_blob (typelib, offset2, error))
1612 for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1614 if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1618 for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1620 if (!validate_signal_blob (typelib, offset2, offset, error))
1624 for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1626 if (!validate_vfunc_blob (typelib, offset2, offset, error))
1630 for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1632 if (!validate_constant_blob (typelib, offset2, error))
1642 validate_errordomain_blob (GTypelib *typelib,
1650 validate_union_blob (GTypelib *typelib,
1658 validate_blob (ValidateContext *ctx,
1662 GTypelib *typelib = ctx->typelib;
1665 if (typelib->len < offset + sizeof (CommonBlob))
1669 G_TYPELIB_ERROR_INVALID,
1670 "The buffer is too short");
1674 common = (CommonBlob*)&typelib->data[offset];
1676 switch (common->blob_type)
1678 case BLOB_TYPE_FUNCTION:
1679 if (!validate_function_blob (ctx, offset, 0, error))
1682 case BLOB_TYPE_CALLBACK:
1683 if (!validate_callback_blob (ctx, offset, error))
1686 case BLOB_TYPE_STRUCT:
1687 case BLOB_TYPE_BOXED:
1688 if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1691 case BLOB_TYPE_ENUM:
1692 case BLOB_TYPE_FLAGS:
1693 if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1696 case BLOB_TYPE_OBJECT:
1697 if (!validate_object_blob (ctx, offset, error))
1700 case BLOB_TYPE_INTERFACE:
1701 if (!validate_interface_blob (ctx, offset, error))
1704 case BLOB_TYPE_CONSTANT:
1705 if (!validate_constant_blob (typelib, offset, error))
1708 case BLOB_TYPE_ERROR_DOMAIN:
1709 if (!validate_errordomain_blob (typelib, offset, error))
1712 case BLOB_TYPE_UNION:
1713 if (!validate_union_blob (typelib, offset, error))
1719 G_TYPELIB_ERROR_INVALID_ENTRY,
1720 "Invalid blob type");
1728 validate_directory (ValidateContext *ctx,
1731 GTypelib *typelib = ctx->typelib;
1732 Header *header = (Header *)typelib->data;
1736 if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1740 G_TYPELIB_ERROR_INVALID,
1741 "The buffer is too short");
1745 for (i = 0; i < header->n_entries; i++)
1747 entry = g_typelib_get_dir_entry (typelib, i + 1);
1749 if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1752 if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1753 entry->blob_type > BLOB_TYPE_UNION)
1757 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1758 "Invalid entry type");
1762 if (i < header->n_local_entries)
1768 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1769 "Too few local directory entries");
1773 if (!is_aligned (entry->offset))
1777 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1778 "Misaligned entry");
1782 if (!validate_blob (ctx, entry->offset, error))
1791 G_TYPELIB_ERROR_INVALID_DIRECTORY,
1792 "Too many local directory entries");
1796 if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1805 validate_annotations (ValidateContext *ctx,
1808 GTypelib *typelib = ctx->typelib;
1809 Header *header = (Header *)typelib->data;
1811 if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
1815 G_TYPELIB_ERROR_INVALID,
1816 "The buffer is too short");
1824 prefix_with_context (GError **error,
1825 const char *section,
1826 ValidateContext *ctx)
1828 GString *str = g_string_new (NULL);
1832 link = ctx->context_stack;
1835 g_prefix_error (error, "In %s:", section);
1839 for (; link; link = link->next)
1841 g_string_append (str, link->data);
1843 g_string_append_c (str, '/');
1845 g_string_append_c (str, ')');
1846 buf = g_string_free (str, FALSE);
1847 g_prefix_error (error, "In %s (Context: %s): ", section, buf);
1852 g_typelib_validate (GTypelib *typelib,
1855 ValidateContext ctx;
1856 ctx.typelib = typelib;
1857 ctx.context_stack = NULL;
1859 if (!validate_header (&ctx, error))
1861 prefix_with_context (error, "In header", &ctx);
1865 if (!validate_directory (&ctx, error))
1867 prefix_with_context (error, "directory", &ctx);
1871 if (!validate_annotations (&ctx, error))
1873 prefix_with_context (error, "annotations", &ctx);
1881 g_typelib_error_quark (void)
1883 static GQuark quark = 0;
1885 quark = g_quark_from_static_string ("g-typelib-error-quark");
1890 _g_typelib_init (GTypelib *typelib)
1894 header = (Header *) typelib->data;
1895 if (header->shared_library)
1897 const gchar *shlib_str;
1898 GModule *app_module = NULL;
1900 shlib_str = g_typelib_get_string (typelib, header->shared_library);
1901 /* note that NULL shlib means to open the main app, which is allowed */
1903 if (shlib_str != NULL)
1908 /* shared-library is a comma-separated list of libraries */
1909 shlibs = g_strsplit (shlib_str, ",", 0);
1911 /* We load all passed libs unconditionally as if the same library is loaded
1912 * again with dlopen(), the same file handle will be returned. See bug:
1913 * http://bugzilla.gnome.org/show_bug.cgi?id=555294
1915 for (i = 0; shlibs[i]; i++)
1919 /* Glade's autoconnect feature and OpenGL's extension mechanism
1920 * as used by Clutter rely on dlopen(NULL) to work as a means of
1921 * accessing the app's symbols. This keeps us from using
1922 * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
1923 * in general libraries are not expecting multiple copies of
1924 * themselves and are not expecting to be unloaded. So we just
1925 * load modules globally for now.
1928 module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
1932 GString *shlib_full = g_string_new (shlibs[i]);
1934 /* Prefix with "lib", try both .la and .so */
1935 if (!g_str_has_prefix (shlib_full->str, "lib"))
1936 g_string_prepend (shlib_full, "lib");
1937 g_string_append (shlib_full, ".la");
1938 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
1940 g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
1941 module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
1943 g_string_free (shlib_full, TRUE);
1948 g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
1949 shlibs[i], g_module_error ());
1953 typelib->modules = g_list_append (typelib->modules, module);
1957 g_strfreev (shlibs);
1960 /* we should make sure the app_module in the end of list so that
1961 * it's last symbol source when loading any symbols from modules.
1962 * See comments in g_typelib_symbol */
1963 app_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
1965 typelib->modules = g_list_append (typelib->modules, app_module);
1970 * g_typelib_new_from_memory:
1971 * @memory: address of memory chunk containing the typelib
1972 * @len: length of memory chunk containing the typelib
1974 * Creates a new #GTypelib from a memory location. The memory block
1975 * pointed to by @typelib will be automatically g_free()d when the
1976 * repository is destroyed.
1978 * Return value: the new #GTypelib
1981 g_typelib_new_from_memory (guchar *memory, gsize len)
1985 meta = g_new0 (GTypelib, 1);
1986 meta->data = memory;
1988 meta->owns_memory = TRUE;
1989 meta->modules = NULL;
1990 _g_typelib_init (meta);
1995 * g_typelib_new_from_const_memory:
1996 * @memory: address of memory chunk containing the typelib
1997 * @len: length of memory chunk containing the typelib
1999 * Creates a new #GTypelib from a memory location.
2001 * Return value: the new #GTypelib
2004 g_typelib_new_from_const_memory (const guchar *memory, gsize len)
2008 meta = g_new0 (GTypelib, 1);
2009 meta->data = (guchar *) memory;
2011 meta->owns_memory = FALSE;
2012 meta->modules = NULL;
2013 _g_typelib_init (meta);
2018 * g_typelib_new_from_mapped_file:
2019 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2021 * Creates a new #GTypelib from a #GMappedFile.
2023 * Return value: the new #GTypelib
2026 g_typelib_new_from_mapped_file (GMappedFile *mfile)
2030 meta = g_new0 (GTypelib, 1);
2031 meta->mfile = mfile;
2032 meta->owns_memory = FALSE;
2033 meta->data = (guchar *) g_mapped_file_get_contents (mfile);
2034 meta->len = g_mapped_file_get_length (mfile);
2035 _g_typelib_init (meta);
2041 * @typelib: a #GTypelib
2046 g_typelib_free (GTypelib *typelib)
2049 g_mapped_file_free (typelib->mfile);
2051 if (typelib->owns_memory)
2052 g_free (typelib->data);
2053 if (typelib->modules)
2055 g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2056 g_list_free (typelib->modules);
2062 g_typelib_get_namespace (GTypelib *typelib)
2064 return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2069 * @symbol_name: name of symbol to be loaded
2070 * @symbol: returns a pointer to the symbol value
2072 * Loads a symbol from #GTypelib.
2074 * Return value: #TRUE on success
2077 g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
2082 * We want to be able to add symbols to an app or an auxiliary
2083 * library to fill in gaps in an introspected library. However,
2084 * normally we would only look for symbols in the main library
2085 * (the first items in typelib->modules).
2087 * A more elaborate solution is probably possible, but as a
2088 * simple approach for now, if we fail to find a symbol we look
2089 * for it in the global module (the last item in type->modules).
2091 * This would not be very efficient if it happened often, since
2092 * we always do the failed lookup above first, but very few
2093 * symbols should be outside of the main libraries in
2094 * typelib->modules so it doesn't matter.
2096 for (l = typelib->modules; l; l = l->next)
2098 GModule *module = l->data;
2100 if (g_module_symbol (module, symbol_name, symbol))