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