Branch data Line data Source code
1 : : /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 : : * GObject introspection: typelib validation, auxiliary functions
3 : : * related to the binary typelib format
4 : : *
5 : : * Copyright (C) 2005 Matthias Clasen
6 : : *
7 : : * SPDX-License-Identifier: LGPL-2.1-or-later
8 : : *
9 : : * This library is free software; you can redistribute it and/or
10 : : * modify it under the terms of the GNU Lesser General Public
11 : : * License as published by the Free Software Foundation; either
12 : : * version 2 of the License, or (at your option) any later version.
13 : : *
14 : : * This library is distributed in the hope that it will be useful,
15 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : : * Lesser General Public License for more details.
18 : : *
19 : : * You should have received a copy of the GNU Lesser General Public
20 : : * License along with this library; if not, write to the
21 : : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 : : * Boston, MA 02111-1307, USA.
23 : : */
24 : :
25 : : #include "config.h"
26 : :
27 : : #include <stdlib.h>
28 : : #include <string.h>
29 : :
30 : : #include <glib.h>
31 : :
32 : : #include "gitypelib-internal.h"
33 : : #include "gitypelib.h"
34 : :
35 : : /**
36 : : * GITypelib:
37 : : *
38 : : * `GITypelib` represents a loaded `.typelib` file, which contains a description
39 : : * of a single module’s API.
40 : : *
41 : : * Since: 2.80
42 : : */
43 : :
44 : 2 : G_DEFINE_BOXED_TYPE (GITypelib, gi_typelib, gi_typelib_ref, gi_typelib_unref)
45 : :
46 : : typedef struct {
47 : : GITypelib *typelib;
48 : : GSList *context_stack;
49 : : } ValidateContext;
50 : :
51 : : #define ALIGN_VALUE(this, boundary) \
52 : : (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
53 : :
54 : : static void
55 : 5695 : push_context (ValidateContext *ctx, const char *name)
56 : : {
57 : 5695 : ctx->context_stack = g_slist_prepend (ctx->context_stack, (char*)name);
58 : 5695 : }
59 : :
60 : : static void
61 : 5695 : pop_context (ValidateContext *ctx)
62 : : {
63 : 5695 : g_assert (ctx->context_stack != NULL);
64 : 5695 : ctx->context_stack = g_slist_delete_link (ctx->context_stack,
65 : : ctx->context_stack);
66 : 5695 : }
67 : :
68 : : static gboolean
69 : : validate_interface_blob (ValidateContext *ctx,
70 : : uint32_t offset,
71 : : GError **error);
72 : :
73 : : static DirEntry *
74 : 6384 : get_dir_entry_checked (GITypelib *typelib,
75 : : uint16_t index,
76 : : GError **error)
77 : : {
78 : 6384 : Header *header = (Header *)typelib->data;
79 : : uint32_t offset;
80 : :
81 : 6384 : if (index == 0 || index > header->n_entries)
82 : : {
83 : 0 : g_set_error (error,
84 : : GI_TYPELIB_ERROR,
85 : : GI_TYPELIB_ERROR_INVALID_BLOB,
86 : : "Invalid directory index %d", index);
87 : 0 : return FALSE;
88 : : }
89 : :
90 : 6384 : offset = header->directory + (index - 1) * header->entry_blob_size;
91 : :
92 : 6384 : if (typelib->len < offset + sizeof (DirEntry))
93 : : {
94 : 0 : g_set_error (error,
95 : : GI_TYPELIB_ERROR,
96 : : GI_TYPELIB_ERROR_INVALID,
97 : : "The buffer is too short");
98 : 0 : return FALSE;
99 : : }
100 : :
101 : 6384 : return (DirEntry *)&typelib->data[offset];
102 : : }
103 : :
104 : :
105 : : static CommonBlob *
106 : 226 : get_blob (GITypelib *typelib,
107 : : uint32_t offset,
108 : : GError **error)
109 : : {
110 : 226 : if (typelib->len < offset + sizeof (CommonBlob))
111 : : {
112 : 0 : g_set_error (error,
113 : : GI_TYPELIB_ERROR,
114 : : GI_TYPELIB_ERROR_INVALID,
115 : : "The buffer is too short");
116 : 0 : return FALSE;
117 : : }
118 : 226 : return (CommonBlob *)&typelib->data[offset];
119 : : }
120 : :
121 : : static InterfaceTypeBlob *
122 : 226 : get_type_blob (GITypelib *typelib,
123 : : SimpleTypeBlob *simple,
124 : : GError **error)
125 : : {
126 : 226 : if (simple->offset == 0)
127 : : {
128 : 0 : g_set_error (error,
129 : : GI_TYPELIB_ERROR,
130 : : GI_TYPELIB_ERROR_INVALID,
131 : : "Expected blob for type");
132 : 0 : return FALSE;
133 : : }
134 : :
135 : 226 : if (simple->flags.reserved == 0 && simple->flags.reserved2 == 0)
136 : : {
137 : 0 : g_set_error (error,
138 : : GI_TYPELIB_ERROR,
139 : : GI_TYPELIB_ERROR_INVALID,
140 : : "Expected non-basic type but got %d",
141 : 0 : simple->flags.tag);
142 : 0 : return FALSE;
143 : : }
144 : :
145 : 226 : return (InterfaceTypeBlob*) get_blob (typelib, simple->offset, error);
146 : : }
147 : :
148 : : /**
149 : : * gi_typelib_get_dir_entry:
150 : : * @typelib: a #GITypelib
151 : : * @index: index to retrieve
152 : : *
153 : : * Get the typelib directory entry at the given @index.
154 : : *
155 : : * Returns: (transfer none): a `DirEntry`
156 : : * Since: 2.80
157 : : */
158 : : DirEntry *
159 : 14864 : gi_typelib_get_dir_entry (GITypelib *typelib,
160 : : uint16_t index)
161 : : {
162 : 14864 : Header *header = (Header *)typelib->data;
163 : :
164 : 14864 : return (DirEntry *)&typelib->data[header->directory + (index - 1) * header->entry_blob_size];
165 : : }
166 : :
167 : : static Section *
168 : 59 : get_section_by_id (GITypelib *typelib,
169 : : SectionType section_type)
170 : : {
171 : 59 : Header *header = (Header *)typelib->data;
172 : : Section *section;
173 : :
174 : 59 : if (header->sections == 0)
175 : 0 : return NULL;
176 : :
177 : 59 : for (section = (Section*)&typelib->data[header->sections];
178 : 59 : section->id != GI_SECTION_END;
179 : 0 : section++)
180 : : {
181 : 59 : if (section->id == section_type)
182 : 59 : return section;
183 : : }
184 : 0 : return NULL;
185 : : }
186 : :
187 : : /**
188 : : * gi_typelib_get_dir_entry_by_name:
189 : : * @typelib: a #GITypelib
190 : : * @name: name to look up
191 : : *
192 : : * Get the typelib directory entry which has @name.
193 : : *
194 : : * Returns: (transfer none) (nullable): entry corresponding to @name, or `NULL`
195 : : * if none was found
196 : : * Since: 2.80
197 : : */
198 : : DirEntry *
199 : 59 : gi_typelib_get_dir_entry_by_name (GITypelib *typelib,
200 : : const char *name)
201 : : {
202 : : Section *dirindex;
203 : : size_t i, n_entries;
204 : : const char *entry_name;
205 : : DirEntry *entry;
206 : :
207 : 59 : dirindex = get_section_by_id (typelib, GI_SECTION_DIRECTORY_INDEX);
208 : 59 : n_entries = ((Header *)typelib->data)->n_local_entries;
209 : :
210 : 59 : if (dirindex == NULL)
211 : : {
212 : 0 : for (i = 1; i <= n_entries; i++)
213 : : {
214 : 0 : entry = gi_typelib_get_dir_entry (typelib, i);
215 : 0 : entry_name = gi_typelib_get_string (typelib, entry->name);
216 : 0 : if (strcmp (name, entry_name) == 0)
217 : 0 : return entry;
218 : : }
219 : 0 : return NULL;
220 : : }
221 : : else
222 : : {
223 : 59 : uint8_t *hash = (uint8_t *) &typelib->data[dirindex->offset];
224 : : uint16_t index;
225 : :
226 : 59 : index = gi_typelib_hash_search (hash, name, n_entries);
227 : 59 : entry = gi_typelib_get_dir_entry (typelib, index + 1);
228 : 59 : entry_name = gi_typelib_get_string (typelib, entry->name);
229 : 59 : if (strcmp (name, entry_name) == 0)
230 : 58 : return entry;
231 : 1 : return NULL;
232 : : }
233 : : }
234 : :
235 : : /**
236 : : * gi_typelib_get_dir_entry_by_gtype_name:
237 : : * @typelib: a #GITypelib
238 : : * @gtype_name: name of a [type@GObject.Type] to look up
239 : : *
240 : : * Get the typelib directory entry for the [type@GObject.Type] with the given
241 : : * @gtype_name.
242 : : *
243 : : * Returns: (transfer none) (nullable): entry corresponding to @gtype_name, or
244 : : * `NULL` if none was found
245 : : * Since: 2.80
246 : : */
247 : : DirEntry *
248 : 17 : gi_typelib_get_dir_entry_by_gtype_name (GITypelib *typelib,
249 : : const char *gtype_name)
250 : : {
251 : 17 : Header *header = (Header *)typelib->data;
252 : :
253 : 5670 : for (size_t i = 1; i <= header->n_local_entries; i++)
254 : : {
255 : : RegisteredTypeBlob *blob;
256 : : const char *type;
257 : 5658 : DirEntry *entry = gi_typelib_get_dir_entry (typelib, i);
258 : 11316 : if (!BLOB_IS_REGISTERED_TYPE (entry))
259 : 3518 : continue;
260 : :
261 : 2140 : blob = (RegisteredTypeBlob *)(&typelib->data[entry->offset]);
262 : 2140 : if (!blob->gtype_name)
263 : 1076 : continue;
264 : :
265 : 1064 : type = gi_typelib_get_string (typelib, blob->gtype_name);
266 : 1064 : if (strcmp (type, gtype_name) == 0)
267 : 5 : return entry;
268 : : }
269 : 12 : return NULL;
270 : : }
271 : :
272 : : typedef struct {
273 : : const char *s;
274 : : const char *separator;
275 : : size_t sep_len;
276 : : GString buf;
277 : : } StrSplitIter;
278 : :
279 : : static void
280 : 12 : strsplit_iter_init (StrSplitIter *iter,
281 : : const char *s,
282 : : const char *separator)
283 : : {
284 : 12 : iter->s = s;
285 : 12 : iter->separator = separator;
286 : 12 : iter->sep_len = strlen (separator);
287 : 12 : iter->buf.str = NULL;
288 : 12 : iter->buf.len = 0;
289 : 12 : iter->buf.allocated_len = 0;
290 : 12 : }
291 : :
292 : : static gboolean
293 : 15 : strsplit_iter_next (StrSplitIter *iter,
294 : : const char **out_val)
295 : : {
296 : 15 : const char *s = iter->s;
297 : : const char *next;
298 : : size_t len;
299 : :
300 : 15 : if (!s)
301 : 0 : return FALSE;
302 : 15 : next = strstr (s, iter->separator);
303 : 15 : if (next)
304 : : {
305 : 3 : iter->s = next + iter->sep_len;
306 : 3 : len = next - s;
307 : : }
308 : : else
309 : : {
310 : 12 : iter->s = NULL;
311 : 12 : len = strlen (s);
312 : : }
313 : 15 : if (len == 0)
314 : : {
315 : 0 : *out_val = "";
316 : : }
317 : : else
318 : : {
319 : 15 : g_string_overwrite_len (&iter->buf, 0, s, (gssize)len + 1);
320 : 15 : iter->buf.str[len] = '\0';
321 : 15 : *out_val = iter->buf.str;
322 : : }
323 : 15 : return TRUE;
324 : : }
325 : :
326 : : static void
327 : 12 : strsplit_iter_clear (StrSplitIter *iter)
328 : : {
329 : 12 : g_free (iter->buf.str);
330 : 12 : }
331 : :
332 : : /**
333 : : * gi_typelib_matches_gtype_name_prefix:
334 : : * @typelib: a #GITypelib
335 : : * @gtype_name: name of a [type@GObject.Type]
336 : : *
337 : : * Check whether the symbol prefix for @typelib is a prefix of the given
338 : : * @gtype_name.
339 : : *
340 : : * Returns: `TRUE` if the prefix for @typelib prefixes @gtype_name
341 : : * Since: 2.80
342 : : */
343 : : gboolean
344 : 12 : gi_typelib_matches_gtype_name_prefix (GITypelib *typelib,
345 : : const char *gtype_name)
346 : : {
347 : 12 : Header *header = (Header *)typelib->data;
348 : : const char *c_prefix;
349 : : const char *prefix;
350 : 12 : gboolean ret = FALSE;
351 : : StrSplitIter split_iter;
352 : : size_t gtype_name_len;
353 : :
354 : 12 : c_prefix = gi_typelib_get_string (typelib, header->c_prefix);
355 : 12 : if (c_prefix == NULL || strlen (c_prefix) == 0)
356 : 0 : return FALSE;
357 : :
358 : 12 : gtype_name_len = strlen (gtype_name);
359 : :
360 : : /* c_prefix is a comma separated string of supported prefixes
361 : : * in the typelib.
362 : : * We match the specified gtype_name if the gtype_name starts
363 : : * with the prefix, and is followed by a capital letter.
364 : : * For example, a typelib offering the 'Gdk' prefix does match
365 : : * GdkX11Cursor, however a typelib offering the 'G' prefix does not.
366 : : */
367 : 12 : strsplit_iter_init (&split_iter, c_prefix, ",");
368 : 15 : while (strsplit_iter_next (&split_iter, &prefix))
369 : : {
370 : 15 : size_t len = strlen (prefix);
371 : :
372 : 15 : if (gtype_name_len < len)
373 : 0 : continue;
374 : :
375 : 15 : if (strncmp (prefix, gtype_name, len) != 0)
376 : 3 : continue;
377 : :
378 : 12 : if (g_ascii_isupper (gtype_name[len]))
379 : : {
380 : 12 : ret = TRUE;
381 : 12 : break;
382 : : }
383 : : }
384 : 12 : strsplit_iter_clear (&split_iter);
385 : 12 : return ret;
386 : : }
387 : :
388 : : /**
389 : : * gi_typelib_get_dir_entry_by_error_domain:
390 : : * @typelib: a #GITypelib
391 : : * @error_domain: name of a [type@GLib.Error] domain to look up
392 : : *
393 : : * Get the typelib directory entry for the [type@GLib.Error] domain with the
394 : : * given @error_domain name.
395 : : *
396 : : * Returns: (transfer none) (nullable): entry corresponding to @error_domain, or
397 : : * `NULL` if none was found
398 : : * Since: 2.80
399 : : */
400 : : DirEntry *
401 : 12 : gi_typelib_get_dir_entry_by_error_domain (GITypelib *typelib,
402 : : GQuark error_domain)
403 : : {
404 : 12 : Header *header = (Header *)typelib->data;
405 : 12 : size_t n_entries = header->n_local_entries;
406 : 12 : const char *domain_string = g_quark_to_string (error_domain);
407 : : DirEntry *entry;
408 : :
409 : 4873 : for (size_t i = 1; i <= n_entries; i++)
410 : : {
411 : : EnumBlob *blob;
412 : : const char *enum_domain_string;
413 : :
414 : 4862 : entry = gi_typelib_get_dir_entry (typelib, i);
415 : 4862 : if (entry->blob_type != BLOB_TYPE_ENUM)
416 : 4671 : continue;
417 : :
418 : 191 : blob = (EnumBlob *)(&typelib->data[entry->offset]);
419 : 191 : if (!blob->error_domain)
420 : 146 : continue;
421 : :
422 : 45 : enum_domain_string = gi_typelib_get_string (typelib, blob->error_domain);
423 : 45 : if (strcmp (domain_string, enum_domain_string) == 0)
424 : 1 : return entry;
425 : : }
426 : 11 : return NULL;
427 : : }
428 : :
429 : : /* When changing the size of a typelib structure, you are required to update
430 : : * the hardcoded size here. Do NOT change these to use sizeof(); these
431 : : * should match whatever is defined in the text specification and serve as
432 : : * a sanity check on structure modifications.
433 : : *
434 : : * Everything else in the code however should be using sizeof().
435 : : */
436 : :
437 : : G_STATIC_ASSERT (sizeof (Header) == 112);
438 : : G_STATIC_ASSERT (sizeof (DirEntry) == 12);
439 : : G_STATIC_ASSERT (sizeof (SimpleTypeBlob) == 4);
440 : : G_STATIC_ASSERT (sizeof (ArgBlob) == 16);
441 : : G_STATIC_ASSERT (sizeof (SignatureBlob) == 8);
442 : : G_STATIC_ASSERT (sizeof (CommonBlob) == 8);
443 : : G_STATIC_ASSERT (sizeof (FunctionBlob) == 20);
444 : : G_STATIC_ASSERT (sizeof (CallbackBlob) == 12);
445 : : G_STATIC_ASSERT (sizeof (InterfaceTypeBlob) == 4);
446 : : G_STATIC_ASSERT (sizeof (ArrayTypeBlob) == 8);
447 : : G_STATIC_ASSERT (sizeof (ParamTypeBlob) == 4);
448 : : G_STATIC_ASSERT (sizeof (ErrorTypeBlob) == 4);
449 : : G_STATIC_ASSERT (sizeof (ValueBlob) == 12);
450 : : G_STATIC_ASSERT (sizeof (FieldBlob) == 16);
451 : : G_STATIC_ASSERT (sizeof (RegisteredTypeBlob) == 16);
452 : : G_STATIC_ASSERT (sizeof (StructBlob) == 32);
453 : : G_STATIC_ASSERT (sizeof (EnumBlob) == 24);
454 : : G_STATIC_ASSERT (sizeof (PropertyBlob) == 16);
455 : : G_STATIC_ASSERT (sizeof (SignalBlob) == 16);
456 : : G_STATIC_ASSERT (sizeof (VFuncBlob) == 20);
457 : : G_STATIC_ASSERT (sizeof (ObjectBlob) == 60);
458 : : G_STATIC_ASSERT (sizeof (InterfaceBlob) == 40);
459 : : G_STATIC_ASSERT (sizeof (ConstantBlob) == 24);
460 : : G_STATIC_ASSERT (sizeof (AttributeBlob) == 12);
461 : : G_STATIC_ASSERT (sizeof (UnionBlob) == 40);
462 : :
463 : : static gboolean
464 : 2932 : is_aligned (uint32_t offset)
465 : : {
466 : 2932 : return offset == ALIGN_VALUE (offset, 4);
467 : : }
468 : :
469 : : #define MAX_NAME_LEN 2048
470 : :
471 : : static const char *
472 : 31898 : get_string (GITypelib *typelib, uint32_t offset, GError **error)
473 : : {
474 : 31898 : if (typelib->len < offset)
475 : : {
476 : 0 : g_set_error (error,
477 : : GI_TYPELIB_ERROR,
478 : : GI_TYPELIB_ERROR_INVALID,
479 : : "Buffer is too short while looking up name");
480 : 0 : return NULL;
481 : : }
482 : :
483 : 31898 : return (const char*)&typelib->data[offset];
484 : : }
485 : :
486 : : static const char *
487 : 5695 : get_string_nofail (GITypelib *typelib, uint32_t offset)
488 : : {
489 : 5695 : const char *ret = get_string (typelib, offset, NULL);
490 : 5695 : g_assert (ret);
491 : 5695 : return ret;
492 : : }
493 : :
494 : : static gboolean
495 : 26203 : validate_name (GITypelib *typelib,
496 : : const char *msg,
497 : : const uint8_t *data,
498 : : uint32_t offset,
499 : : GError **error)
500 : : {
501 : : const char *name;
502 : :
503 : 26203 : name = get_string (typelib, offset, error);
504 : 26203 : if (!name)
505 : 0 : return FALSE;
506 : :
507 : 26203 : if (!memchr (name, '\0', MAX_NAME_LEN))
508 : : {
509 : 0 : g_set_error (error,
510 : : GI_TYPELIB_ERROR,
511 : : GI_TYPELIB_ERROR_INVALID,
512 : : "The %s is too long: %s",
513 : : msg, name);
514 : 0 : return FALSE;
515 : : }
516 : :
517 : 26203 : if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
518 : : {
519 : 0 : g_set_error (error,
520 : : GI_TYPELIB_ERROR,
521 : : GI_TYPELIB_ERROR_INVALID,
522 : : "The %s contains invalid characters: '%s'",
523 : : msg, name);
524 : 0 : return FALSE;
525 : : }
526 : :
527 : 26203 : return TRUE;
528 : : }
529 : :
530 : : /* Fast path sanity check, operates on a memory blob */
531 : : static gboolean
532 : 208 : validate_header_basic (const uint8_t *memory,
533 : : size_t len,
534 : : GError **error)
535 : : {
536 : 208 : Header *header = (Header *)memory;
537 : :
538 : 208 : if (len < sizeof (Header))
539 : : {
540 : 0 : g_set_error (error,
541 : : GI_TYPELIB_ERROR,
542 : : GI_TYPELIB_ERROR_INVALID,
543 : : "The specified typelib length %zu is too short", len);
544 : 0 : return FALSE;
545 : : }
546 : :
547 : 208 : if (strncmp (header->magic, GI_IR_MAGIC, 16) != 0)
548 : : {
549 : 0 : g_set_error (error,
550 : : GI_TYPELIB_ERROR,
551 : : GI_TYPELIB_ERROR_INVALID_HEADER,
552 : : "Invalid magic header");
553 : 0 : return FALSE;
554 : :
555 : : }
556 : :
557 : 208 : if (header->major_version != 4)
558 : : {
559 : 0 : g_set_error (error,
560 : : GI_TYPELIB_ERROR,
561 : : GI_TYPELIB_ERROR_INVALID_HEADER,
562 : : "Typelib version mismatch; expected 4, found %d",
563 : 0 : header->major_version);
564 : 0 : return FALSE;
565 : :
566 : : }
567 : :
568 : 208 : if (header->n_entries < header->n_local_entries)
569 : : {
570 : 0 : g_set_error (error,
571 : : GI_TYPELIB_ERROR,
572 : : GI_TYPELIB_ERROR_INVALID_HEADER,
573 : : "Inconsistent entry counts");
574 : 0 : return FALSE;
575 : : }
576 : :
577 : 208 : if (header->size != len)
578 : : {
579 : 0 : g_set_error (error,
580 : : GI_TYPELIB_ERROR,
581 : : GI_TYPELIB_ERROR_INVALID_HEADER,
582 : : "Typelib size %zu does not match %zu",
583 : 0 : (size_t) header->size, len);
584 : 0 : return FALSE;
585 : : }
586 : :
587 : : /* This is a sanity check for a specific typelib; it
588 : : * prevents us from loading an incompatible typelib.
589 : : *
590 : : * The hardcoded static checks to protect against inadvertent
591 : : * or buggy changes to the typelib format itself.
592 : : */
593 : :
594 : 208 : if (header->entry_blob_size != sizeof (DirEntry) ||
595 : 208 : header->function_blob_size != sizeof (FunctionBlob) ||
596 : 208 : header->callback_blob_size != sizeof (CallbackBlob) ||
597 : 208 : header->signal_blob_size != sizeof (SignalBlob) ||
598 : 208 : header->vfunc_blob_size != sizeof (VFuncBlob) ||
599 : 208 : header->arg_blob_size != sizeof (ArgBlob) ||
600 : 208 : header->property_blob_size != sizeof (PropertyBlob) ||
601 : 208 : header->field_blob_size != sizeof (FieldBlob) ||
602 : 208 : header->value_blob_size != sizeof (ValueBlob) ||
603 : 208 : header->constant_blob_size != sizeof (ConstantBlob) ||
604 : 208 : header->attribute_blob_size != sizeof (AttributeBlob) ||
605 : 208 : header->signature_blob_size != sizeof (SignatureBlob) ||
606 : 208 : header->enum_blob_size != sizeof (EnumBlob) ||
607 : 208 : header->struct_blob_size != sizeof (StructBlob) ||
608 : 208 : header->object_blob_size != sizeof(ObjectBlob) ||
609 : 208 : header->interface_blob_size != sizeof (InterfaceBlob) ||
610 : 208 : header->union_blob_size != sizeof (UnionBlob))
611 : : {
612 : 0 : g_set_error (error,
613 : : GI_TYPELIB_ERROR,
614 : : GI_TYPELIB_ERROR_INVALID_HEADER,
615 : : "Blob size mismatch");
616 : 0 : return FALSE;
617 : : }
618 : :
619 : 208 : if (!is_aligned (header->directory))
620 : : {
621 : 0 : g_set_error (error,
622 : : GI_TYPELIB_ERROR,
623 : : GI_TYPELIB_ERROR_INVALID_HEADER,
624 : : "Misaligned directory");
625 : 0 : return FALSE;
626 : : }
627 : :
628 : 208 : if (!is_aligned (header->attributes))
629 : : {
630 : 0 : g_set_error (error,
631 : : GI_TYPELIB_ERROR,
632 : : GI_TYPELIB_ERROR_INVALID_HEADER,
633 : : "Misaligned attributes");
634 : 0 : return FALSE;
635 : : }
636 : :
637 : 208 : if (header->attributes == 0 && header->n_attributes > 0)
638 : : {
639 : 0 : g_set_error (error,
640 : : GI_TYPELIB_ERROR,
641 : : GI_TYPELIB_ERROR_INVALID_HEADER,
642 : : "Wrong number of attributes");
643 : 0 : return FALSE;
644 : : }
645 : :
646 : 208 : return TRUE;
647 : : }
648 : :
649 : : static gboolean
650 : 7 : validate_header (ValidateContext *ctx,
651 : : GError **error)
652 : : {
653 : 7 : GITypelib *typelib = ctx->typelib;
654 : :
655 : 7 : if (!validate_header_basic (typelib->data, typelib->len, error))
656 : 0 : return FALSE;
657 : :
658 : : {
659 : 7 : Header *header = (Header*)typelib->data;
660 : 7 : if (!validate_name (typelib, "namespace", typelib->data, header->namespace, error))
661 : 0 : return FALSE;
662 : : }
663 : :
664 : 7 : return TRUE;
665 : : }
666 : :
667 : : static gboolean validate_type_blob (GITypelib *typelib,
668 : : uint32_t offset,
669 : : uint32_t signature_offset,
670 : : gboolean return_type,
671 : : GError **error);
672 : :
673 : : static gboolean
674 : 534 : validate_array_type_blob (GITypelib *typelib,
675 : : uint32_t offset,
676 : : uint32_t signature_offset,
677 : : gboolean return_type,
678 : : GError **error)
679 : : {
680 : : /* FIXME validate length */
681 : :
682 : 534 : if (!validate_type_blob (typelib,
683 : : offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
684 : : 0, FALSE, error))
685 : 0 : return FALSE;
686 : :
687 : 534 : return TRUE;
688 : : }
689 : :
690 : : static gboolean
691 : 6047 : validate_iface_type_blob (GITypelib *typelib,
692 : : uint32_t offset,
693 : : uint32_t signature_offset,
694 : : gboolean return_type,
695 : : GError **error)
696 : : {
697 : : InterfaceTypeBlob *blob;
698 : : InterfaceBlob *target;
699 : :
700 : 6047 : blob = (InterfaceTypeBlob*)&typelib->data[offset];
701 : :
702 : 6047 : target = (InterfaceBlob*) get_dir_entry_checked (typelib, blob->interface, error);
703 : :
704 : 6047 : if (!target)
705 : 0 : return FALSE;
706 : 6047 : if (target->blob_type == 0) /* non-local */
707 : 767 : return TRUE;
708 : :
709 : 5280 : return TRUE;
710 : : }
711 : :
712 : : static gboolean
713 : 164 : validate_param_type_blob (GITypelib *typelib,
714 : : uint32_t offset,
715 : : uint32_t signature_offset,
716 : : gboolean return_type,
717 : : size_t n_params,
718 : : GError **error)
719 : : {
720 : : ParamTypeBlob *blob;
721 : :
722 : 164 : blob = (ParamTypeBlob*)&typelib->data[offset];
723 : :
724 : 164 : if (!blob->pointer)
725 : : {
726 : 0 : g_set_error (error,
727 : : GI_TYPELIB_ERROR,
728 : : GI_TYPELIB_ERROR_INVALID_BLOB,
729 : 0 : "Pointer type exected for tag %d", blob->tag);
730 : 0 : return FALSE;
731 : : }
732 : :
733 : 164 : if (blob->n_types != n_params)
734 : : {
735 : 0 : g_set_error (error,
736 : : GI_TYPELIB_ERROR,
737 : : GI_TYPELIB_ERROR_INVALID_BLOB,
738 : : "Parameter type number mismatch");
739 : 0 : return FALSE;
740 : : }
741 : :
742 : 381 : for (size_t i = 0; i < n_params; i++)
743 : : {
744 : 217 : if (!validate_type_blob (typelib,
745 : 217 : offset + sizeof (ParamTypeBlob) +
746 : : i * sizeof (SimpleTypeBlob),
747 : : 0, FALSE, error))
748 : 0 : return FALSE;
749 : : }
750 : :
751 : 164 : return TRUE;
752 : : }
753 : :
754 : : static gboolean
755 : 33 : validate_error_type_blob (GITypelib *typelib,
756 : : uint32_t offset,
757 : : uint32_t signature_offset,
758 : : gboolean return_type,
759 : : GError **error)
760 : : {
761 : : ErrorTypeBlob *blob;
762 : :
763 : 33 : blob = (ErrorTypeBlob*)&typelib->data[offset];
764 : :
765 : 33 : if (!blob->pointer)
766 : : {
767 : 0 : g_set_error (error,
768 : : GI_TYPELIB_ERROR,
769 : : GI_TYPELIB_ERROR_INVALID_BLOB,
770 : 0 : "Pointer type exected for tag %d", blob->tag);
771 : 0 : return FALSE;
772 : : }
773 : :
774 : 33 : return TRUE;
775 : : }
776 : :
777 : : static gboolean
778 : 15262 : validate_type_blob (GITypelib *typelib,
779 : : uint32_t offset,
780 : : uint32_t signature_offset,
781 : : gboolean return_type,
782 : : GError **error)
783 : : {
784 : : SimpleTypeBlob *simple;
785 : : InterfaceTypeBlob *iface;
786 : :
787 : 15262 : simple = (SimpleTypeBlob *)&typelib->data[offset];
788 : :
789 : 15262 : if (simple->flags.reserved == 0 &&
790 : 8545 : simple->flags.reserved2 == 0)
791 : : {
792 : 8484 : if (!GI_TYPE_TAG_IS_BASIC(simple->flags.tag))
793 : : {
794 : 0 : g_set_error (error,
795 : : GI_TYPELIB_ERROR,
796 : : GI_TYPELIB_ERROR_INVALID_BLOB,
797 : 0 : "Invalid non-basic tag %d in simple type", simple->flags.tag);
798 : 0 : return FALSE;
799 : : }
800 : :
801 : 8484 : if (simple->flags.tag >= GI_TYPE_TAG_UTF8 &&
802 : 2869 : simple->flags.tag != GI_TYPE_TAG_UNICHAR &&
803 : 2809 : !simple->flags.pointer)
804 : : {
805 : 0 : g_set_error (error,
806 : : GI_TYPELIB_ERROR,
807 : : GI_TYPELIB_ERROR_INVALID_BLOB,
808 : 0 : "Pointer type exected for tag %d", simple->flags.tag);
809 : 0 : return FALSE;
810 : : }
811 : :
812 : 8484 : return TRUE;
813 : : }
814 : :
815 : 6778 : iface = (InterfaceTypeBlob*)&typelib->data[simple->offset];
816 : :
817 : 6778 : switch (iface->tag)
818 : : {
819 : 534 : case GI_TYPE_TAG_ARRAY:
820 : 534 : if (!validate_array_type_blob (typelib, simple->offset,
821 : : signature_offset, return_type, error))
822 : 0 : return FALSE;
823 : 534 : break;
824 : 6047 : case GI_TYPE_TAG_INTERFACE:
825 : 6047 : if (!validate_iface_type_blob (typelib, simple->offset,
826 : : signature_offset, return_type, error))
827 : 0 : return FALSE;
828 : 6047 : break;
829 : 111 : case GI_TYPE_TAG_GLIST:
830 : : case GI_TYPE_TAG_GSLIST:
831 : 111 : if (!validate_param_type_blob (typelib, simple->offset,
832 : : signature_offset, return_type, 1, error))
833 : 0 : return FALSE;
834 : 111 : break;
835 : 53 : case GI_TYPE_TAG_GHASH:
836 : 53 : if (!validate_param_type_blob (typelib, simple->offset,
837 : : signature_offset, return_type, 2, error))
838 : 0 : return FALSE;
839 : 53 : break;
840 : 33 : case GI_TYPE_TAG_ERROR:
841 : 33 : if (!validate_error_type_blob (typelib, simple->offset,
842 : : signature_offset, return_type, error))
843 : 0 : return FALSE;
844 : 33 : break;
845 : 0 : default:
846 : 0 : g_set_error (error,
847 : : GI_TYPELIB_ERROR,
848 : : GI_TYPELIB_ERROR_INVALID_BLOB,
849 : : "Wrong tag in complex type");
850 : 0 : return FALSE;
851 : : }
852 : :
853 : 6778 : return TRUE;
854 : : }
855 : :
856 : : static gboolean
857 : 9004 : validate_arg_blob (GITypelib *typelib,
858 : : uint32_t offset,
859 : : uint32_t signature_offset,
860 : : GError **error)
861 : : {
862 : : ArgBlob *blob;
863 : :
864 : 9004 : if (typelib->len < offset + sizeof (ArgBlob))
865 : : {
866 : 0 : g_set_error (error,
867 : : GI_TYPELIB_ERROR,
868 : : GI_TYPELIB_ERROR_INVALID,
869 : : "The buffer is too short");
870 : 0 : return FALSE;
871 : : }
872 : :
873 : 9004 : blob = (ArgBlob*) &typelib->data[offset];
874 : :
875 : 9004 : if (!validate_name (typelib, "argument", typelib->data, blob->name, error))
876 : 0 : return FALSE;
877 : :
878 : 9004 : if (!validate_type_blob (typelib,
879 : : offset + G_STRUCT_OFFSET (ArgBlob, arg_type),
880 : : signature_offset, FALSE, error))
881 : 0 : return FALSE;
882 : :
883 : 9004 : return TRUE;
884 : : }
885 : :
886 : : static SimpleTypeBlob *
887 : 226 : return_type_from_signature (GITypelib *typelib,
888 : : uint32_t offset,
889 : : GError **error)
890 : : {
891 : : SignatureBlob *blob;
892 : 226 : if (typelib->len < offset + sizeof (SignatureBlob))
893 : : {
894 : 0 : g_set_error (error,
895 : : GI_TYPELIB_ERROR,
896 : : GI_TYPELIB_ERROR_INVALID,
897 : : "The buffer is too short");
898 : 0 : return NULL;
899 : : }
900 : :
901 : 226 : blob = (SignatureBlob*) &typelib->data[offset];
902 : 226 : if (blob->return_type.offset == 0)
903 : : {
904 : 0 : g_set_error (error,
905 : : GI_TYPELIB_ERROR,
906 : : GI_TYPELIB_ERROR_INVALID,
907 : : "No return type found in signature");
908 : 0 : return NULL;
909 : : }
910 : :
911 : 226 : return (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (SignatureBlob, return_type)];
912 : : }
913 : :
914 : : static gboolean
915 : 5567 : validate_signature_blob (GITypelib *typelib,
916 : : uint32_t offset,
917 : : GError **error)
918 : : {
919 : : SignatureBlob *blob;
920 : :
921 : 5567 : if (typelib->len < offset + sizeof (SignatureBlob))
922 : : {
923 : 0 : g_set_error (error,
924 : : GI_TYPELIB_ERROR,
925 : : GI_TYPELIB_ERROR_INVALID,
926 : : "The buffer is too short");
927 : 0 : return FALSE;
928 : : }
929 : :
930 : 5567 : blob = (SignatureBlob*) &typelib->data[offset];
931 : :
932 : 5567 : if (blob->return_type.offset != 0)
933 : : {
934 : 3918 : if (!validate_type_blob (typelib,
935 : : offset + G_STRUCT_OFFSET (SignatureBlob, return_type),
936 : : offset, TRUE, error))
937 : 0 : return FALSE;
938 : : }
939 : :
940 : 14571 : for (size_t i = 0; i < blob->n_arguments; i++)
941 : : {
942 : 9004 : if (!validate_arg_blob (typelib,
943 : 9004 : offset + sizeof (SignatureBlob) +
944 : : i * sizeof (ArgBlob),
945 : : offset,
946 : : error))
947 : 0 : return FALSE;
948 : : }
949 : :
950 : : /* FIXME check constraints on return_value */
951 : : /* FIXME check array-length pairs */
952 : 5567 : return TRUE;
953 : : }
954 : :
955 : : static gboolean
956 : 4198 : validate_function_blob (ValidateContext *ctx,
957 : : uint32_t offset,
958 : : uint16_t container_type,
959 : : GError **error)
960 : : {
961 : 4198 : GITypelib *typelib = ctx->typelib;
962 : : FunctionBlob *blob;
963 : :
964 : 4198 : if (typelib->len < offset + sizeof (FunctionBlob))
965 : : {
966 : 0 : g_set_error (error,
967 : : GI_TYPELIB_ERROR,
968 : : GI_TYPELIB_ERROR_INVALID,
969 : : "The buffer is too short");
970 : 0 : return FALSE;
971 : : }
972 : :
973 : 4198 : blob = (FunctionBlob*) &typelib->data[offset];
974 : :
975 : 4198 : if (blob->blob_type != BLOB_TYPE_FUNCTION)
976 : : {
977 : 0 : g_set_error (error,
978 : : GI_TYPELIB_ERROR,
979 : : GI_TYPELIB_ERROR_INVALID_BLOB,
980 : 0 : "Wrong blob type %d, expected function", blob->blob_type);
981 : 0 : return FALSE;
982 : : }
983 : :
984 : 4198 : if (!validate_name (typelib, "function", typelib->data, blob->name, error))
985 : 0 : return FALSE;
986 : :
987 : 4198 : push_context (ctx, get_string_nofail (typelib, blob->name));
988 : :
989 : 4198 : if (!validate_name (typelib, "function symbol", typelib->data, blob->symbol, error))
990 : 0 : return FALSE;
991 : :
992 : 4198 : if (blob->constructor)
993 : : {
994 : 226 : switch (container_type)
995 : : {
996 : 226 : case BLOB_TYPE_BOXED:
997 : : case BLOB_TYPE_STRUCT:
998 : : case BLOB_TYPE_UNION:
999 : : case BLOB_TYPE_OBJECT:
1000 : : case BLOB_TYPE_INTERFACE:
1001 : 226 : break;
1002 : 0 : default:
1003 : 0 : g_set_error (error,
1004 : : GI_TYPELIB_ERROR,
1005 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1006 : : "Constructor not allowed");
1007 : 0 : return FALSE;
1008 : : }
1009 : : }
1010 : :
1011 : 4198 : if (blob->setter || blob->getter || blob->wraps_vfunc)
1012 : : {
1013 : 260 : switch (container_type)
1014 : : {
1015 : 260 : case BLOB_TYPE_OBJECT:
1016 : : case BLOB_TYPE_INTERFACE:
1017 : 260 : break;
1018 : 0 : default:
1019 : 0 : g_set_error (error,
1020 : : GI_TYPELIB_ERROR,
1021 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1022 : : "Setter, getter or wrapper not allowed");
1023 : 0 : return FALSE;
1024 : : }
1025 : : }
1026 : :
1027 : 4198 : if (blob->index)
1028 : : {
1029 : 193 : if (!(blob->setter || blob->getter || blob->wraps_vfunc))
1030 : : {
1031 : 0 : g_set_error (error,
1032 : : GI_TYPELIB_ERROR,
1033 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1034 : : "Must be setter, getter or wrapper");
1035 : 0 : return FALSE;
1036 : : }
1037 : : }
1038 : :
1039 : : /* FIXME: validate index range */
1040 : :
1041 : 4198 : if (!validate_signature_blob (typelib, blob->signature, error))
1042 : 0 : return FALSE;
1043 : :
1044 : 4198 : if (blob->constructor)
1045 : : {
1046 : 226 : SimpleTypeBlob *simple = return_type_from_signature (typelib,
1047 : : blob->signature,
1048 : : error);
1049 : : InterfaceTypeBlob *iface_type;
1050 : :
1051 : 226 : if (!simple)
1052 : 0 : return FALSE;
1053 : 226 : iface_type = get_type_blob (typelib, simple, error);
1054 : 226 : if (!iface_type)
1055 : 0 : return FALSE;
1056 : 226 : if (iface_type->tag != GI_TYPE_TAG_INTERFACE &&
1057 : 1 : (container_type == BLOB_TYPE_OBJECT ||
1058 : : container_type == BLOB_TYPE_INTERFACE))
1059 : : {
1060 : 0 : g_set_error (error,
1061 : : GI_TYPELIB_ERROR,
1062 : : GI_TYPELIB_ERROR_INVALID,
1063 : : "Invalid return type '%s' for constructor '%s'",
1064 : 0 : gi_type_tag_to_string (iface_type->tag),
1065 : : get_string_nofail (typelib, blob->symbol));
1066 : 0 : return FALSE;
1067 : : }
1068 : : }
1069 : :
1070 : 4198 : pop_context (ctx);
1071 : :
1072 : 4198 : return TRUE;
1073 : : }
1074 : :
1075 : : static gboolean
1076 : 731 : validate_callback_blob (ValidateContext *ctx,
1077 : : uint32_t offset,
1078 : : GError **error)
1079 : : {
1080 : 731 : GITypelib *typelib = ctx->typelib;
1081 : : CallbackBlob *blob;
1082 : :
1083 : 731 : if (typelib->len < offset + sizeof (CallbackBlob))
1084 : : {
1085 : 0 : g_set_error (error,
1086 : : GI_TYPELIB_ERROR,
1087 : : GI_TYPELIB_ERROR_INVALID,
1088 : : "The buffer is too short");
1089 : 0 : return FALSE;
1090 : : }
1091 : :
1092 : 731 : blob = (CallbackBlob*) &typelib->data[offset];
1093 : :
1094 : 731 : if (blob->blob_type != BLOB_TYPE_CALLBACK)
1095 : : {
1096 : 0 : g_set_error (error,
1097 : : GI_TYPELIB_ERROR,
1098 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1099 : : "Wrong blob type");
1100 : 0 : return FALSE;
1101 : : }
1102 : :
1103 : 731 : if (!validate_name (typelib, "callback", typelib->data, blob->name, error))
1104 : 0 : return FALSE;
1105 : :
1106 : 731 : push_context (ctx, get_string_nofail (typelib, blob->name));
1107 : :
1108 : 731 : if (!validate_signature_blob (typelib, blob->signature, error))
1109 : 0 : return FALSE;
1110 : :
1111 : 731 : pop_context (ctx);
1112 : :
1113 : 731 : return TRUE;
1114 : : }
1115 : :
1116 : : static gboolean
1117 : 293 : validate_constant_blob (GITypelib *typelib,
1118 : : uint32_t offset,
1119 : : GError **error)
1120 : : {
1121 : 293 : size_t value_size[] = {
1122 : : 0, /* VOID */
1123 : : 4, /* BOOLEAN */
1124 : : 1, /* INT8 */
1125 : : 1, /* UINT8 */
1126 : : 2, /* INT16 */
1127 : : 2, /* UINT16 */
1128 : : 4, /* INT32 */
1129 : : 4, /* UINT32 */
1130 : : 8, /* INT64 */
1131 : : 8, /* UINT64 */
1132 : : sizeof (float),
1133 : : sizeof (double),
1134 : : 0, /* GTYPE */
1135 : : 0, /* UTF8 */
1136 : : 0, /* FILENAME */
1137 : : 0, /* ARRAY */
1138 : : 0, /* INTERFACE */
1139 : : 0, /* GLIST */
1140 : : 0, /* GSLIST */
1141 : : 0, /* GHASH */
1142 : : 0, /* ERROR */
1143 : : 4 /* UNICHAR */
1144 : : };
1145 : : ConstantBlob *blob;
1146 : : SimpleTypeBlob *type;
1147 : :
1148 : : g_assert (G_N_ELEMENTS (value_size) == GI_TYPE_TAG_N_TYPES);
1149 : :
1150 : 293 : if (typelib->len < offset + sizeof (ConstantBlob))
1151 : : {
1152 : 0 : g_set_error (error,
1153 : : GI_TYPELIB_ERROR,
1154 : : GI_TYPELIB_ERROR_INVALID,
1155 : : "The buffer is too short");
1156 : 0 : return FALSE;
1157 : : }
1158 : :
1159 : 293 : blob = (ConstantBlob*) &typelib->data[offset];
1160 : :
1161 : 293 : if (blob->blob_type != BLOB_TYPE_CONSTANT)
1162 : : {
1163 : 0 : g_set_error (error,
1164 : : GI_TYPELIB_ERROR,
1165 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1166 : : "Wrong blob type");
1167 : 0 : return FALSE;
1168 : : }
1169 : :
1170 : 293 : if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
1171 : 0 : return FALSE;
1172 : :
1173 : 293 : if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type),
1174 : : 0, FALSE, error))
1175 : 0 : return FALSE;
1176 : :
1177 : 293 : if (!is_aligned (blob->offset))
1178 : : {
1179 : 0 : g_set_error (error,
1180 : : GI_TYPELIB_ERROR,
1181 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1182 : : "Misaligned constant value");
1183 : 0 : return FALSE;
1184 : : }
1185 : :
1186 : 293 : type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
1187 : 293 : if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
1188 : : {
1189 : 293 : if (type->flags.tag == 0)
1190 : : {
1191 : 0 : g_set_error (error,
1192 : : GI_TYPELIB_ERROR,
1193 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1194 : : "Constant value type void");
1195 : 0 : return FALSE;
1196 : : }
1197 : :
1198 : 293 : if (value_size[type->flags.tag] != 0 &&
1199 : 107 : blob->size != value_size[type->flags.tag])
1200 : : {
1201 : 0 : g_set_error (error,
1202 : : GI_TYPELIB_ERROR,
1203 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1204 : : "Constant value size mismatch");
1205 : 0 : return FALSE;
1206 : : }
1207 : : /* FIXME check string values */
1208 : : }
1209 : :
1210 : 293 : return TRUE;
1211 : : }
1212 : :
1213 : : static gboolean
1214 : 1297 : validate_value_blob (GITypelib *typelib,
1215 : : uint32_t offset,
1216 : : GError **error)
1217 : : {
1218 : : ValueBlob *blob;
1219 : :
1220 : 1297 : if (typelib->len < offset + sizeof (ValueBlob))
1221 : : {
1222 : 0 : g_set_error (error,
1223 : : GI_TYPELIB_ERROR,
1224 : : GI_TYPELIB_ERROR_INVALID,
1225 : : "The buffer is too short");
1226 : 0 : return FALSE;
1227 : : }
1228 : :
1229 : 1297 : blob = (ValueBlob*) &typelib->data[offset];
1230 : :
1231 : 1297 : if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1232 : 0 : return FALSE;
1233 : :
1234 : 1297 : return TRUE;
1235 : : }
1236 : :
1237 : : static gboolean
1238 : 1608 : validate_field_blob (ValidateContext *ctx,
1239 : : uint32_t offset,
1240 : : GError **error)
1241 : : {
1242 : 1608 : GITypelib *typelib = ctx->typelib;
1243 : 1608 : Header *header = (Header *)typelib->data;
1244 : : FieldBlob *blob;
1245 : :
1246 : 1608 : if (typelib->len < offset + sizeof (FieldBlob))
1247 : : {
1248 : 0 : g_set_error (error,
1249 : : GI_TYPELIB_ERROR,
1250 : : GI_TYPELIB_ERROR_INVALID,
1251 : : "The buffer is too short");
1252 : 0 : return FALSE;
1253 : : }
1254 : :
1255 : 1608 : blob = (FieldBlob*) &typelib->data[offset];
1256 : :
1257 : 1608 : if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1258 : 0 : return FALSE;
1259 : :
1260 : 1608 : if (blob->has_embedded_type)
1261 : : {
1262 : 602 : if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
1263 : 0 : return FALSE;
1264 : : }
1265 : 1006 : else if (!validate_type_blob (typelib,
1266 : : offset + G_STRUCT_OFFSET (FieldBlob, type),
1267 : : 0, FALSE, error))
1268 : 0 : return FALSE;
1269 : :
1270 : 1608 : return TRUE;
1271 : : }
1272 : :
1273 : : static gboolean
1274 : 290 : validate_property_blob (GITypelib *typelib,
1275 : : uint32_t offset,
1276 : : GError **error)
1277 : : {
1278 : : PropertyBlob *blob;
1279 : :
1280 : 290 : if (typelib->len < offset + sizeof (PropertyBlob))
1281 : : {
1282 : 0 : g_set_error (error,
1283 : : GI_TYPELIB_ERROR,
1284 : : GI_TYPELIB_ERROR_INVALID,
1285 : : "The buffer is too short");
1286 : 0 : return FALSE;
1287 : : }
1288 : :
1289 : 290 : blob = (PropertyBlob*) &typelib->data[offset];
1290 : :
1291 : 290 : if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1292 : 0 : return FALSE;
1293 : :
1294 : 290 : if (!validate_type_blob (typelib,
1295 : : offset + G_STRUCT_OFFSET (PropertyBlob, type),
1296 : : 0, FALSE, error))
1297 : 0 : return FALSE;
1298 : :
1299 : 290 : return TRUE;
1300 : : }
1301 : :
1302 : : static gboolean
1303 : 86 : validate_signal_blob (GITypelib *typelib,
1304 : : uint32_t offset,
1305 : : uint32_t container_offset,
1306 : : GError **error)
1307 : : {
1308 : : SignalBlob *blob;
1309 : : size_t n_signals;
1310 : :
1311 : 86 : if (typelib->len < offset + sizeof (SignalBlob))
1312 : : {
1313 : 0 : g_set_error (error,
1314 : : GI_TYPELIB_ERROR,
1315 : : GI_TYPELIB_ERROR_INVALID,
1316 : : "The buffer is too short");
1317 : 0 : return FALSE;
1318 : : }
1319 : :
1320 : 86 : blob = (SignalBlob*) &typelib->data[offset];
1321 : :
1322 : 86 : if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1323 : 0 : return FALSE;
1324 : :
1325 : 86 : if ((blob->run_first != 0) +
1326 : 86 : (blob->run_last != 0) +
1327 : 86 : (blob->run_cleanup != 0) != 1)
1328 : : {
1329 : 0 : g_set_error (error,
1330 : : GI_TYPELIB_ERROR,
1331 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1332 : : "Invalid signal run flags");
1333 : 0 : return FALSE;
1334 : : }
1335 : :
1336 : 86 : if (blob->has_class_closure)
1337 : : {
1338 : 0 : if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1339 : : {
1340 : : ObjectBlob *object;
1341 : :
1342 : 0 : object = (ObjectBlob*)&typelib->data[container_offset];
1343 : :
1344 : 0 : n_signals = object->n_signals;
1345 : : }
1346 : : else
1347 : : {
1348 : : InterfaceBlob *iface;
1349 : :
1350 : 0 : iface = (InterfaceBlob*)&typelib->data[container_offset];
1351 : :
1352 : 0 : n_signals = iface->n_signals;
1353 : : }
1354 : :
1355 : 0 : if (blob->class_closure >= n_signals)
1356 : : {
1357 : 0 : g_set_error (error,
1358 : : GI_TYPELIB_ERROR,
1359 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1360 : : "Invalid class closure index");
1361 : 0 : return FALSE;
1362 : : }
1363 : : }
1364 : :
1365 : 86 : if (!validate_signature_blob (typelib, blob->signature, error))
1366 : 0 : return FALSE;
1367 : :
1368 : 86 : return TRUE;
1369 : : }
1370 : :
1371 : : static gboolean
1372 : 552 : validate_vfunc_blob (GITypelib *typelib,
1373 : : uint32_t offset,
1374 : : uint32_t container_offset,
1375 : : GError **error)
1376 : : {
1377 : : VFuncBlob *blob;
1378 : : size_t n_vfuncs;
1379 : :
1380 : 552 : if (typelib->len < offset + sizeof (VFuncBlob))
1381 : : {
1382 : 0 : g_set_error (error,
1383 : : GI_TYPELIB_ERROR,
1384 : : GI_TYPELIB_ERROR_INVALID,
1385 : : "The buffer is too short");
1386 : 0 : return FALSE;
1387 : : }
1388 : :
1389 : 552 : blob = (VFuncBlob*) &typelib->data[offset];
1390 : :
1391 : 552 : if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1392 : 0 : return FALSE;
1393 : :
1394 : 552 : if (blob->class_closure)
1395 : : {
1396 : 0 : if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1397 : : {
1398 : : ObjectBlob *object;
1399 : :
1400 : 0 : object = (ObjectBlob*)&typelib->data[container_offset];
1401 : :
1402 : 0 : n_vfuncs = object->n_vfuncs;
1403 : : }
1404 : : else
1405 : : {
1406 : : InterfaceBlob *iface;
1407 : :
1408 : 0 : iface = (InterfaceBlob*)&typelib->data[container_offset];
1409 : :
1410 : 0 : n_vfuncs = iface->n_vfuncs;
1411 : : }
1412 : :
1413 : 0 : if (blob->class_closure >= n_vfuncs)
1414 : : {
1415 : 0 : g_set_error (error,
1416 : : GI_TYPELIB_ERROR,
1417 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1418 : : "Invalid class closure index");
1419 : 0 : return FALSE;
1420 : : }
1421 : : }
1422 : :
1423 : 552 : if (!validate_signature_blob (typelib, blob->signature, error))
1424 : 0 : return FALSE;
1425 : :
1426 : 552 : return TRUE;
1427 : : }
1428 : :
1429 : : static gboolean
1430 : 393 : validate_struct_blob (ValidateContext *ctx,
1431 : : uint32_t offset,
1432 : : uint16_t blob_type,
1433 : : GError **error)
1434 : : {
1435 : 393 : GITypelib *typelib = ctx->typelib;
1436 : : StructBlob *blob;
1437 : : size_t i;
1438 : : uint32_t field_offset;
1439 : :
1440 : 393 : if (typelib->len < offset + sizeof (StructBlob))
1441 : : {
1442 : 0 : g_set_error (error,
1443 : : GI_TYPELIB_ERROR,
1444 : : GI_TYPELIB_ERROR_INVALID,
1445 : : "The buffer is too short");
1446 : 0 : return FALSE;
1447 : : }
1448 : :
1449 : 393 : blob = (StructBlob*) &typelib->data[offset];
1450 : :
1451 : 393 : if (blob->blob_type != blob_type)
1452 : : {
1453 : 0 : g_set_error (error,
1454 : : GI_TYPELIB_ERROR,
1455 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1456 : : "Wrong blob type");
1457 : 0 : return FALSE;
1458 : : }
1459 : :
1460 : 393 : if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1461 : 0 : return FALSE;
1462 : :
1463 : 393 : push_context (ctx, get_string_nofail (typelib, blob->name));
1464 : :
1465 : 393 : if (!blob->unregistered)
1466 : : {
1467 : 92 : if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1468 : 0 : return FALSE;
1469 : :
1470 : 92 : if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1471 : 0 : return FALSE;
1472 : : }
1473 : : else
1474 : : {
1475 : 301 : if (blob->gtype_name || blob->gtype_init)
1476 : : {
1477 : 0 : g_set_error (error,
1478 : : GI_TYPELIB_ERROR,
1479 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1480 : : "Gtype data in struct");
1481 : 0 : return FALSE;
1482 : : }
1483 : : }
1484 : :
1485 : 393 : if (typelib->len < offset + sizeof (StructBlob) +
1486 : 393 : blob->n_fields * sizeof (FieldBlob) +
1487 : 393 : blob->n_methods * sizeof (FunctionBlob))
1488 : : {
1489 : 0 : g_set_error (error,
1490 : : GI_TYPELIB_ERROR,
1491 : : GI_TYPELIB_ERROR_INVALID,
1492 : : "The buffer is too short");
1493 : 0 : return FALSE;
1494 : : }
1495 : :
1496 : 393 : field_offset = offset + sizeof (StructBlob);
1497 : 1753 : for (i = 0; i < blob->n_fields; i++)
1498 : : {
1499 : 1360 : FieldBlob *field_blob = (FieldBlob*) &typelib->data[field_offset];
1500 : :
1501 : 1360 : if (!validate_field_blob (ctx,
1502 : : field_offset,
1503 : : error))
1504 : 0 : return FALSE;
1505 : :
1506 : 1360 : field_offset += sizeof (FieldBlob);
1507 : 1360 : if (field_blob->has_embedded_type)
1508 : 602 : field_offset += sizeof (CallbackBlob);
1509 : : }
1510 : :
1511 : 1676 : for (i = 0; i < blob->n_methods; i++)
1512 : : {
1513 : 1283 : if (!validate_function_blob (ctx,
1514 : : field_offset +
1515 : : i * sizeof (FunctionBlob),
1516 : : blob_type,
1517 : : error))
1518 : 0 : return FALSE;
1519 : : }
1520 : :
1521 : 393 : pop_context (ctx);
1522 : :
1523 : 393 : return TRUE;
1524 : : }
1525 : :
1526 : : static gboolean
1527 : 166 : validate_enum_blob (ValidateContext *ctx,
1528 : : uint32_t offset,
1529 : : uint16_t blob_type,
1530 : : GError **error)
1531 : : {
1532 : 166 : GITypelib *typelib = ctx->typelib;
1533 : : EnumBlob *blob;
1534 : : uint32_t offset2;
1535 : :
1536 : 166 : if (typelib->len < offset + sizeof (EnumBlob))
1537 : : {
1538 : 0 : g_set_error (error,
1539 : : GI_TYPELIB_ERROR,
1540 : : GI_TYPELIB_ERROR_INVALID,
1541 : : "The buffer is too short");
1542 : 0 : return FALSE;
1543 : : }
1544 : :
1545 : 166 : blob = (EnumBlob*) &typelib->data[offset];
1546 : :
1547 : 166 : if (blob->blob_type != blob_type)
1548 : : {
1549 : 0 : g_set_error (error,
1550 : : GI_TYPELIB_ERROR,
1551 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1552 : : "Wrong blob type");
1553 : 0 : return FALSE;
1554 : : }
1555 : :
1556 : 166 : if (!blob->unregistered)
1557 : : {
1558 : 89 : if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1559 : 0 : return FALSE;
1560 : :
1561 : 89 : if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1562 : 0 : return FALSE;
1563 : : }
1564 : : else
1565 : : {
1566 : 77 : if (blob->gtype_name || blob->gtype_init)
1567 : : {
1568 : 0 : g_set_error (error,
1569 : : GI_TYPELIB_ERROR,
1570 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1571 : : "Gtype data in unregistered enum");
1572 : 0 : return FALSE;
1573 : : }
1574 : : }
1575 : :
1576 : 166 : if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1577 : 0 : return FALSE;
1578 : :
1579 : 166 : if (typelib->len < offset + sizeof (EnumBlob) +
1580 : 166 : blob->n_values * sizeof (ValueBlob) +
1581 : 166 : blob->n_methods * sizeof (FunctionBlob))
1582 : : {
1583 : 0 : g_set_error (error,
1584 : : GI_TYPELIB_ERROR,
1585 : : GI_TYPELIB_ERROR_INVALID,
1586 : : "The buffer is too short");
1587 : 0 : return FALSE;
1588 : : }
1589 : :
1590 : 166 : offset2 = offset + sizeof (EnumBlob);
1591 : :
1592 : 166 : push_context (ctx, get_string_nofail (typelib, blob->name));
1593 : :
1594 : 1463 : for (size_t i = 0; i < blob->n_values; i++, offset2 += sizeof (ValueBlob))
1595 : : {
1596 : 1297 : if (!validate_value_blob (typelib,
1597 : : offset2,
1598 : : error))
1599 : 0 : return FALSE;
1600 : :
1601 : : #if 0
1602 : : v1 = (ValueBlob *)&typelib->data[offset2];
1603 : : for (j = 0; j < i; j++)
1604 : : {
1605 : : v2 = (ValueBlob *)&typelib->data[offset2 +
1606 : : j * sizeof (ValueBlob)];
1607 : :
1608 : : if (v1->value == v2->value)
1609 : : {
1610 : :
1611 : : /* FIXME should this be an error ? */
1612 : : g_set_error (error,
1613 : : GI_TYPELIB_ERROR,
1614 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1615 : : "Duplicate enum value");
1616 : : return FALSE;
1617 : : }
1618 : : }
1619 : : #endif
1620 : : }
1621 : :
1622 : 181 : for (size_t i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1623 : : {
1624 : 15 : if (!validate_function_blob (ctx, offset2, BLOB_TYPE_ENUM, error))
1625 : 0 : return FALSE;
1626 : : }
1627 : :
1628 : 166 : pop_context (ctx);
1629 : :
1630 : 166 : return TRUE;
1631 : : }
1632 : :
1633 : : static gboolean
1634 : 165 : validate_object_blob (ValidateContext *ctx,
1635 : : uint32_t offset,
1636 : : GError **error)
1637 : : {
1638 : 165 : GITypelib *typelib = ctx->typelib;
1639 : : Header *header;
1640 : : ObjectBlob *blob;
1641 : : size_t i;
1642 : : uint32_t offset2;
1643 : : uint16_t n_field_callbacks;
1644 : :
1645 : 165 : header = (Header *)typelib->data;
1646 : :
1647 : 165 : if (typelib->len < offset + sizeof (ObjectBlob))
1648 : : {
1649 : 0 : g_set_error (error,
1650 : : GI_TYPELIB_ERROR,
1651 : : GI_TYPELIB_ERROR_INVALID,
1652 : : "The buffer is too short");
1653 : 0 : return FALSE;
1654 : : }
1655 : :
1656 : 165 : blob = (ObjectBlob*) &typelib->data[offset];
1657 : :
1658 : 165 : if (blob->blob_type != BLOB_TYPE_OBJECT)
1659 : : {
1660 : 0 : g_set_error (error,
1661 : : GI_TYPELIB_ERROR,
1662 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1663 : : "Wrong blob type");
1664 : 0 : return FALSE;
1665 : : }
1666 : :
1667 : 165 : if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1668 : 0 : return FALSE;
1669 : :
1670 : 165 : if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1671 : 0 : return FALSE;
1672 : :
1673 : 165 : if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1674 : 0 : return FALSE;
1675 : :
1676 : 165 : if (blob->parent > header->n_entries)
1677 : : {
1678 : 0 : g_set_error (error,
1679 : : GI_TYPELIB_ERROR,
1680 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1681 : : "Invalid parent index");
1682 : 0 : return FALSE;
1683 : : }
1684 : :
1685 : 165 : if (blob->parent != 0)
1686 : : {
1687 : : DirEntry *entry;
1688 : :
1689 : 162 : entry = get_dir_entry_checked (typelib, blob->parent, error);
1690 : 162 : if (!entry)
1691 : 0 : return FALSE;
1692 : 162 : if (entry->blob_type != BLOB_TYPE_OBJECT &&
1693 : 80 : (entry->local || entry->blob_type != 0))
1694 : : {
1695 : 0 : g_set_error (error,
1696 : : GI_TYPELIB_ERROR,
1697 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1698 : : "Parent not object");
1699 : 0 : return FALSE;
1700 : : }
1701 : : }
1702 : :
1703 : 165 : if (blob->gtype_struct != 0)
1704 : : {
1705 : : DirEntry *entry;
1706 : :
1707 : 101 : entry = get_dir_entry_checked (typelib, blob->gtype_struct, error);
1708 : 101 : if (!entry)
1709 : 0 : return FALSE;
1710 : 101 : if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1711 : : {
1712 : 0 : g_set_error (error,
1713 : : GI_TYPELIB_ERROR,
1714 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1715 : : "Class struct invalid type or not local");
1716 : 0 : return FALSE;
1717 : : }
1718 : : }
1719 : :
1720 : 165 : if (typelib->len < offset + sizeof (ObjectBlob) +
1721 : 165 : (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1722 : 165 : blob->n_fields * sizeof (FieldBlob) +
1723 : 165 : blob->n_properties * sizeof (PropertyBlob) +
1724 : 165 : blob->n_methods * sizeof (FunctionBlob) +
1725 : 165 : blob->n_signals * sizeof (SignalBlob) +
1726 : 165 : blob->n_vfuncs * sizeof (VFuncBlob) +
1727 : 165 : blob->n_constants * sizeof (ConstantBlob))
1728 : :
1729 : : {
1730 : 0 : g_set_error (error,
1731 : : GI_TYPELIB_ERROR,
1732 : : GI_TYPELIB_ERROR_INVALID,
1733 : : "The buffer is too short");
1734 : 0 : return FALSE;
1735 : : }
1736 : :
1737 : 165 : offset2 = offset + sizeof (ObjectBlob);
1738 : :
1739 : 239 : for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1740 : : {
1741 : : uint16_t iface;
1742 : : DirEntry *entry;
1743 : :
1744 : 74 : iface = *(uint16_t *)&typelib->data[offset2];
1745 : 74 : if (iface == 0 || iface > header->n_entries)
1746 : : {
1747 : 0 : g_set_error (error,
1748 : : GI_TYPELIB_ERROR,
1749 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1750 : : "Invalid interface index");
1751 : 0 : return FALSE;
1752 : : }
1753 : :
1754 : 74 : entry = get_dir_entry_checked (typelib, iface, error);
1755 : 74 : if (!entry)
1756 : 0 : return FALSE;
1757 : :
1758 : 74 : if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1759 : 4 : (entry->local || entry->blob_type != 0))
1760 : : {
1761 : 0 : g_set_error (error,
1762 : : GI_TYPELIB_ERROR,
1763 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1764 : : "Not an interface");
1765 : 0 : return FALSE;
1766 : : }
1767 : : }
1768 : :
1769 : 165 : offset2 += 2 * (blob->n_interfaces %2);
1770 : :
1771 : 165 : push_context (ctx, get_string_nofail (typelib, blob->name));
1772 : :
1773 : 165 : n_field_callbacks = 0;
1774 : 413 : for (i = 0; i < blob->n_fields; i++)
1775 : : {
1776 : 248 : FieldBlob *field_blob = (FieldBlob*) &typelib->data[offset2];
1777 : :
1778 : 248 : if (!validate_field_blob (ctx, offset2, error))
1779 : 0 : return FALSE;
1780 : :
1781 : 248 : offset2 += sizeof (FieldBlob);
1782 : : /* Special case fields which are callbacks. */
1783 : 248 : if (field_blob->has_embedded_type) {
1784 : 0 : offset2 += sizeof (CallbackBlob);
1785 : 0 : n_field_callbacks++;
1786 : : }
1787 : : }
1788 : :
1789 : 165 : if (blob->n_field_callbacks != n_field_callbacks)
1790 : : {
1791 : 0 : g_set_error (error,
1792 : : GI_TYPELIB_ERROR,
1793 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1794 : : "Incorrect number of field callbacks; expected "
1795 : : "%" G_GUINT16_FORMAT ", got %" G_GUINT16_FORMAT,
1796 : 0 : blob->n_field_callbacks, n_field_callbacks);
1797 : 0 : return FALSE;
1798 : : }
1799 : :
1800 : 423 : for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1801 : : {
1802 : 258 : if (!validate_property_blob (typelib, offset2, error))
1803 : 0 : return FALSE;
1804 : : }
1805 : :
1806 : 1609 : for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1807 : : {
1808 : 1444 : if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1809 : 0 : return FALSE;
1810 : : }
1811 : :
1812 : 228 : for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1813 : : {
1814 : 63 : if (!validate_signal_blob (typelib, offset2, offset, error))
1815 : 0 : return FALSE;
1816 : : }
1817 : :
1818 : 402 : for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1819 : : {
1820 : 237 : if (!validate_vfunc_blob (typelib, offset2, offset, error))
1821 : 0 : return FALSE;
1822 : : }
1823 : :
1824 : 165 : for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1825 : : {
1826 : 0 : if (!validate_constant_blob (typelib, offset2, error))
1827 : 0 : return FALSE;
1828 : : }
1829 : :
1830 : 165 : pop_context (ctx);
1831 : :
1832 : 165 : return TRUE;
1833 : : }
1834 : :
1835 : : static gboolean
1836 : 42 : validate_interface_blob (ValidateContext *ctx,
1837 : : uint32_t offset,
1838 : : GError **error)
1839 : : {
1840 : 42 : GITypelib *typelib = ctx->typelib;
1841 : : Header *header;
1842 : : InterfaceBlob *blob;
1843 : : size_t i;
1844 : : uint32_t offset2;
1845 : :
1846 : 42 : header = (Header *)typelib->data;
1847 : :
1848 : 42 : if (typelib->len < offset + sizeof (InterfaceBlob))
1849 : : {
1850 : 0 : g_set_error (error,
1851 : : GI_TYPELIB_ERROR,
1852 : : GI_TYPELIB_ERROR_INVALID,
1853 : : "The buffer is too short");
1854 : 0 : return FALSE;
1855 : : }
1856 : :
1857 : 42 : blob = (InterfaceBlob*) &typelib->data[offset];
1858 : :
1859 : 42 : if (blob->blob_type != BLOB_TYPE_INTERFACE)
1860 : : {
1861 : 0 : g_set_error (error,
1862 : : GI_TYPELIB_ERROR,
1863 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1864 : 0 : "Wrong blob type; expected interface, got %d", blob->blob_type);
1865 : 0 : return FALSE;
1866 : : }
1867 : :
1868 : 42 : if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1869 : 0 : return FALSE;
1870 : :
1871 : 42 : if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1872 : 0 : return FALSE;
1873 : :
1874 : 42 : if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1875 : 0 : return FALSE;
1876 : :
1877 : 42 : if (typelib->len < offset + sizeof (InterfaceBlob) +
1878 : 42 : (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1879 : 42 : blob->n_properties * sizeof (PropertyBlob) +
1880 : 42 : blob->n_methods * sizeof (FunctionBlob) +
1881 : 42 : blob->n_signals * sizeof (SignalBlob) +
1882 : 42 : blob->n_vfuncs * sizeof (VFuncBlob) +
1883 : 42 : blob->n_constants * sizeof (ConstantBlob))
1884 : :
1885 : : {
1886 : 0 : g_set_error (error,
1887 : : GI_TYPELIB_ERROR,
1888 : : GI_TYPELIB_ERROR_INVALID,
1889 : : "The buffer is too short");
1890 : 0 : return FALSE;
1891 : : }
1892 : :
1893 : 42 : offset2 = offset + sizeof (InterfaceBlob);
1894 : :
1895 : 58 : for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1896 : : {
1897 : : DirEntry *entry;
1898 : : uint16_t req;
1899 : :
1900 : 16 : req = *(uint16_t *)&typelib->data[offset2];
1901 : 16 : if (req == 0 || req > header->n_entries)
1902 : : {
1903 : 0 : g_set_error (error,
1904 : : GI_TYPELIB_ERROR,
1905 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1906 : : "Invalid prerequisite index");
1907 : 0 : return FALSE;
1908 : : }
1909 : :
1910 : 16 : entry = gi_typelib_get_dir_entry (typelib, req);
1911 : 16 : if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1912 : 5 : entry->blob_type != BLOB_TYPE_OBJECT &&
1913 : 0 : (entry->local || entry->blob_type != 0))
1914 : : {
1915 : 0 : g_set_error (error,
1916 : : GI_TYPELIB_ERROR,
1917 : : GI_TYPELIB_ERROR_INVALID_BLOB,
1918 : : "Not an interface or object");
1919 : 0 : return FALSE;
1920 : : }
1921 : : }
1922 : :
1923 : 42 : offset2 += 2 * (blob->n_prerequisites % 2);
1924 : :
1925 : 42 : push_context (ctx, get_string_nofail (typelib, blob->name));
1926 : :
1927 : 74 : for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1928 : : {
1929 : 32 : if (!validate_property_blob (typelib, offset2, error))
1930 : 0 : return FALSE;
1931 : : }
1932 : :
1933 : 470 : for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1934 : : {
1935 : 428 : if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1936 : 0 : return FALSE;
1937 : : }
1938 : :
1939 : 65 : for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1940 : : {
1941 : 23 : if (!validate_signal_blob (typelib, offset2, offset, error))
1942 : 0 : return FALSE;
1943 : : }
1944 : :
1945 : 357 : for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1946 : : {
1947 : 315 : if (!validate_vfunc_blob (typelib, offset2, offset, error))
1948 : 0 : return FALSE;
1949 : : }
1950 : :
1951 : 42 : for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1952 : : {
1953 : 0 : if (!validate_constant_blob (typelib, offset2, error))
1954 : 0 : return FALSE;
1955 : : }
1956 : :
1957 : 42 : pop_context (ctx);
1958 : :
1959 : 42 : return TRUE;
1960 : : }
1961 : :
1962 : : static gboolean
1963 : 7 : validate_union_blob (GITypelib *typelib,
1964 : : uint32_t offset,
1965 : : GError **error)
1966 : : {
1967 : 7 : return TRUE;
1968 : : }
1969 : :
1970 : : static gboolean
1971 : 2223 : validate_blob (ValidateContext *ctx,
1972 : : uint32_t offset,
1973 : : GError **error)
1974 : : {
1975 : 2223 : GITypelib *typelib = ctx->typelib;
1976 : : CommonBlob *common;
1977 : :
1978 : 2223 : if (typelib->len < offset + sizeof (CommonBlob))
1979 : : {
1980 : 0 : g_set_error (error,
1981 : : GI_TYPELIB_ERROR,
1982 : : GI_TYPELIB_ERROR_INVALID,
1983 : : "The buffer is too short");
1984 : 0 : return FALSE;
1985 : : }
1986 : :
1987 : 2223 : common = (CommonBlob*)&typelib->data[offset];
1988 : :
1989 : 2223 : switch (common->blob_type)
1990 : : {
1991 : 1028 : case BLOB_TYPE_FUNCTION:
1992 : 1028 : if (!validate_function_blob (ctx, offset, 0, error))
1993 : 0 : return FALSE;
1994 : 1028 : break;
1995 : 129 : case BLOB_TYPE_CALLBACK:
1996 : 129 : if (!validate_callback_blob (ctx, offset, error))
1997 : 0 : return FALSE;
1998 : 129 : break;
1999 : 393 : case BLOB_TYPE_STRUCT:
2000 : : case BLOB_TYPE_BOXED:
2001 : 393 : if (!validate_struct_blob (ctx, offset, common->blob_type, error))
2002 : 0 : return FALSE;
2003 : 393 : break;
2004 : 166 : case BLOB_TYPE_ENUM:
2005 : : case BLOB_TYPE_FLAGS:
2006 : 166 : if (!validate_enum_blob (ctx, offset, common->blob_type, error))
2007 : 0 : return FALSE;
2008 : 166 : break;
2009 : 165 : case BLOB_TYPE_OBJECT:
2010 : 165 : if (!validate_object_blob (ctx, offset, error))
2011 : 0 : return FALSE;
2012 : 165 : break;
2013 : 42 : case BLOB_TYPE_INTERFACE:
2014 : 42 : if (!validate_interface_blob (ctx, offset, error))
2015 : 0 : return FALSE;
2016 : 42 : break;
2017 : 293 : case BLOB_TYPE_CONSTANT:
2018 : 293 : if (!validate_constant_blob (typelib, offset, error))
2019 : 0 : return FALSE;
2020 : 293 : break;
2021 : 7 : case BLOB_TYPE_UNION:
2022 : 7 : if (!validate_union_blob (typelib, offset, error))
2023 : 0 : return FALSE;
2024 : 7 : break;
2025 : 0 : default:
2026 : 0 : g_set_error (error,
2027 : : GI_TYPELIB_ERROR,
2028 : : GI_TYPELIB_ERROR_INVALID_ENTRY,
2029 : : "Invalid blob type");
2030 : 0 : return FALSE;
2031 : : }
2032 : :
2033 : 2223 : return TRUE;
2034 : : }
2035 : :
2036 : : static gboolean
2037 : 7 : validate_directory (ValidateContext *ctx,
2038 : : GError **error)
2039 : : {
2040 : 7 : GITypelib *typelib = ctx->typelib;
2041 : 7 : Header *header = (Header *)typelib->data;
2042 : : DirEntry *entry;
2043 : : size_t i;
2044 : :
2045 : 7 : if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
2046 : : {
2047 : 0 : g_set_error (error,
2048 : : GI_TYPELIB_ERROR,
2049 : : GI_TYPELIB_ERROR_INVALID,
2050 : : "The buffer is too short");
2051 : 0 : return FALSE;
2052 : : }
2053 : :
2054 : 2317 : for (i = 0; i < header->n_entries; i++)
2055 : : {
2056 : 2310 : entry = gi_typelib_get_dir_entry (typelib, i + 1);
2057 : :
2058 : 2310 : if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
2059 : 0 : return FALSE;
2060 : :
2061 : 2310 : if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
2062 : 2310 : entry->blob_type > BLOB_TYPE_UNION)
2063 : : {
2064 : 0 : g_set_error (error,
2065 : : GI_TYPELIB_ERROR,
2066 : : GI_TYPELIB_ERROR_INVALID_DIRECTORY,
2067 : : "Invalid entry type");
2068 : 0 : return FALSE;
2069 : : }
2070 : :
2071 : 2310 : if (i < header->n_local_entries)
2072 : : {
2073 : 2223 : if (!entry->local)
2074 : : {
2075 : 0 : g_set_error (error,
2076 : : GI_TYPELIB_ERROR,
2077 : : GI_TYPELIB_ERROR_INVALID_DIRECTORY,
2078 : : "Too few local directory entries");
2079 : 0 : return FALSE;
2080 : : }
2081 : :
2082 : 2223 : if (!is_aligned (entry->offset))
2083 : : {
2084 : 0 : g_set_error (error,
2085 : : GI_TYPELIB_ERROR,
2086 : : GI_TYPELIB_ERROR_INVALID_DIRECTORY,
2087 : : "Misaligned entry");
2088 : 0 : return FALSE;
2089 : : }
2090 : :
2091 : 2223 : if (!validate_blob (ctx, entry->offset, error))
2092 : 0 : return FALSE;
2093 : : }
2094 : : else
2095 : : {
2096 : 87 : if (entry->local)
2097 : : {
2098 : 0 : g_set_error (error,
2099 : : GI_TYPELIB_ERROR,
2100 : : GI_TYPELIB_ERROR_INVALID_DIRECTORY,
2101 : : "Too many local directory entries");
2102 : 0 : return FALSE;
2103 : : }
2104 : :
2105 : 87 : if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
2106 : 0 : return FALSE;
2107 : : }
2108 : : }
2109 : :
2110 : 7 : return TRUE;
2111 : : }
2112 : :
2113 : : static gboolean
2114 : 7 : validate_attributes (ValidateContext *ctx,
2115 : : GError **error)
2116 : : {
2117 : 7 : GITypelib *typelib = ctx->typelib;
2118 : 7 : Header *header = (Header *)typelib->data;
2119 : :
2120 : 7 : if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
2121 : : {
2122 : 0 : g_set_error (error,
2123 : : GI_TYPELIB_ERROR,
2124 : : GI_TYPELIB_ERROR_INVALID,
2125 : : "The buffer is too short");
2126 : 0 : return FALSE;
2127 : : }
2128 : :
2129 : 7 : return TRUE;
2130 : : }
2131 : :
2132 : : static void
2133 : 0 : prefix_with_context (GError **error,
2134 : : const char *section,
2135 : : ValidateContext *ctx)
2136 : : {
2137 : : GString *str;
2138 : : GSList *link;
2139 : : char *buf;
2140 : :
2141 : 0 : link = ctx->context_stack;
2142 : 0 : if (!link)
2143 : : {
2144 : 0 : g_prefix_error (error, "In %s:", section);
2145 : 0 : return;
2146 : : }
2147 : :
2148 : 0 : str = g_string_new (NULL);
2149 : :
2150 : 0 : for (; link; link = link->next)
2151 : : {
2152 : 0 : g_string_append (str, link->data);
2153 : 0 : if (link->next)
2154 : : g_string_append_c (str, '/');
2155 : : }
2156 : : g_string_append_c (str, ')');
2157 : 0 : buf = g_string_free (str, FALSE);
2158 : 0 : g_prefix_error (error, "In %s (Context: %s): ", section, buf);
2159 : 0 : g_free (buf);
2160 : : }
2161 : :
2162 : : /**
2163 : : * gi_typelib_validate:
2164 : : * @typelib: a #GITypelib
2165 : : * @error: return location for a [type@GLib.Error], or `NULL`
2166 : : *
2167 : : * Check whether @typelib is well-formed, i.e. that the file is not corrupt or
2168 : : * truncated.
2169 : : *
2170 : : * Returns: `TRUE` if @typelib is well-formed, `FALSE` otherwise
2171 : : * Since: 2.80
2172 : : */
2173 : : gboolean
2174 : 7 : gi_typelib_validate (GITypelib *typelib,
2175 : : GError **error)
2176 : : {
2177 : : ValidateContext ctx;
2178 : 7 : ctx.typelib = typelib;
2179 : 7 : ctx.context_stack = NULL;
2180 : :
2181 : 7 : if (!validate_header (&ctx, error))
2182 : : {
2183 : 0 : prefix_with_context (error, "In header", &ctx);
2184 : 0 : return FALSE;
2185 : : }
2186 : :
2187 : 7 : if (!validate_directory (&ctx, error))
2188 : : {
2189 : 0 : prefix_with_context (error, "directory", &ctx);
2190 : 0 : return FALSE;
2191 : : }
2192 : :
2193 : 7 : if (!validate_attributes (&ctx, error))
2194 : : {
2195 : 0 : prefix_with_context (error, "attributes", &ctx);
2196 : 0 : return FALSE;
2197 : : }
2198 : :
2199 : 7 : return TRUE;
2200 : : }
2201 : :
2202 : : /**
2203 : : * gi_typelib_error_quark:
2204 : : *
2205 : : * Get the quark representing the [type@GIRepository.TypelibError] error domain.
2206 : : *
2207 : : * Returns: quark representing the error domain
2208 : : * Since: 2.80
2209 : : */
2210 : : GQuark
2211 : 0 : gi_typelib_error_quark (void)
2212 : : {
2213 : : static GQuark quark = 0;
2214 : 0 : if (quark == 0)
2215 : 0 : quark = g_quark_from_static_string ("gi-typelib-error-quark");
2216 : 0 : return quark;
2217 : : }
2218 : :
2219 : : /* Note on the GModule flags used by this function:
2220 : :
2221 : : * Glade's autoconnect feature and OpenGL's extension mechanism
2222 : : * as used by Clutter rely on g_module_open(NULL) to work as a means of
2223 : : * accessing the app's symbols. This keeps us from using
2224 : : * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
2225 : : * in general libraries are not expecting multiple copies of
2226 : : * themselves and are not expecting to be unloaded. So we just
2227 : : * load modules globally for now.
2228 : : */
2229 : : static GModule *
2230 : 7 : load_one_shared_library (GITypelib *typelib,
2231 : : const char *shlib)
2232 : : {
2233 : : GModule *m;
2234 : :
2235 : : #ifdef __APPLE__
2236 : : /* On macOS, @-prefixed shlib paths (@rpath, @executable_path, @loader_path)
2237 : : need to be treated as absolute; trying to combine them with a
2238 : : configured library path produces a mangled path that is unresolvable
2239 : : and may cause unintended side effects (such as loading the library
2240 : : from a fall-back location on macOS 12.0.1).
2241 : : */
2242 : : if (!g_path_is_absolute (shlib) && !g_str_has_prefix (shlib, "@"))
2243 : : #else
2244 : 7 : if (!g_path_is_absolute (shlib))
2245 : : #endif
2246 : : {
2247 : : /* First try in configured library paths */
2248 : 7 : for (unsigned int i = 0; typelib->library_paths != NULL && i < typelib->library_paths->len; i++)
2249 : : {
2250 : 0 : char *path = g_build_filename (typelib->library_paths->pdata[i], shlib, NULL);
2251 : :
2252 : 0 : m = g_module_open (path, G_MODULE_BIND_LAZY);
2253 : :
2254 : 0 : g_free (path);
2255 : 0 : if (m != NULL)
2256 : 0 : return m;
2257 : : }
2258 : : }
2259 : :
2260 : : /* Then try loading from standard paths */
2261 : : /* Do not attempt to fix up shlib to replace .la with .so:
2262 : : it's done by GModule anyway.
2263 : : */
2264 : 7 : return g_module_open (shlib, G_MODULE_BIND_LAZY);
2265 : : }
2266 : :
2267 : : static void
2268 : 5 : gi_typelib_do_dlopen (GITypelib *typelib)
2269 : : {
2270 : : Header *header;
2271 : : const char *shlib_str;
2272 : :
2273 : 5 : header = (Header *) typelib->data;
2274 : : /* note that NULL shlib means to open the main app, which is allowed */
2275 : 5 : if (header->shared_library)
2276 : 5 : shlib_str = gi_typelib_get_string (typelib, header->shared_library);
2277 : : else
2278 : 0 : shlib_str = NULL;
2279 : :
2280 : 5 : if (shlib_str != NULL && shlib_str[0] != '\0')
2281 : 5 : {
2282 : : char **shlibs;
2283 : :
2284 : : /* shared-library is a comma-separated list of libraries */
2285 : 5 : shlibs = g_strsplit (shlib_str, ",", 0);
2286 : :
2287 : : /* We load all passed libs unconditionally as if the same library is loaded
2288 : : * again with g_module_open(), the same file handle will be returned. See bug:
2289 : : * http://bugzilla.gnome.org/show_bug.cgi?id=555294
2290 : : */
2291 : 12 : for (size_t i = 0; shlibs[i]; i++)
2292 : : {
2293 : : GModule *module;
2294 : :
2295 : 7 : module = load_one_shared_library (typelib, shlibs[i]);
2296 : :
2297 : 7 : if (module == NULL)
2298 : : {
2299 : 0 : g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2300 : : shlibs[i], g_module_error ());
2301 : : }
2302 : : else
2303 : : {
2304 : 7 : typelib->modules = g_list_append (typelib->modules, module);
2305 : : }
2306 : : }
2307 : :
2308 : 5 : g_strfreev (shlibs);
2309 : : }
2310 : : else
2311 : : {
2312 : : /* If there's no shared-library entry for this module, assume that
2313 : : * the module is for the application. Some of the hand-written .gir files
2314 : : * in gobject-introspection don't have shared-library entries, but no one
2315 : : * is really going to be calling g_module_symbol on them either.
2316 : : */
2317 : 0 : GModule *module = g_module_open (NULL, 0);
2318 : 0 : if (module == NULL)
2319 : 0 : g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
2320 : : else
2321 : 0 : typelib->modules = g_list_prepend (typelib->modules, module);
2322 : : }
2323 : 5 : }
2324 : :
2325 : : static inline void
2326 : 5 : gi_typelib_ensure_open (GITypelib *typelib)
2327 : : {
2328 : 5 : if (typelib->open_attempted)
2329 : 0 : return;
2330 : 5 : typelib->open_attempted = TRUE;
2331 : 5 : gi_typelib_do_dlopen (typelib);
2332 : : }
2333 : :
2334 : : /**
2335 : : * gi_typelib_new_from_bytes:
2336 : : * @bytes: memory chunk containing the typelib
2337 : : * @error: a [type@GLib.Error]
2338 : : *
2339 : : * Creates a new [type@GIRepository.Typelib] from a [type@GLib.Bytes].
2340 : : *
2341 : : * The [type@GLib.Bytes] can point to a memory location or a mapped file, and
2342 : : * the typelib will hold a reference to it until the repository is destroyed.
2343 : : *
2344 : : * Returns: (transfer full): the new [type@GIRepository.Typelib]
2345 : : * Since: 2.80
2346 : : */
2347 : : GITypelib *
2348 : 201 : gi_typelib_new_from_bytes (GBytes *bytes,
2349 : : GError **error)
2350 : : {
2351 : : GITypelib *meta;
2352 : : size_t len;
2353 : 201 : const uint8_t *data = g_bytes_get_data (bytes, &len);
2354 : :
2355 : 201 : if (!validate_header_basic (data, len, error))
2356 : 0 : return NULL;
2357 : :
2358 : 201 : meta = g_slice_new0 (GITypelib);
2359 : 201 : g_atomic_ref_count_init (&meta->ref_count);
2360 : 201 : meta->bytes = g_bytes_ref (bytes);
2361 : 201 : meta->data = data;
2362 : 201 : meta->len = len;
2363 : 201 : meta->modules = NULL;
2364 : :
2365 : 201 : return meta;
2366 : : }
2367 : :
2368 : : /**
2369 : : * gi_typelib_ref:
2370 : : * @typelib: (transfer none): a #GITypelib
2371 : : *
2372 : : * Increment the reference count of a [type@GIRepository.Typelib].
2373 : : *
2374 : : * Returns: (transfer full): the same @typelib pointer
2375 : : * Since: 2.80
2376 : : */
2377 : : GITypelib *
2378 : 195 : gi_typelib_ref (GITypelib *typelib)
2379 : : {
2380 : 195 : g_return_val_if_fail (typelib != NULL, NULL);
2381 : :
2382 : 195 : g_atomic_ref_count_inc (&typelib->ref_count);
2383 : :
2384 : 195 : return typelib;
2385 : : }
2386 : :
2387 : : /**
2388 : : * gi_typelib_unref:
2389 : : * @typelib: (transfer full): a #GITypelib
2390 : : *
2391 : : * Decrement the reference count of a [type@GIRepository.Typelib].
2392 : : *
2393 : : * Once the reference count reaches zero, the typelib is freed.
2394 : : *
2395 : : * Since: 2.80
2396 : : */
2397 : : void
2398 : 396 : gi_typelib_unref (GITypelib *typelib)
2399 : : {
2400 : 396 : g_return_if_fail (typelib != NULL);
2401 : :
2402 : 396 : if (g_atomic_ref_count_dec (&typelib->ref_count))
2403 : : {
2404 : 201 : g_clear_pointer (&typelib->bytes, g_bytes_unref);
2405 : :
2406 : 201 : g_clear_pointer (&typelib->library_paths, g_ptr_array_unref);
2407 : :
2408 : 201 : if (typelib->modules)
2409 : : {
2410 : 5 : g_list_foreach (typelib->modules, (GFunc) (void *) g_module_close, NULL);
2411 : 5 : g_list_free (typelib->modules);
2412 : : }
2413 : 201 : g_slice_free (GITypelib, typelib);
2414 : : }
2415 : : }
2416 : :
2417 : : /**
2418 : : * gi_typelib_get_namespace:
2419 : : * @typelib: a #GITypelib
2420 : : *
2421 : : * Get the name of the namespace represented by @typelib.
2422 : : *
2423 : : * Returns: name of the namespace represented by @typelib
2424 : : * Since: 2.80
2425 : : */
2426 : : const char *
2427 : 603 : gi_typelib_get_namespace (GITypelib *typelib)
2428 : : {
2429 : 603 : return gi_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2430 : : }
2431 : :
2432 : : /**
2433 : : * gi_typelib_symbol:
2434 : : * @typelib: the typelib
2435 : : * @symbol_name: name of symbol to be loaded
2436 : : * @symbol: (out) (nullable): returns a pointer to the symbol value, or `NULL`
2437 : : * on failure
2438 : : *
2439 : : * Loads a symbol from a `GITypelib`.
2440 : : *
2441 : : * Returns: `TRUE` on success
2442 : : * Since: 2.80
2443 : : */
2444 : : gboolean
2445 : 5 : gi_typelib_symbol (GITypelib *typelib, const char *symbol_name, void **symbol)
2446 : : {
2447 : : GList *l;
2448 : :
2449 : 5 : gi_typelib_ensure_open (typelib);
2450 : :
2451 : : /*
2452 : : * The reason for having multiple modules dates from gir-repository
2453 : : * when it was desired to inject code (accessors, etc.) into an
2454 : : * existing library. In that situation, the first module listed
2455 : : * will be the custom one, which overrides the main one. A bit
2456 : : * inefficient, but the problem will go away when gir-repository
2457 : : * does.
2458 : : *
2459 : : * For modules with no shared library, we dlopen'd the current
2460 : : * process above.
2461 : : */
2462 : 5 : for (l = typelib->modules; l; l = l->next)
2463 : : {
2464 : 5 : GModule *module = l->data;
2465 : :
2466 : 5 : if (g_module_symbol (module, symbol_name, symbol))
2467 : 5 : return TRUE;
2468 : : }
2469 : :
2470 : 0 : return FALSE;
2471 : : }
|