1 /* GObject introspection: metadata validation, auxiliary functions
2 * related to the binary metadata 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.
27 #include "gmetadata.h"
30 #define ALIGN_VALUE(this, boundary) \
31 (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
35 g_metadata_get_dir_entry (GMetadata
*metadata
,
38 Header
*header
= (Header
*)metadata
->data
;
40 return (DirEntry
*)&metadata
->data
[header
->directory
+ (index
- 1) * header
->entry_blob_size
];
44 g_metadata_check_sanity (void)
46 /* Check that struct layout is as we expect */
47 g_assert (sizeof (Header
) == 100);
48 g_assert (sizeof (DirEntry
) == 12);
49 g_assert (sizeof (SimpleTypeBlob
) == 4);
50 g_assert (sizeof (ArgBlob
) == 12);
51 g_assert (sizeof (SignatureBlob
) == 8);
52 g_assert (sizeof (CommonBlob
) == 8);
53 g_assert (sizeof (FunctionBlob
) == 16);
54 g_assert (sizeof (InterfaceTypeBlob
) == 4);
55 g_assert (sizeof (ArrayTypeBlob
) == 8);
56 g_assert (sizeof (ParamTypeBlob
) == 4);
57 g_assert (sizeof (ErrorTypeBlob
) == 4);
58 g_assert (sizeof (ErrorDomainBlob
) == 16);
59 g_assert (sizeof (ValueBlob
) == 12);
60 g_assert (sizeof (FieldBlob
) == 12);
61 g_assert (sizeof (RegisteredTypeBlob
) == 16);
62 g_assert (sizeof (StructBlob
) == 20);
63 g_assert (sizeof (EnumBlob
) == 20);
64 g_assert (sizeof (PropertyBlob
) == 12);
65 g_assert (sizeof (SignalBlob
) == 12);
66 g_assert (sizeof (VFuncBlob
) == 16);
67 g_assert (sizeof (ObjectBlob
) == 32);
68 g_assert (sizeof (InterfaceBlob
) == 28);
69 g_assert (sizeof (ConstantBlob
) == 20);
70 g_assert (sizeof (AnnotationBlob
) == 12);
71 g_assert (sizeof (UnionBlob
) == 28);
76 is_aligned (guint32 offset
)
78 return offset
== ALIGN_VALUE (offset
, 4);
81 #define MAX_NAME_LEN 200
84 is_name (const guchar
*data
, guint32 offset
)
88 name
= (gchar
*)&data
[offset
];
90 if (!memchr (name
, '\0', MAX_NAME_LEN
))
93 if (strspn (name
, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS
"-_") < strlen (name
))
100 validate_header (GMetadata
*metadata
,
105 if (metadata
->len
< sizeof (Header
))
109 G_METADATA_ERROR_INVALID
,
110 "The buffer is too short");
114 header
= (Header
*)metadata
->data
;
116 if (strncmp (header
->magic
, G_IDL_MAGIC
, 16) != 0)
120 G_METADATA_ERROR_INVALID_HEADER
,
121 "Magic string not found");
126 if (header
->major_version
!= 1 || header
->minor_version
!= 0)
130 G_METADATA_ERROR_INVALID_HEADER
,
136 if (header
->n_entries
< header
->n_local_entries
)
140 G_METADATA_ERROR_INVALID_HEADER
,
141 "Inconsistent entry counts");
145 if (header
->size
!= metadata
->len
)
149 G_METADATA_ERROR_INVALID_HEADER
,
150 "Metadata size mismatch");
154 if (header
->entry_blob_size
!= 12 ||
155 header
->function_blob_size
!= 16 ||
156 header
->callback_blob_size
!= 12 ||
157 header
->signal_blob_size
!= 12 ||
158 header
->vfunc_blob_size
!= 16 ||
159 header
->arg_blob_size
!= 12 ||
160 header
->property_blob_size
!= 12 ||
161 header
->field_blob_size
!= 12 ||
162 header
->value_blob_size
!= 12 ||
163 header
->constant_blob_size
!= 20 ||
164 header
->error_domain_blob_size
!= 16 ||
165 header
->annotation_blob_size
!= 12 ||
166 header
->signature_blob_size
!= 8 ||
167 header
->enum_blob_size
!= 20 ||
168 header
->struct_blob_size
!= 20 ||
169 header
->object_blob_size
!= 32 ||
170 header
->interface_blob_size
!= 28 ||
171 header
->union_blob_size
!= 28)
175 G_METADATA_ERROR_INVALID_HEADER
,
176 "Blob size mismatch");
180 if (!is_aligned (header
->directory
))
184 G_METADATA_ERROR_INVALID_HEADER
,
185 "Misaligned directory");
189 if (!is_aligned (header
->annotations
))
193 G_METADATA_ERROR_INVALID_HEADER
,
194 "Misaligned annotations");
198 if (header
->annotations
== 0 && header
->n_annotations
> 0)
202 G_METADATA_ERROR_INVALID_HEADER
,
203 "Wrong number of annotations");
207 if (!is_name (metadata
->data
, header
->namespace))
211 G_METADATA_ERROR_INVALID_HEADER
,
212 "Invalid namespace name");
219 static gboolean
validate_type_blob (GMetadata
*metadata
,
221 guint32 signature_offset
,
222 gboolean return_type
,
226 validate_array_type_blob (GMetadata
*metadata
,
228 guint32 signature_offset
,
229 gboolean return_type
,
234 blob
= (ArrayTypeBlob
*)&metadata
->data
[offset
];
240 G_METADATA_ERROR_INVALID_BLOB
,
241 "Pointer type exected for tag %d", blob
->tag
);
245 /* FIXME validate length */
247 if (!validate_type_blob (metadata
,
248 offset
+ G_STRUCT_OFFSET (ArrayTypeBlob
, type
),
256 validate_iface_type_blob (GMetadata
*metadata
,
258 guint32 signature_offset
,
259 gboolean return_type
,
262 InterfaceTypeBlob
*blob
;
265 header
= (Header
*)metadata
->data
;
267 blob
= (InterfaceTypeBlob
*)&metadata
->data
[offset
];
269 if (blob
->interface
== 0 || blob
->interface
> header
->n_entries
)
273 G_METADATA_ERROR_INVALID_BLOB
,
274 "Invalid directory index %d", blob
->interface
);
282 validate_param_type_blob (GMetadata
*metadata
,
284 guint32 signature_offset
,
285 gboolean return_type
,
292 blob
= (ParamTypeBlob
*)&metadata
->data
[offset
];
298 G_METADATA_ERROR_INVALID_BLOB
,
299 "Pointer type exected for tag %d", blob
->tag
);
303 if (blob
->n_types
!= n_params
)
307 G_METADATA_ERROR_INVALID_BLOB
,
308 "Parameter type number mismatch");
312 for (i
= 0; i
< n_params
; i
++)
314 if (!validate_type_blob (metadata
,
315 offset
+ sizeof (ParamTypeBlob
) +
316 i
* sizeof (SimpleTypeBlob
),
325 validate_error_type_blob (GMetadata
*metadata
,
327 guint32 signature_offset
,
328 gboolean return_type
,
336 blob
= (ErrorTypeBlob
*)&metadata
->data
[offset
];
338 header
= (Header
*)metadata
->data
;
344 G_METADATA_ERROR_INVALID_BLOB
,
345 "Pointer type exected for tag %d", blob
->tag
);
349 for (i
= 0; i
< blob
->n_domains
; i
++)
351 if (blob
->domains
[i
] == 0 || blob
->domains
[i
] > header
->n_entries
)
355 G_METADATA_ERROR_INVALID_BLOB
,
356 "Invalid directory index %d", blob
->domains
[i
]);
360 entry
= g_metadata_get_dir_entry (metadata
, blob
->domains
[i
]);
362 if (entry
->blob_type
!= BLOB_TYPE_ERROR_DOMAIN
&&
363 (entry
->local
|| entry
->blob_type
!= BLOB_TYPE_INVALID
))
367 G_METADATA_ERROR_INVALID_BLOB
,
377 validate_type_blob (GMetadata
*metadata
,
379 guint32 signature_offset
,
380 gboolean return_type
,
383 SimpleTypeBlob
*simple
;
384 InterfaceTypeBlob
*iface
;
386 simple
= (SimpleTypeBlob
*)&metadata
->data
[offset
];
388 if (simple
->reserved
== 0 &&
389 simple
->reserved2
== 0)
391 if (simple
->tag
>= TYPE_TAG_ARRAY
)
395 G_METADATA_ERROR_INVALID_BLOB
,
396 "Wrong tag in simple type");
400 if (simple
->tag
>= TYPE_TAG_UTF8
&&
405 G_METADATA_ERROR_INVALID_BLOB
,
406 "Pointer type exected for tag %d", simple
->tag
);
413 iface
= (InterfaceTypeBlob
*)&metadata
->data
[simple
->offset
];
418 if (!validate_array_type_blob (metadata
, simple
->offset
,
419 signature_offset
, return_type
, error
))
422 case TYPE_TAG_INTERFACE
:
423 if (!validate_iface_type_blob (metadata
, simple
->offset
,
424 signature_offset
, return_type
, error
))
429 if (!validate_param_type_blob (metadata
, simple
->offset
,
430 signature_offset
, return_type
, 1, error
))
434 if (!validate_param_type_blob (metadata
, simple
->offset
,
435 signature_offset
, return_type
, 2, error
))
439 if (!validate_error_type_blob (metadata
, simple
->offset
,
440 signature_offset
, return_type
, error
))
446 G_METADATA_ERROR_INVALID_BLOB
,
447 "Wrong tag in complex type");
455 validate_arg_blob (GMetadata
*metadata
,
457 guint32 signature_offset
,
462 if (metadata
->len
< offset
+ sizeof (ArgBlob
))
466 G_METADATA_ERROR_INVALID
,
467 "The buffer is too short");
471 blob
= (ArgBlob
*) &metadata
->data
[offset
];
473 if (!is_name (metadata
->data
, blob
->name
))
477 G_METADATA_ERROR_INVALID_BLOB
,
478 "Invalid argument name");
482 if (!validate_type_blob (metadata
,
483 offset
+ G_STRUCT_OFFSET (ArgBlob
, arg_type
),
484 signature_offset
, FALSE
, error
))
491 validate_signature_blob (GMetadata
*metadata
,
498 if (metadata
->len
< offset
+ sizeof (SignatureBlob
))
502 G_METADATA_ERROR_INVALID
,
503 "The buffer is too short");
507 blob
= (SignatureBlob
*) &metadata
->data
[offset
];
509 if (blob
->return_type
.offset
!= 0)
511 if (!validate_type_blob (metadata
,
512 offset
+ G_STRUCT_OFFSET (SignatureBlob
, return_type
),
513 offset
, TRUE
, error
))
517 for (i
= 0; i
< blob
->n_arguments
; i
++)
519 if (!validate_arg_blob (metadata
,
520 offset
+ sizeof (SignatureBlob
) +
521 i
* sizeof (ArgBlob
),
527 /* FIXME check constraints on return_value */
528 /* FIXME check array-length pairs */
533 validate_function_blob (GMetadata
*metadata
,
535 guint16 container_type
,
540 if (metadata
->len
< offset
+ sizeof (FunctionBlob
))
544 G_METADATA_ERROR_INVALID
,
545 "The buffer is too short");
549 blob
= (FunctionBlob
*) &metadata
->data
[offset
];
551 if (blob
->blob_type
!= BLOB_TYPE_FUNCTION
)
555 G_METADATA_ERROR_INVALID_BLOB
,
560 if (!is_name (metadata
->data
, blob
->name
))
564 G_METADATA_ERROR_INVALID_BLOB
,
565 "Invalid function name");
569 if (!is_name (metadata
->data
, blob
->symbol
))
573 G_METADATA_ERROR_INVALID_BLOB
,
574 "Invalid function symbol");
578 if (blob
->constructor
)
580 switch (container_type
)
582 case BLOB_TYPE_BOXED
:
583 case BLOB_TYPE_OBJECT
:
584 case BLOB_TYPE_INTERFACE
:
589 G_METADATA_ERROR_INVALID_BLOB
,
590 "Constructor not allowed");
595 if (blob
->setter
|| blob
->getter
|| blob
->wraps_vfunc
)
597 switch (container_type
)
599 case BLOB_TYPE_OBJECT
:
600 case BLOB_TYPE_INTERFACE
:
605 G_METADATA_ERROR_INVALID_BLOB
,
606 "Setter, getter or wrapper not allowed");
613 if (!(blob
->setter
|| blob
->getter
|| blob
->wraps_vfunc
))
617 G_METADATA_ERROR_INVALID_BLOB
,
618 "Must be setter, getter or wrapper");
623 /* FIXME: validate index range */
624 /* FIXME: validate "this" argument for methods */
625 /* FIXME: validate return type for constructors */
627 if (!validate_signature_blob (metadata
, blob
->signature
, error
))
634 validate_callback_blob (GMetadata
*metadata
,
640 if (metadata
->len
< offset
+ sizeof (CallbackBlob
))
644 G_METADATA_ERROR_INVALID
,
645 "The buffer is too short");
649 blob
= (CallbackBlob
*) &metadata
->data
[offset
];
651 if (blob
->blob_type
!= BLOB_TYPE_CALLBACK
)
655 G_METADATA_ERROR_INVALID_BLOB
,
660 if (!is_name (metadata
->data
, blob
->name
))
664 G_METADATA_ERROR_INVALID_BLOB
,
665 "Invalid callback name");
669 if (!validate_signature_blob (metadata
, blob
->signature
, error
))
676 validate_constant_blob (GMetadata
*metadata
,
680 gint value_size
[] = {
681 0, 4, 1, 1, 2, 2, 4, 4, 8, 8,
682 sizeof (gint
), sizeof (guint
),
683 sizeof (glong
), sizeof (gulong
),
684 sizeof (gssize
), sizeof (gsize
),
685 sizeof (gfloat
), sizeof (gdouble
),
689 SimpleTypeBlob
*type
;
691 if (metadata
->len
< offset
+ sizeof (ConstantBlob
))
695 G_METADATA_ERROR_INVALID
,
696 "The buffer is too short");
700 blob
= (ConstantBlob
*) &metadata
->data
[offset
];
702 if (blob
->blob_type
!= BLOB_TYPE_CONSTANT
)
706 G_METADATA_ERROR_INVALID_BLOB
,
711 if (!is_name (metadata
->data
, blob
->name
))
715 G_METADATA_ERROR_INVALID_BLOB
,
716 "Invalid constant name");
720 if (!validate_type_blob (metadata
, offset
+ G_STRUCT_OFFSET (ConstantBlob
, type
),
724 if (!is_aligned (blob
->offset
))
728 G_METADATA_ERROR_INVALID_BLOB
,
729 "Misaligned constant value");
733 type
= (SimpleTypeBlob
*)&metadata
->data
[offset
+ G_STRUCT_OFFSET (ConstantBlob
, type
)];
734 if (type
->reserved
== 0)
740 G_METADATA_ERROR_INVALID_BLOB
,
741 "Constant value type void");
745 if (value_size
[type
->tag
] != 0 &&
746 blob
->size
!= value_size
[type
->tag
])
750 G_METADATA_ERROR_INVALID_BLOB
,
751 "Constant value size mismatch");
754 /* FIXME check string values */
761 validate_value_blob (GMetadata
*metadata
,
767 if (metadata
->len
< offset
+ sizeof (ValueBlob
))
771 G_METADATA_ERROR_INVALID
,
772 "The buffer is too short");
776 blob
= (ValueBlob
*) &metadata
->data
[offset
];
778 if (!is_name (metadata
->data
, blob
->name
))
782 G_METADATA_ERROR_INVALID_BLOB
,
783 "Invalid value name");
791 validate_field_blob (GMetadata
*metadata
,
797 if (metadata
->len
< offset
+ sizeof (FieldBlob
))
801 G_METADATA_ERROR_INVALID
,
802 "The buffer is too short");
806 blob
= (FieldBlob
*) &metadata
->data
[offset
];
808 if (!is_name (metadata
->data
, blob
->name
))
812 G_METADATA_ERROR_INVALID_BLOB
,
813 "Invalid field name");
817 if (!validate_type_blob (metadata
,
818 offset
+ G_STRUCT_OFFSET (FieldBlob
, type
),
826 validate_property_blob (GMetadata
*metadata
,
832 if (metadata
->len
< offset
+ sizeof (PropertyBlob
))
836 G_METADATA_ERROR_INVALID
,
837 "The buffer is too short");
841 blob
= (PropertyBlob
*) &metadata
->data
[offset
];
843 if (!is_name (metadata
->data
, blob
->name
))
847 G_METADATA_ERROR_INVALID_BLOB
,
848 "Invalid property name");
852 if (!validate_type_blob (metadata
,
853 offset
+ G_STRUCT_OFFSET (PropertyBlob
, type
),
861 validate_signal_blob (GMetadata
*metadata
,
863 guint32 container_offset
,
869 if (metadata
->len
< offset
+ sizeof (SignalBlob
))
873 G_METADATA_ERROR_INVALID
,
874 "The buffer is too short");
878 blob
= (SignalBlob
*) &metadata
->data
[offset
];
880 if (!is_name (metadata
->data
, blob
->name
))
884 G_METADATA_ERROR_INVALID_BLOB
,
885 "Invalid signal name");
889 if ((blob
->run_first
!= 0) +
890 (blob
->run_last
!= 0) +
891 (blob
->run_cleanup
!= 0) != 1)
895 G_METADATA_ERROR_INVALID_BLOB
,
896 "Invalid signal run flags");
900 if (blob
->has_class_closure
)
902 if (((CommonBlob
*)&metadata
->data
[container_offset
])->blob_type
== BLOB_TYPE_OBJECT
)
906 object
= (ObjectBlob
*)&metadata
->data
[container_offset
];
908 n_signals
= object
->n_signals
;
912 InterfaceBlob
*iface
;
914 iface
= (InterfaceBlob
*)&metadata
->data
[container_offset
];
916 n_signals
= iface
->n_signals
;
919 if (blob
->class_closure
>= n_signals
)
923 G_METADATA_ERROR_INVALID_BLOB
,
924 "Invalid class closure index");
929 if (!validate_signature_blob (metadata
, blob
->signature
, error
))
936 validate_vfunc_blob (GMetadata
*metadata
,
938 guint32 container_offset
,
944 if (metadata
->len
< offset
+ sizeof (VFuncBlob
))
948 G_METADATA_ERROR_INVALID
,
949 "The buffer is too short");
953 blob
= (VFuncBlob
*) &metadata
->data
[offset
];
955 if (!is_name (metadata
->data
, blob
->name
))
959 G_METADATA_ERROR_INVALID_BLOB
,
960 "Invalid vfunc name");
964 if (blob
->class_closure
)
966 if (((CommonBlob
*)&metadata
->data
[container_offset
])->blob_type
== BLOB_TYPE_OBJECT
)
970 object
= (ObjectBlob
*)&metadata
->data
[container_offset
];
972 n_vfuncs
= object
->n_vfuncs
;
976 InterfaceBlob
*iface
;
978 iface
= (InterfaceBlob
*)&metadata
->data
[container_offset
];
980 n_vfuncs
= iface
->n_vfuncs
;
983 if (blob
->class_closure
>= n_vfuncs
)
987 G_METADATA_ERROR_INVALID_BLOB
,
988 "Invalid class closure index");
993 if (!validate_signature_blob (metadata
, blob
->signature
, error
))
1000 validate_struct_blob (GMetadata
*metadata
,
1008 if (metadata
->len
< offset
+ sizeof (StructBlob
))
1012 G_METADATA_ERROR_INVALID
,
1013 "The buffer is too short");
1017 blob
= (StructBlob
*) &metadata
->data
[offset
];
1019 if (blob
->blob_type
!= blob_type
)
1023 G_METADATA_ERROR_INVALID_BLOB
,
1028 if ((blob
->blob_type
== BLOB_TYPE_BOXED
&& blob
->unregistered
) ||
1029 (blob
->blob_type
== BLOB_TYPE_STRUCT
&& !blob
->unregistered
))
1033 G_METADATA_ERROR_INVALID_BLOB
,
1034 "Registration/blob type mismatch");
1038 if (!is_name (metadata
->data
, blob
->name
))
1042 G_METADATA_ERROR_INVALID_BLOB
,
1043 "Invalid struct name");
1047 if (blob_type
== BLOB_TYPE_BOXED
)
1049 if (!is_name (metadata
->data
, blob
->gtype_name
))
1053 G_METADATA_ERROR_INVALID_BLOB
,
1054 "Invalid boxed type name");
1058 if (!is_name (metadata
->data
, blob
->gtype_init
))
1062 G_METADATA_ERROR_INVALID_BLOB
,
1063 "Invalid boxed type init");
1069 if (blob
->gtype_name
|| blob
->gtype_init
)
1073 G_METADATA_ERROR_INVALID_BLOB
,
1074 "Gtype data in struct");
1079 if (metadata
->len
< offset
+ sizeof (StructBlob
) +
1080 blob
->n_fields
* sizeof (FieldBlob
) +
1081 blob
->n_methods
* sizeof (FunctionBlob
))
1085 G_METADATA_ERROR_INVALID
,
1086 "The buffer is too short");
1090 for (i
= 0; i
< blob
->n_fields
; i
++)
1092 if (!validate_field_blob (metadata
,
1093 offset
+ sizeof (StructBlob
) +
1094 i
* sizeof (FieldBlob
),
1099 for (i
= 0; i
< blob
->n_methods
; i
++)
1101 if (!validate_function_blob (metadata
,
1102 offset
+ sizeof (StructBlob
) +
1103 blob
->n_fields
* sizeof (FieldBlob
) +
1104 i
* sizeof (FunctionBlob
),
1114 validate_enum_blob (GMetadata
*metadata
,
1123 if (metadata
->len
< offset
+ sizeof (EnumBlob
))
1127 G_METADATA_ERROR_INVALID
,
1128 "The buffer is too short");
1132 blob
= (EnumBlob
*) &metadata
->data
[offset
];
1134 if (blob
->blob_type
!= blob_type
)
1138 G_METADATA_ERROR_INVALID_BLOB
,
1143 if (!blob
->unregistered
)
1145 if (!is_name (metadata
->data
, blob
->gtype_name
))
1149 G_METADATA_ERROR_INVALID_BLOB
,
1150 "Invalid enum type name");
1154 if (!is_name (metadata
->data
, blob
->gtype_init
))
1158 G_METADATA_ERROR_INVALID_BLOB
,
1159 "Invalid enum type init");
1165 if (blob
->gtype_name
|| blob
->gtype_init
)
1169 G_METADATA_ERROR_INVALID_BLOB
,
1170 "Gtype data in unregistered enum");
1175 if (!is_name (metadata
->data
, blob
->name
))
1179 G_METADATA_ERROR_INVALID_BLOB
,
1180 "Invalid enum name");
1184 if (metadata
->len
< offset
+ sizeof (EnumBlob
) +
1185 blob
->n_values
* sizeof (ValueBlob
))
1189 G_METADATA_ERROR_INVALID
,
1190 "The buffer is too short");
1194 for (i
= 0; i
< blob
->n_values
; i
++)
1196 if (!validate_value_blob (metadata
,
1197 offset
+ sizeof (EnumBlob
) +
1198 i
* sizeof (ValueBlob
),
1202 v1
= (ValueBlob
*)&metadata
->data
[offset
+ sizeof (EnumBlob
) +
1203 i
* sizeof (ValueBlob
)];
1204 for (j
= 0; j
< i
; j
++)
1206 v2
= (ValueBlob
*)&metadata
->data
[offset
+ sizeof (EnumBlob
) +
1207 j
* sizeof (ValueBlob
)];
1209 if (v1
->value
== v2
->value
)
1211 /* FIXME should this be an error ? */
1214 G_METADATA_ERROR_INVALID_BLOB
,
1215 "Duplicate enum value");
1225 validate_object_blob (GMetadata
*metadata
,
1234 header
= (Header
*)metadata
->data
;
1236 if (metadata
->len
< offset
+ sizeof (ObjectBlob
))
1240 G_METADATA_ERROR_INVALID
,
1241 "The buffer is too short");
1245 blob
= (ObjectBlob
*) &metadata
->data
[offset
];
1247 if (blob
->blob_type
!= BLOB_TYPE_OBJECT
)
1251 G_METADATA_ERROR_INVALID_BLOB
,
1256 if (!is_name (metadata
->data
, blob
->gtype_name
))
1260 G_METADATA_ERROR_INVALID_BLOB
,
1261 "Invalid object type name");
1265 if (!is_name (metadata
->data
, blob
->gtype_init
))
1269 G_METADATA_ERROR_INVALID_BLOB
,
1270 "Invalid object type init");
1274 if (!is_name (metadata
->data
, blob
->name
))
1278 G_METADATA_ERROR_INVALID_BLOB
,
1279 "Invalid object name");
1283 if (blob
->parent
> header
->n_entries
)
1287 G_METADATA_ERROR_INVALID_BLOB
,
1288 "Invalid parent index");
1292 if (blob
->parent
!= 0)
1296 entry
= g_metadata_get_dir_entry (metadata
, blob
->parent
);
1297 if (entry
->blob_type
!= BLOB_TYPE_OBJECT
&&
1298 (entry
->local
|| entry
->blob_type
!= 0))
1302 G_METADATA_ERROR_INVALID_BLOB
,
1303 "Parent not object");
1308 if (metadata
->len
< offset
+ sizeof (ObjectBlob
) +
1309 (blob
->n_interfaces
+ blob
->n_interfaces
% 2) * 2 +
1310 blob
->n_fields
* sizeof (FieldBlob
) +
1311 blob
->n_properties
* sizeof (PropertyBlob
) +
1312 blob
->n_methods
* sizeof (FunctionBlob
) +
1313 blob
->n_signals
* sizeof (SignalBlob
) +
1314 blob
->n_vfuncs
* sizeof (VFuncBlob
) +
1315 blob
->n_constants
* sizeof (ConstantBlob
))
1320 G_METADATA_ERROR_INVALID
,
1321 "The buffer is too short");
1325 offset2
= offset
+ sizeof (ObjectBlob
);
1327 for (i
= 0; i
< blob
->n_interfaces
; i
++, offset2
+= 2)
1332 iface
= *(guint16
*)&metadata
->data
[offset2
];
1333 if (iface
== 0 || iface
> header
->n_entries
)
1337 G_METADATA_ERROR_INVALID_BLOB
,
1338 "Invalid interface index");
1342 entry
= g_metadata_get_dir_entry (metadata
, iface
);
1344 if (entry
->blob_type
!= BLOB_TYPE_INTERFACE
&&
1345 (entry
->local
|| entry
->blob_type
!= 0))
1349 G_METADATA_ERROR_INVALID_BLOB
,
1350 "Not an interface");
1355 offset2
+= 2 * (blob
->n_interfaces
%2);
1357 for (i
= 0; i
< blob
->n_fields
; i
++, offset2
+= sizeof (FieldBlob
))
1359 if (!validate_field_blob (metadata
, offset2
, error
))
1363 for (i
= 0; i
< blob
->n_properties
; i
++, offset2
+= sizeof (PropertyBlob
))
1365 if (!validate_property_blob (metadata
, offset2
, error
))
1369 for (i
= 0; i
< blob
->n_methods
; i
++, offset2
+= sizeof (FunctionBlob
))
1371 if (!validate_function_blob (metadata
, offset2
, BLOB_TYPE_OBJECT
, error
))
1375 for (i
= 0; i
< blob
->n_signals
; i
++, offset2
+= sizeof (SignalBlob
))
1377 if (!validate_signal_blob (metadata
, offset2
, offset
, error
))
1381 for (i
= 0; i
< blob
->n_vfuncs
; i
++, offset2
+= sizeof (VFuncBlob
))
1383 if (!validate_vfunc_blob (metadata
, offset2
, offset
, error
))
1387 for (i
= 0; i
< blob
->n_constants
; i
++, offset2
+= sizeof (ConstantBlob
))
1389 if (!validate_constant_blob (metadata
, offset2
, error
))
1397 validate_interface_blob (GMetadata
*metadata
,
1402 InterfaceBlob
*blob
;
1406 header
= (Header
*)metadata
->data
;
1408 if (metadata
->len
< offset
+ sizeof (InterfaceBlob
))
1412 G_METADATA_ERROR_INVALID
,
1413 "The buffer is too short");
1417 blob
= (InterfaceBlob
*) &metadata
->data
[offset
];
1419 if (blob
->blob_type
!= BLOB_TYPE_INTERFACE
)
1423 G_METADATA_ERROR_INVALID_BLOB
,
1428 if (!is_name (metadata
->data
, blob
->gtype_name
))
1432 G_METADATA_ERROR_INVALID_BLOB
,
1433 "Invalid interface type name");
1437 if (!is_name (metadata
->data
, blob
->gtype_init
))
1441 G_METADATA_ERROR_INVALID_BLOB
,
1442 "Invalid interface type init");
1446 if (!is_name (metadata
->data
, blob
->name
))
1450 G_METADATA_ERROR_INVALID_BLOB
,
1451 "Invalid interface name");
1455 if (metadata
->len
< offset
+ sizeof (InterfaceBlob
) +
1456 (blob
->n_prerequisites
+ blob
->n_prerequisites
% 2) * 2 +
1457 blob
->n_properties
* sizeof (PropertyBlob
) +
1458 blob
->n_methods
* sizeof (FunctionBlob
) +
1459 blob
->n_signals
* sizeof (SignalBlob
) +
1460 blob
->n_vfuncs
* sizeof (VFuncBlob
) +
1461 blob
->n_constants
* sizeof (ConstantBlob
))
1466 G_METADATA_ERROR_INVALID
,
1467 "The buffer is too short");
1471 offset2
= offset
+ sizeof (InterfaceBlob
);
1473 for (i
= 0; i
< blob
->n_prerequisites
; i
++, offset2
+= 2)
1478 req
= *(guint16
*)&metadata
->data
[offset2
];
1479 if (req
== 0 || req
> header
->n_entries
)
1483 G_METADATA_ERROR_INVALID_BLOB
,
1484 "Invalid prerequisite index");
1488 entry
= g_metadata_get_dir_entry (metadata
, req
);
1489 if (entry
->blob_type
!= BLOB_TYPE_INTERFACE
&&
1490 entry
->blob_type
!= BLOB_TYPE_OBJECT
&&
1491 (entry
->local
|| entry
->blob_type
!= 0))
1495 G_METADATA_ERROR_INVALID_BLOB
,
1496 "Not an interface or object");
1501 offset2
+= 2 * (blob
->n_prerequisites
% 2);
1503 for (i
= 0; i
< blob
->n_properties
; i
++, offset2
+= sizeof (PropertyBlob
))
1505 if (!validate_property_blob (metadata
, offset2
, error
))
1509 for (i
= 0; i
< blob
->n_methods
; i
++, offset2
+= sizeof (FunctionBlob
))
1511 if (!validate_function_blob (metadata
, offset2
, BLOB_TYPE_INTERFACE
, error
))
1515 for (i
= 0; i
< blob
->n_signals
; i
++, offset2
+= sizeof (SignalBlob
))
1517 if (!validate_signal_blob (metadata
, offset2
, offset
, error
))
1521 for (i
= 0; i
< blob
->n_vfuncs
; i
++, offset2
+= sizeof (VFuncBlob
))
1523 if (!validate_vfunc_blob (metadata
, offset2
, offset
, error
))
1527 for (i
= 0; i
< blob
->n_constants
; i
++, offset2
+= sizeof (ConstantBlob
))
1529 if (!validate_constant_blob (metadata
, offset2
, error
))
1537 validate_errordomain_blob (GMetadata
*metadata
,
1545 validate_union_blob (GMetadata
*metadata
,
1553 validate_blob (GMetadata
*metadata
,
1559 if (metadata
->len
< offset
+ sizeof (CommonBlob
))
1563 G_METADATA_ERROR_INVALID
,
1564 "The buffer is too short");
1568 common
= (CommonBlob
*)&metadata
->data
[offset
];
1570 switch (common
->blob_type
)
1572 case BLOB_TYPE_FUNCTION
:
1573 if (!validate_function_blob (metadata
, offset
, 0, error
))
1576 case BLOB_TYPE_CALLBACK
:
1577 if (!validate_callback_blob (metadata
, offset
, error
))
1580 case BLOB_TYPE_STRUCT
:
1581 case BLOB_TYPE_BOXED
:
1582 if (!validate_struct_blob (metadata
, offset
, common
->blob_type
, error
))
1585 case BLOB_TYPE_ENUM
:
1586 case BLOB_TYPE_FLAGS
:
1587 if (!validate_enum_blob (metadata
, offset
, common
->blob_type
, error
))
1590 case BLOB_TYPE_OBJECT
:
1591 if (!validate_object_blob (metadata
, offset
, error
))
1594 case BLOB_TYPE_INTERFACE
:
1595 if (!validate_interface_blob (metadata
, offset
, error
))
1598 case BLOB_TYPE_CONSTANT
:
1599 if (!validate_constant_blob (metadata
, offset
, error
))
1602 case BLOB_TYPE_ERROR_DOMAIN
:
1603 if (!validate_errordomain_blob (metadata
, offset
, error
))
1606 case BLOB_TYPE_UNION
:
1607 if (!validate_union_blob (metadata
, offset
, error
))
1613 G_METADATA_ERROR_INVALID_ENTRY
,
1614 "Invalid blob type");
1622 validate_directory (GMetadata
*metadata
,
1625 Header
*header
= (Header
*)metadata
->data
;
1629 if (metadata
->len
< header
->directory
+ header
->n_entries
* sizeof (DirEntry
))
1633 G_METADATA_ERROR_INVALID
,
1634 "The buffer is too short");
1638 for (i
= 0; i
< header
->n_entries
; i
++)
1640 entry
= g_metadata_get_dir_entry (metadata
, i
+ 1);
1642 if (!is_name (metadata
->data
, entry
->name
))
1646 G_METADATA_ERROR_INVALID_DIRECTORY
,
1647 "Invalid entry name");
1651 if ((entry
->local
&& entry
->blob_type
== BLOB_TYPE_INVALID
) ||
1652 entry
->blob_type
> BLOB_TYPE_UNION
)
1656 G_METADATA_ERROR_INVALID_DIRECTORY
,
1657 "Invalid entry type");
1661 if (i
< header
->n_local_entries
)
1667 G_METADATA_ERROR_INVALID_DIRECTORY
,
1668 "Too few local directory entries");
1672 if (!is_aligned (entry
->offset
))
1676 G_METADATA_ERROR_INVALID_DIRECTORY
,
1677 "Misaligned entry");
1681 if (!validate_blob (metadata
, entry
->offset
, error
))
1690 G_METADATA_ERROR_INVALID_DIRECTORY
,
1691 "Too many local directory entries");
1695 if (!is_name (metadata
->data
, entry
->offset
))
1699 G_METADATA_ERROR_INVALID_DIRECTORY
,
1700 "Invalid namespace name");
1710 validate_annotations (GMetadata
*metadata
,
1713 Header
*header
= (Header
*)metadata
->data
;
1715 if (header
->size
< header
->annotations
+ header
->n_annotations
* sizeof (AnnotationBlob
))
1719 G_METADATA_ERROR_INVALID
,
1720 "The buffer is too short");
1728 g_metadata_validate (GMetadata
*metadata
,
1731 if (!validate_header (metadata
, error
))
1734 if (!validate_directory (metadata
, error
))
1737 if (!validate_annotations (metadata
, error
))
1744 g_metadata_error_quark (void)
1746 static GQuark quark
= 0;
1748 quark
= g_quark_from_static_string ("g-metadata-error-quark");
1754 _g_metadata_init (GMetadata
*metadata
)
1758 header
= (Header
*) metadata
->data
;
1759 if (header
->shared_library
)
1762 shlib
= g_metadata_get_string (metadata
, header
->shared_library
);
1763 metadata
->module
= g_module_open (shlib
, G_MODULE_BIND_LAZY
|G_MODULE_BIND_LOCAL
);
1764 if (metadata
->module
== NULL
)
1765 g_warning ("Failed to load shared library referenced by the metadata: %s",
1771 * g_metadata_new_from_memory:
1772 * @memory: address of memory chunk containing the metadata
1773 * @len: length of memory chunk containing the metadata
1775 * Creates a new #GMetadata from a memory location. The memory block
1776 * pointed to by @metadata will be automatically g_free()d when the
1777 * repository is destroyed.
1779 * Return value: the new #GMetadata
1782 g_metadata_new_from_memory (guchar
*memory
, gsize len
)
1786 meta
= g_new0 (GMetadata
, 1);
1787 meta
->data
= memory
;
1789 meta
->owns_memory
= TRUE
;
1790 _g_metadata_init (meta
);
1795 * g_metadata_new_from_const_memory:
1796 * @memory: address of memory chunk containing the metadata
1797 * @len: length of memory chunk containing the metadata
1799 * Creates a new #GMetadata from a memory location.
1801 * Return value: the new #GMetadata
1804 g_metadata_new_from_const_memory (const guchar
*memory
, gsize len
)
1808 meta
= g_new0 (GMetadata
, 1);
1809 meta
->data
= (guchar
*) memory
;
1811 meta
->owns_memory
= FALSE
;
1812 _g_metadata_init (meta
);
1817 * g_metadata_new_from_mapped_file:
1818 * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
1820 * Creates a new #GMetadata from a #GMappedFile.
1822 * Return value: the new #GMetadata
1825 g_metadata_new_from_mapped_file (GMappedFile
*mfile
)
1829 meta
= g_new0 (GMetadata
, 1);
1830 meta
->mfile
= mfile
;
1831 meta
->owns_memory
= FALSE
;
1832 meta
->data
= (guchar
*) g_mapped_file_get_contents (mfile
);
1833 meta
->len
= g_mapped_file_get_length (mfile
);
1834 _g_metadata_init (meta
);
1840 * @metadata: a #GMetadata
1842 * Free a #GMetadata.
1845 g_metadata_free (GMetadata
*metadata
)
1847 if (metadata
->mfile
)
1848 g_mapped_file_unref (metadata
->mfile
);
1850 if (metadata
->owns_memory
)
1851 g_free (metadata
->data
);
1852 if (metadata
->module
)
1853 g_module_close (metadata
->module
);
1858 * g_metadata_set_module:
1859 * @metadata: a #GMetadata instance
1860 * @module: a #GModule; takes ownership of this module
1862 * Sets the target module for all symbols referenced by the metadata.
1865 g_metadata_set_module (GMetadata
*metadata
, GModule
*module
)
1867 if (metadata
->module
)
1868 g_module_close (metadata
->module
);
1869 metadata
->module
= module
;
1873 g_metadata_get_namespace(GMetadata
*metadata
)
1875 return g_metadata_get_string (metadata
, ((Header
*) metadata
->data
)->namespace);