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