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