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