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