bc9896d2bf4e8c7f49fbf07dbab75b1d02580f1f
[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->flags.reserved == 0 && simple->flags.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->flags.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, 112);
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, 16);
179   CHECK_SIZE (RegisteredTypeBlob, 16);
180   CHECK_SIZE (StructBlob, 32);
181   CHECK_SIZE (EnumBlob, 24);
182   CHECK_SIZE (PropertyBlob, 16);
183   CHECK_SIZE (SignalBlob, 16);
184   CHECK_SIZE (VFuncBlob, 20);
185   CHECK_SIZE (ObjectBlob, 44);
186   CHECK_SIZE (InterfaceBlob, 40);
187   CHECK_SIZE (ConstantBlob, 24);
188   CHECK_SIZE (AttributeBlob, 12);
189   CHECK_SIZE (UnionBlob, 40);
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 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->attribute_blob_size != sizeof (AttributeBlob) ||
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->attributes))
362     {
363       g_set_error (error,
364                    G_TYPELIB_ERROR,
365                    G_TYPELIB_ERROR_INVALID_HEADER,
366                    "Misaligned attributes");
367       return FALSE; 
368     }
369
370   if (header->attributes == 0 && header->n_attributes > 0)
371     {
372       g_set_error (error,
373                    G_TYPELIB_ERROR,
374                    G_TYPELIB_ERROR_INVALID_HEADER,
375                    "Wrong number of attributes");
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->flags.reserved == 0 && 
551       simple->flags.reserved2 == 0)
552     {
553       if (simple->flags.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->flags.tag >= GI_TYPE_TAG_UTF8 &&
563           !simple->flags.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->flags.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 (gshort),
908     sizeof (gushort),
909     sizeof (gint),
910     sizeof (guint),
911     sizeof (glong),
912     sizeof (gulong),
913     sizeof (gssize),
914     sizeof (gsize),
915     sizeof (gfloat),
916     sizeof (gdouble),
917     sizeof (time_t),
918     0, /* GTYPE */
919     0, /* UTF8 */
920     0, /* FILENAME */
921     0, /* ARRAY */
922     0, /* INTERFACE */
923     0, /* GLIST */
924     0, /* GSLIST */
925     0, /* GHASH */
926     0, /* ERROR */
927   };
928   ConstantBlob *blob;
929   SimpleTypeBlob *type;
930
931   if (typelib->len < offset + sizeof (ConstantBlob))
932     {
933       g_set_error (error,
934                    G_TYPELIB_ERROR,
935                    G_TYPELIB_ERROR_INVALID,
936                    "The buffer is too short");
937       return FALSE;
938     }
939
940   blob = (ConstantBlob*) &typelib->data[offset];
941
942   if (blob->blob_type != BLOB_TYPE_CONSTANT)
943     {
944       g_set_error (error,
945                    G_TYPELIB_ERROR,
946                    G_TYPELIB_ERROR_INVALID_BLOB,
947                    "Wrong blob type");
948       return FALSE;
949     }
950
951   if (!validate_name (typelib, "constant", typelib->data, blob->name, error))
952     return FALSE; 
953   
954   if (!validate_type_blob (typelib, offset + G_STRUCT_OFFSET (ConstantBlob, type), 
955                            0, FALSE, error))
956     return FALSE;
957
958   if (!is_aligned (blob->offset))
959     {
960       g_set_error (error,
961                    G_TYPELIB_ERROR,
962                    G_TYPELIB_ERROR_INVALID_BLOB,
963                    "Misaligned constant value");
964       return FALSE;
965     }
966   
967   type = (SimpleTypeBlob *)&typelib->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
968   if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
969     {
970       if (type->flags.tag == 0)
971         {
972           g_set_error (error,
973                        G_TYPELIB_ERROR,
974                        G_TYPELIB_ERROR_INVALID_BLOB,
975                        "Constant value type void");
976           return FALSE;
977         }
978
979       if (value_size[type->flags.tag] != 0 &&
980           blob->size != value_size[type->flags.tag])
981         {
982           g_set_error (error,
983                        G_TYPELIB_ERROR,
984                        G_TYPELIB_ERROR_INVALID_BLOB,
985                        "Constant value size mismatch");
986           return FALSE;
987         }
988       /* FIXME check string values */
989     }
990
991   return TRUE;
992 }
993
994 static gboolean
995 validate_value_blob (GTypelib     *typelib,
996                      guint32        offset,
997                      GError       **error)
998 {
999   ValueBlob *blob;
1000
1001   if (typelib->len < offset + sizeof (ValueBlob))
1002     {
1003       g_set_error (error,
1004                    G_TYPELIB_ERROR,
1005                    G_TYPELIB_ERROR_INVALID,
1006                    "The buffer is too short");
1007       return FALSE;
1008     }
1009
1010   blob = (ValueBlob*) &typelib->data[offset];
1011
1012   if (!validate_name (typelib, "value", typelib->data, blob->name, error))
1013     return FALSE; 
1014   
1015   return TRUE;
1016 }
1017
1018 static gboolean
1019 validate_field_blob (ValidateContext *ctx,
1020                      guint32        offset,
1021                      GError       **error)
1022 {
1023   GTypelib *typelib = ctx->typelib;
1024   Header *header = (Header *)typelib->data;
1025   FieldBlob *blob;
1026
1027   if (typelib->len < offset + sizeof (FieldBlob))
1028     {
1029       g_set_error (error,
1030                    G_TYPELIB_ERROR,
1031                    G_TYPELIB_ERROR_INVALID,
1032                    "The buffer is too short");
1033       return FALSE;
1034     }
1035
1036   blob = (FieldBlob*) &typelib->data[offset];
1037   
1038   if (!validate_name (typelib, "field", typelib->data, blob->name, error))
1039     return FALSE; 
1040
1041   if (blob->has_embedded_type)
1042     {
1043       if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
1044         return FALSE;
1045     }
1046   else if (!validate_type_blob (typelib,
1047                                 offset + G_STRUCT_OFFSET (FieldBlob, type), 
1048                                 0, FALSE, error))
1049     return FALSE;
1050
1051   return TRUE;
1052 }
1053
1054 static gboolean
1055 validate_property_blob (GTypelib     *typelib,
1056                         guint32        offset,
1057                         GError       **error)
1058 {
1059   PropertyBlob *blob;
1060
1061   if (typelib->len < offset + sizeof (PropertyBlob))
1062     {
1063       g_set_error (error,
1064                    G_TYPELIB_ERROR,
1065                    G_TYPELIB_ERROR_INVALID,
1066                    "The buffer is too short");
1067       return FALSE;
1068     }
1069
1070   blob = (PropertyBlob*) &typelib->data[offset];
1071   
1072   if (!validate_name (typelib, "property", typelib->data, blob->name, error))
1073     return FALSE; 
1074     
1075   if (!validate_type_blob (typelib,
1076                            offset + G_STRUCT_OFFSET (PropertyBlob, type), 
1077                            0, FALSE, error))
1078     return FALSE;
1079
1080   return TRUE;
1081 }
1082
1083 static gboolean
1084 validate_signal_blob (GTypelib     *typelib,
1085                       guint32        offset,
1086                       guint32        container_offset,
1087                       GError       **error)
1088 {
1089   SignalBlob *blob;
1090   gint n_signals;
1091
1092   if (typelib->len < offset + sizeof (SignalBlob))
1093     {
1094       g_set_error (error,
1095                    G_TYPELIB_ERROR,
1096                    G_TYPELIB_ERROR_INVALID,
1097                    "The buffer is too short");
1098       return FALSE;
1099     }
1100
1101   blob = (SignalBlob*) &typelib->data[offset];
1102
1103   if (!validate_name (typelib, "signal", typelib->data, blob->name, error))
1104     return FALSE; 
1105   
1106   if ((blob->run_first != 0) + 
1107       (blob->run_last != 0) + 
1108       (blob->run_cleanup != 0) != 1)
1109     {
1110       g_set_error (error,
1111                    G_TYPELIB_ERROR,
1112                    G_TYPELIB_ERROR_INVALID_BLOB,
1113                    "Invalid signal run flags");
1114       return FALSE; 
1115     }
1116
1117   if (blob->has_class_closure)
1118     {
1119       if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1120         {
1121           ObjectBlob *object;
1122
1123           object = (ObjectBlob*)&typelib->data[container_offset];
1124           
1125           n_signals = object->n_signals;
1126         }
1127       else
1128         {
1129           InterfaceBlob *iface;
1130           
1131           iface = (InterfaceBlob*)&typelib->data[container_offset];
1132           
1133           n_signals = iface->n_signals;
1134         }
1135
1136       if (blob->class_closure >= n_signals)
1137         {
1138           g_set_error (error,
1139                        G_TYPELIB_ERROR,
1140                        G_TYPELIB_ERROR_INVALID_BLOB,
1141                        "Invalid class closure index");
1142           return FALSE; 
1143         }
1144     }
1145
1146   if (!validate_signature_blob (typelib, blob->signature, error))
1147     return FALSE;
1148   
1149   return TRUE;
1150 }
1151
1152 static gboolean
1153 validate_vfunc_blob (GTypelib     *typelib,
1154                      guint32        offset,
1155                      guint32        container_offset,
1156                      GError       **error)
1157 {
1158   VFuncBlob *blob;
1159   gint n_vfuncs;
1160
1161   if (typelib->len < offset + sizeof (VFuncBlob))
1162     {
1163       g_set_error (error,
1164                    G_TYPELIB_ERROR,
1165                    G_TYPELIB_ERROR_INVALID,
1166                    "The buffer is too short");
1167       return FALSE;
1168     }
1169
1170   blob = (VFuncBlob*) &typelib->data[offset];
1171
1172   if (!validate_name (typelib, "vfunc", typelib->data, blob->name, error))
1173     return FALSE; 
1174   
1175   if (blob->class_closure)
1176     {
1177       if (((CommonBlob*)&typelib->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
1178         {
1179           ObjectBlob *object;
1180
1181           object = (ObjectBlob*)&typelib->data[container_offset];
1182           
1183           n_vfuncs = object->n_vfuncs;
1184         }
1185       else
1186         {
1187           InterfaceBlob *iface;
1188           
1189           iface = (InterfaceBlob*)&typelib->data[container_offset];
1190           
1191           n_vfuncs = iface->n_vfuncs;
1192         }
1193
1194       if (blob->class_closure >= n_vfuncs)
1195         {
1196           g_set_error (error,
1197                        G_TYPELIB_ERROR,
1198                        G_TYPELIB_ERROR_INVALID_BLOB,
1199                        "Invalid class closure index");
1200           return FALSE; 
1201         }
1202     }
1203
1204   if (!validate_signature_blob (typelib, blob->signature, error))
1205     return FALSE;
1206   
1207   return TRUE;
1208 }
1209
1210 static gboolean
1211 validate_struct_blob (ValidateContext *ctx,
1212                       guint32        offset,
1213                       guint16        blob_type,
1214                       GError       **error)
1215 {
1216   GTypelib *typelib = ctx->typelib;
1217   StructBlob *blob;
1218   gint i;
1219   guint32 field_offset;
1220
1221   if (typelib->len < offset + sizeof (StructBlob))
1222     {
1223       g_set_error (error,
1224                    G_TYPELIB_ERROR,
1225                    G_TYPELIB_ERROR_INVALID,
1226                    "The buffer is too short");
1227       return FALSE;
1228     }
1229
1230   blob = (StructBlob*) &typelib->data[offset];
1231
1232   if (blob->blob_type != blob_type)
1233     {
1234       g_set_error (error,
1235                    G_TYPELIB_ERROR,
1236                    G_TYPELIB_ERROR_INVALID_BLOB,
1237                    "Wrong blob type");
1238       return FALSE;
1239     }
1240
1241   if (!validate_name (typelib, "struct", typelib->data, blob->name, error))
1242     return FALSE; 
1243
1244   push_context (ctx, get_string_nofail (typelib, blob->name));
1245   
1246   if (!blob->unregistered)
1247     {
1248       if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_name, error))
1249         return FALSE; 
1250
1251       if (!validate_name (typelib, "boxed", typelib->data, blob->gtype_init, error))
1252         return FALSE; 
1253     }
1254   else
1255     {
1256       if (blob->gtype_name || blob->gtype_init)
1257         {
1258           g_set_error (error,
1259                        G_TYPELIB_ERROR,
1260                        G_TYPELIB_ERROR_INVALID_BLOB,
1261                        "Gtype data in struct");
1262           return FALSE; 
1263         }
1264     }
1265
1266   if (typelib->len < offset + sizeof (StructBlob) + 
1267             blob->n_fields * sizeof (FieldBlob) +
1268             blob->n_methods * sizeof (FunctionBlob))
1269     {
1270       g_set_error (error,
1271                    G_TYPELIB_ERROR,
1272                    G_TYPELIB_ERROR_INVALID,
1273                    "The buffer is too short");
1274       return FALSE;
1275     }
1276
1277   field_offset = offset + sizeof (StructBlob);
1278   for (i = 0; i < blob->n_fields; i++)
1279     {
1280       FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
1281
1282       if (!validate_field_blob (ctx,
1283                                 field_offset,
1284                                 error))
1285         return FALSE;
1286
1287       field_offset += sizeof (FieldBlob);
1288       if (blob->has_embedded_type)
1289         field_offset += sizeof (CallbackBlob);
1290     }
1291
1292   for (i = 0; i < blob->n_methods; i++)
1293     {
1294       if (!validate_function_blob (ctx, 
1295                                    field_offset + 
1296                                    i * sizeof (FunctionBlob), 
1297                                    blob_type,
1298                                    error))
1299         return FALSE;
1300     }
1301
1302   pop_context (ctx);
1303
1304   return TRUE;
1305 }
1306
1307 static gboolean
1308 validate_enum_blob (ValidateContext *ctx,
1309                     guint32        offset,
1310                     guint16        blob_type,
1311                     GError       **error)
1312 {
1313   GTypelib *typelib = ctx->typelib;
1314   EnumBlob *blob;
1315   gint i;
1316
1317   if (typelib->len < offset + sizeof (EnumBlob))
1318     {
1319       g_set_error (error,
1320                    G_TYPELIB_ERROR,
1321                    G_TYPELIB_ERROR_INVALID,
1322                    "The buffer is too short");
1323       return FALSE;
1324     }
1325
1326   blob = (EnumBlob*) &typelib->data[offset];
1327
1328   if (blob->blob_type != blob_type)
1329     {
1330       g_set_error (error,
1331                    G_TYPELIB_ERROR,
1332                    G_TYPELIB_ERROR_INVALID_BLOB,
1333                    "Wrong blob type");
1334       return FALSE;
1335     }
1336   
1337   if (!blob->unregistered)
1338     {
1339       if (!validate_name (typelib, "enum", typelib->data, blob->gtype_name, error))
1340         return FALSE; 
1341
1342       if (!validate_name (typelib, "enum", typelib->data, blob->gtype_init, error))
1343         return FALSE; 
1344     }
1345   else
1346     {
1347       if (blob->gtype_name || blob->gtype_init)
1348         {
1349           g_set_error (error,
1350                        G_TYPELIB_ERROR,
1351                        G_TYPELIB_ERROR_INVALID_BLOB,
1352                        "Gtype data in unregistered enum");
1353           return FALSE; 
1354         }
1355     }
1356
1357   if (!validate_name (typelib, "enum", typelib->data, blob->name, error))
1358     return FALSE; 
1359   
1360   if (typelib->len < offset + sizeof (EnumBlob) + 
1361       blob->n_values * sizeof (ValueBlob))
1362     {
1363       g_set_error (error,
1364                    G_TYPELIB_ERROR,
1365                    G_TYPELIB_ERROR_INVALID,
1366                    "The buffer is too short");
1367       return FALSE;
1368     }
1369
1370   push_context (ctx, get_string_nofail (typelib, blob->name));
1371   
1372   for (i = 0; i < blob->n_values; i++)
1373     {
1374       if (!validate_value_blob (typelib, 
1375                                 offset + sizeof (EnumBlob) + 
1376                                 i * sizeof (ValueBlob), 
1377                                 error))
1378         return FALSE;
1379
1380 #if 0
1381       v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) + 
1382                                         i * sizeof (ValueBlob)];
1383       for (j = 0; j < i; j++) 
1384         {
1385           v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) + 
1386                                             j * sizeof (ValueBlob)];
1387
1388           if (v1->value == v2->value)
1389             {
1390
1391               /* FIXME should this be an error ? */
1392               g_set_error (error,
1393                            G_TYPELIB_ERROR,
1394                            G_TYPELIB_ERROR_INVALID_BLOB,
1395                            "Duplicate enum value");
1396               return FALSE;
1397             }
1398         }
1399 #endif      
1400     }
1401
1402   pop_context (ctx);
1403   
1404   return TRUE;
1405 }
1406
1407 static gboolean
1408 validate_object_blob (ValidateContext *ctx,
1409                       guint32        offset,
1410                       GError       **error)
1411 {
1412   GTypelib *typelib = ctx->typelib;
1413   Header *header;
1414   ObjectBlob *blob;
1415   gint i;
1416   guint32 offset2;
1417
1418   header = (Header *)typelib->data;
1419
1420   if (typelib->len < offset + sizeof (ObjectBlob))
1421     {
1422       g_set_error (error,
1423                    G_TYPELIB_ERROR,
1424                    G_TYPELIB_ERROR_INVALID,
1425                    "The buffer is too short");
1426       return FALSE;
1427     }
1428
1429   blob = (ObjectBlob*) &typelib->data[offset];
1430
1431   if (blob->blob_type != BLOB_TYPE_OBJECT)
1432     {
1433       g_set_error (error,
1434                    G_TYPELIB_ERROR,
1435                    G_TYPELIB_ERROR_INVALID_BLOB,
1436                    "Wrong blob type");
1437       return FALSE;
1438     }
1439   
1440   if (!validate_name (typelib, "object", typelib->data, blob->gtype_name, error))
1441     return FALSE; 
1442   
1443   if (!validate_name (typelib, "object", typelib->data, blob->gtype_init, error))
1444     return FALSE; 
1445   
1446   if (!validate_name (typelib, "object", typelib->data, blob->name, error))
1447     return FALSE; 
1448
1449   if (blob->parent > header->n_entries)
1450     {
1451       g_set_error (error,
1452                    G_TYPELIB_ERROR,
1453                    G_TYPELIB_ERROR_INVALID_BLOB,
1454                    "Invalid parent index");
1455       return FALSE; 
1456     }
1457
1458   if (blob->parent != 0)
1459     {
1460       DirEntry *entry;
1461
1462       entry = get_dir_entry_checked (typelib, blob->parent, error);
1463       if (!entry)
1464         return FALSE;
1465       if (entry->blob_type != BLOB_TYPE_OBJECT &&
1466           (entry->local || entry->blob_type != 0))
1467         {
1468           g_set_error (error,
1469                        G_TYPELIB_ERROR,
1470                        G_TYPELIB_ERROR_INVALID_BLOB,
1471                        "Parent not object");
1472           return FALSE; 
1473         }
1474     }
1475   
1476   if (blob->gtype_struct != 0)
1477     {
1478       DirEntry *entry;
1479
1480       entry = get_dir_entry_checked (typelib, blob->gtype_struct, error);
1481       if (!entry)
1482         return FALSE;
1483       if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
1484         {
1485           g_set_error (error,
1486                        G_TYPELIB_ERROR,
1487                        G_TYPELIB_ERROR_INVALID_BLOB,
1488                        "Class struct invalid type or not local");
1489           return FALSE; 
1490         }
1491     }  
1492   
1493   if (typelib->len < offset + sizeof (ObjectBlob) + 
1494             (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
1495             blob->n_fields * sizeof (FieldBlob) +
1496             blob->n_properties * sizeof (PropertyBlob) +
1497             blob->n_methods * sizeof (FunctionBlob) +
1498             blob->n_signals * sizeof (SignalBlob) +
1499             blob->n_vfuncs * sizeof (VFuncBlob) +
1500             blob->n_constants * sizeof (ConstantBlob))
1501      
1502     {
1503       g_set_error (error,
1504                    G_TYPELIB_ERROR,
1505                    G_TYPELIB_ERROR_INVALID,
1506                    "The buffer is too short");
1507       return FALSE;
1508     }
1509
1510   offset2 = offset + sizeof (ObjectBlob);
1511
1512   for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
1513     {
1514       guint16 iface;
1515       DirEntry *entry;
1516
1517       iface = *(guint16*)&typelib->data[offset2];
1518       if (iface == 0 || iface > header->n_entries)
1519         {
1520           g_set_error (error,
1521                        G_TYPELIB_ERROR,
1522                        G_TYPELIB_ERROR_INVALID_BLOB,
1523                        "Invalid interface index");
1524           return FALSE; 
1525         }
1526       
1527       entry = get_dir_entry_checked (typelib, iface, error);
1528       if (!entry)
1529         return FALSE;
1530
1531       if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1532           (entry->local || entry->blob_type != 0))
1533         {
1534           g_set_error (error,
1535                        G_TYPELIB_ERROR,
1536                        G_TYPELIB_ERROR_INVALID_BLOB,
1537                        "Not an interface");
1538           return FALSE; 
1539         }
1540     }
1541
1542   offset2 += 2 * (blob->n_interfaces %2);
1543
1544   push_context (ctx, get_string_nofail (typelib, blob->name));
1545   
1546   for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
1547     {
1548       if (!validate_field_blob (ctx, offset2, error))
1549         return FALSE;
1550     }
1551
1552   for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1553     {
1554       if (!validate_property_blob (typelib, offset2, error))
1555         return FALSE;
1556     }
1557
1558   for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1559     {
1560       if (!validate_function_blob (ctx, offset2, BLOB_TYPE_OBJECT, error))
1561         return FALSE;
1562     }
1563
1564   for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1565     {
1566       if (!validate_signal_blob (typelib, offset2, offset, error))
1567         return FALSE;
1568     }
1569
1570   for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1571     {
1572       if (!validate_vfunc_blob (typelib, offset2, offset, error))
1573         return FALSE;
1574     }
1575
1576   for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1577     {
1578       if (!validate_constant_blob (typelib, offset2, error))
1579         return FALSE;
1580     }
1581
1582   pop_context (ctx);
1583
1584   return TRUE;
1585 }
1586
1587 static gboolean
1588 validate_interface_blob (ValidateContext *ctx,
1589                          guint32        offset,
1590                          GError       **error)
1591 {
1592   GTypelib *typelib = ctx->typelib;
1593   Header *header;
1594   InterfaceBlob *blob;
1595   gint i;
1596   guint32 offset2;
1597   
1598   header = (Header *)typelib->data;
1599
1600   if (typelib->len < offset + sizeof (InterfaceBlob))
1601     {
1602       g_set_error (error,
1603                    G_TYPELIB_ERROR,
1604                    G_TYPELIB_ERROR_INVALID,
1605                    "The buffer is too short");
1606       return FALSE;
1607     }
1608
1609   blob = (InterfaceBlob*) &typelib->data[offset];
1610
1611   if (blob->blob_type != BLOB_TYPE_INTERFACE)
1612     {
1613       g_set_error (error,
1614                    G_TYPELIB_ERROR,
1615                    G_TYPELIB_ERROR_INVALID_BLOB,
1616                    "Wrong blob type; expected interface, got %d", blob->blob_type);
1617       return FALSE;
1618     }
1619   
1620   if (!validate_name (typelib, "interface", typelib->data, blob->gtype_name, error))
1621     return FALSE; 
1622   
1623   if (!validate_name (typelib, "interface", typelib->data, blob->gtype_init, error))
1624     return FALSE; 
1625   
1626   if (!validate_name (typelib, "interface", typelib->data, blob->name, error))
1627     return FALSE; 
1628   
1629   if (typelib->len < offset + sizeof (InterfaceBlob) + 
1630             (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
1631             blob->n_properties * sizeof (PropertyBlob) +
1632             blob->n_methods * sizeof (FunctionBlob) +
1633             blob->n_signals * sizeof (SignalBlob) +
1634             blob->n_vfuncs * sizeof (VFuncBlob) +
1635             blob->n_constants * sizeof (ConstantBlob))
1636      
1637     {
1638       g_set_error (error,
1639                    G_TYPELIB_ERROR,
1640                    G_TYPELIB_ERROR_INVALID,
1641                    "The buffer is too short");
1642       return FALSE;
1643     }
1644
1645   offset2 = offset + sizeof (InterfaceBlob);
1646
1647   for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
1648     {
1649       DirEntry *entry;
1650       guint16 req;
1651
1652       req = *(guint16*)&typelib->data[offset2];
1653       if (req == 0 || req > header->n_entries)
1654         {
1655           g_set_error (error,
1656                        G_TYPELIB_ERROR,
1657                        G_TYPELIB_ERROR_INVALID_BLOB,
1658                        "Invalid prerequisite index");
1659           return FALSE; 
1660         }
1661
1662       entry = g_typelib_get_dir_entry (typelib, req);
1663       if (entry->blob_type != BLOB_TYPE_INTERFACE &&
1664           entry->blob_type != BLOB_TYPE_OBJECT &&
1665           (entry->local || entry->blob_type != 0))
1666         {
1667           g_set_error (error,
1668                        G_TYPELIB_ERROR,
1669                        G_TYPELIB_ERROR_INVALID_BLOB,
1670                        "Not an interface or object");
1671           return FALSE; 
1672         }
1673     }
1674
1675   offset2 += 2 * (blob->n_prerequisites % 2);
1676
1677   push_context (ctx, get_string_nofail (typelib, blob->name));
1678   
1679   for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
1680     {
1681       if (!validate_property_blob (typelib, offset2, error))
1682         return FALSE;
1683     }
1684
1685   for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
1686     {
1687       if (!validate_function_blob (ctx, offset2, BLOB_TYPE_INTERFACE, error))
1688         return FALSE;
1689     }
1690   
1691   for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
1692     {
1693       if (!validate_signal_blob (typelib, offset2, offset, error))
1694         return FALSE;
1695     }
1696   
1697   for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
1698     {
1699       if (!validate_vfunc_blob (typelib, offset2, offset, error))
1700         return FALSE;
1701     }
1702
1703   for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
1704     {
1705       if (!validate_constant_blob (typelib, offset2, error))
1706         return FALSE;
1707     }
1708
1709   pop_context (ctx);
1710
1711   return TRUE;
1712 }
1713
1714 static gboolean
1715 validate_errordomain_blob (GTypelib     *typelib,
1716                            guint32        offset,
1717                            GError       **error)
1718 {
1719   return TRUE;
1720 }
1721
1722 static gboolean
1723 validate_union_blob (GTypelib     *typelib,
1724                      guint32        offset,
1725                      GError       **error)
1726 {
1727   return TRUE;
1728 }
1729
1730 static gboolean
1731 validate_blob (ValidateContext *ctx,
1732                guint32          offset,
1733                GError         **error)
1734 {
1735   GTypelib *typelib = ctx->typelib;
1736   CommonBlob *common;
1737
1738   if (typelib->len < offset + sizeof (CommonBlob))
1739     {
1740       g_set_error (error,
1741                    G_TYPELIB_ERROR,
1742                    G_TYPELIB_ERROR_INVALID,
1743                    "The buffer is too short");
1744       return FALSE;
1745     }
1746
1747   common = (CommonBlob*)&typelib->data[offset];
1748   
1749   switch (common->blob_type)
1750     {
1751     case BLOB_TYPE_FUNCTION:
1752       if (!validate_function_blob (ctx, offset, 0, error))
1753         return FALSE;
1754       break;
1755     case BLOB_TYPE_CALLBACK:
1756       if (!validate_callback_blob (ctx, offset, error))
1757         return FALSE;
1758       break;
1759     case BLOB_TYPE_STRUCT:
1760     case BLOB_TYPE_BOXED:
1761       if (!validate_struct_blob (ctx, offset, common->blob_type, error))
1762         return FALSE;
1763       break;
1764     case BLOB_TYPE_ENUM:
1765     case BLOB_TYPE_FLAGS:
1766       if (!validate_enum_blob (ctx, offset, common->blob_type, error))
1767         return FALSE;
1768       break;
1769     case BLOB_TYPE_OBJECT:
1770       if (!validate_object_blob (ctx, offset, error))
1771         return FALSE;
1772       break;
1773     case BLOB_TYPE_INTERFACE:
1774       if (!validate_interface_blob (ctx, offset, error))
1775         return FALSE;
1776       break;
1777     case BLOB_TYPE_CONSTANT:
1778       if (!validate_constant_blob (typelib, offset, error))
1779         return FALSE;
1780       break;
1781     case BLOB_TYPE_ERROR_DOMAIN:
1782       if (!validate_errordomain_blob (typelib, offset, error))
1783         return FALSE;
1784       break;
1785     case BLOB_TYPE_UNION:
1786       if (!validate_union_blob (typelib, offset, error))
1787         return FALSE;
1788       break;
1789     default:
1790       g_set_error (error, 
1791                    G_TYPELIB_ERROR,
1792                    G_TYPELIB_ERROR_INVALID_ENTRY,
1793                    "Invalid blob type");
1794       return FALSE;
1795     }
1796
1797   return TRUE;
1798 }
1799
1800 static gboolean 
1801 validate_directory (ValidateContext   *ctx,
1802                     GError            **error)
1803 {
1804   GTypelib *typelib = ctx->typelib;
1805   Header *header = (Header *)typelib->data;
1806   DirEntry *entry;
1807   gint i;
1808   
1809   if (typelib->len < header->directory + header->n_entries * sizeof (DirEntry))
1810     {
1811       g_set_error (error,
1812                    G_TYPELIB_ERROR,
1813                    G_TYPELIB_ERROR_INVALID,
1814                    "The buffer is too short");
1815       return FALSE;
1816     }
1817
1818   for (i = 0; i < header->n_entries; i++)
1819     {
1820       entry = g_typelib_get_dir_entry (typelib, i + 1);
1821
1822       if (!validate_name (typelib, "entry", typelib->data, entry->name, error))
1823         return FALSE; 
1824       
1825       if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
1826           entry->blob_type > BLOB_TYPE_UNION)
1827         {
1828           g_set_error (error,
1829                        G_TYPELIB_ERROR,
1830                        G_TYPELIB_ERROR_INVALID_DIRECTORY,
1831                        "Invalid entry type");
1832           return FALSE; 
1833         }
1834
1835       if (i < header->n_local_entries)
1836         {
1837           if (!entry->local)
1838             {
1839               g_set_error (error,
1840                            G_TYPELIB_ERROR,
1841                            G_TYPELIB_ERROR_INVALID_DIRECTORY,
1842                            "Too few local directory entries");
1843               return FALSE;
1844             }
1845
1846           if (!is_aligned (entry->offset))
1847             {
1848               g_set_error (error,
1849                            G_TYPELIB_ERROR,
1850                            G_TYPELIB_ERROR_INVALID_DIRECTORY,
1851                            "Misaligned entry");
1852               return FALSE;
1853             }
1854
1855           if (!validate_blob (ctx, entry->offset, error))
1856             return FALSE;
1857         }
1858       else
1859         {
1860           if (entry->local)
1861             {
1862               g_set_error (error,
1863                            G_TYPELIB_ERROR,
1864                            G_TYPELIB_ERROR_INVALID_DIRECTORY,
1865                            "Too many local directory entries");
1866               return FALSE;
1867             }
1868
1869           if (!validate_name (typelib, "namespace", typelib->data, entry->offset, error))
1870             return FALSE; 
1871         }
1872     }
1873
1874   return TRUE;
1875 }
1876
1877 static gboolean
1878 validate_attributes (ValidateContext *ctx,
1879                      GError       **error)
1880 {
1881   GTypelib *typelib = ctx->typelib;
1882   Header *header = (Header *)typelib->data;
1883
1884   if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
1885     {
1886       g_set_error (error,
1887                    G_TYPELIB_ERROR,
1888                    G_TYPELIB_ERROR_INVALID,
1889                    "The buffer is too short");
1890       return FALSE;      
1891     }
1892   
1893   return TRUE;
1894 }
1895
1896 static void
1897 prefix_with_context (GError **error,
1898                      const char *section,
1899                      ValidateContext *ctx)
1900 {
1901   GString *str = g_string_new (NULL);
1902   GSList *link;
1903   char *buf;
1904   
1905   link = ctx->context_stack;
1906   if (!link)
1907     {
1908       g_prefix_error (error, "In %s:", section);
1909       return;
1910     }
1911
1912   for (; link; link = link->next)
1913     {
1914       g_string_append (str, link->data);
1915       if (link->next)
1916         g_string_append_c (str, '/');
1917     }
1918   g_string_append_c (str, ')');
1919   buf = g_string_free (str, FALSE);
1920   g_prefix_error (error, "In %s (Context: %s): ", section, buf);
1921   g_free (buf);
1922 }
1923
1924 gboolean 
1925 g_typelib_validate (GTypelib     *typelib,
1926                      GError       **error)
1927 {
1928   ValidateContext ctx;
1929   ctx.typelib = typelib;
1930   ctx.context_stack = NULL;
1931
1932   if (!validate_header (&ctx, error))
1933     {
1934       prefix_with_context (error, "In header", &ctx);
1935       return FALSE;
1936     }
1937
1938   if (!validate_directory (&ctx, error))
1939     {
1940       prefix_with_context (error, "directory", &ctx);
1941       return FALSE;
1942     }
1943
1944   if (!validate_attributes (&ctx, error))
1945     {
1946       prefix_with_context (error, "attributes", &ctx);
1947       return FALSE;
1948     }
1949
1950   return TRUE;
1951 }
1952
1953 GQuark
1954 g_typelib_error_quark (void)
1955 {
1956   static GQuark quark = 0;
1957   if (quark == 0)
1958     quark = g_quark_from_static_string ("g-typelib-error-quark");
1959   return quark;
1960 }
1961
1962 static void
1963 _g_typelib_do_dlopen (GTypelib *typelib)
1964 {
1965   Header *header;
1966   const char *shlib_str;
1967   
1968   header = (Header *) typelib->data;
1969   /* note that NULL shlib means to open the main app, which is allowed */
1970   if (header->shared_library)
1971     shlib_str = g_typelib_get_string (typelib, header->shared_library);
1972   else
1973     shlib_str = NULL;
1974
1975   if (shlib_str != NULL && shlib_str[0] != '\0')
1976     {
1977       gchar **shlibs;
1978       gint i;
1979
1980       /* shared-library is a comma-separated list of libraries */
1981       shlibs = g_strsplit (shlib_str, ",", 0);
1982
1983        /* We load all passed libs unconditionally as if the same library is loaded
1984         * again with dlopen(), the same file handle will be returned. See bug:
1985         * http://bugzilla.gnome.org/show_bug.cgi?id=555294
1986         */
1987       for (i = 0; shlibs[i]; i++)
1988         {
1989           GModule *module;
1990
1991           /* Glade's autoconnect feature and OpenGL's extension mechanism
1992            * as used by Clutter rely on dlopen(NULL) to work as a means of
1993            * accessing the app's symbols. This keeps us from using
1994            * G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
1995            * in general libraries are not expecting multiple copies of
1996            * themselves and are not expecting to be unloaded. So we just
1997            * load modules globally for now.
1998            */
1999
2000           module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
2001
2002           if (module == NULL)
2003             {
2004               GString *shlib_full = g_string_new (shlibs[i]);
2005
2006               /* Prefix with "lib", try both .la and .so */
2007               if (!g_str_has_prefix (shlib_full->str, "lib"))
2008                 g_string_prepend (shlib_full, "lib");
2009               g_string_append (shlib_full, ".la");
2010               module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2011               if (module == NULL)
2012                 {
2013                   g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
2014                   module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
2015                 }
2016
2017               g_string_free (shlib_full, TRUE);
2018             }
2019
2020           if (module == NULL)
2021             {
2022               g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
2023                          shlibs[i], g_module_error ());
2024             }
2025           else
2026             {
2027               typelib->modules = g_list_append (typelib->modules, module);
2028             }
2029        }
2030
2031       g_strfreev (shlibs);
2032     }
2033   else
2034     {
2035       /* If there's no shared-library entry for this module, assume that
2036        * the module is for the application.  Some of the hand-written .gir files
2037        * in gobject-introspection don't have shared-library entries, but no one
2038        * is really going to be calling g_module_symbol on them either.
2039        */
2040       GModule *module = g_module_open (NULL, 0);
2041       if (module == NULL)
2042         g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
2043       else
2044         typelib->modules = g_list_prepend (typelib->modules, module);
2045     }
2046 }
2047
2048 static inline void
2049 _g_typelib_ensure_open (GTypelib *typelib)
2050 {
2051   if (typelib->open_attempted)
2052     return;
2053   typelib->open_attempted = TRUE;
2054   _g_typelib_do_dlopen (typelib);
2055 }
2056
2057 /**
2058  * g_typelib_new_from_memory:
2059  * @memory: address of memory chunk containing the typelib
2060  * @len: length of memory chunk containing the typelib
2061  * 
2062  * Creates a new #GTypelib from a memory location.  The memory block
2063  * pointed to by @typelib will be automatically g_free()d when the
2064  * repository is destroyed.
2065  * 
2066  * Return value: the new #GTypelib
2067  **/
2068 GTypelib *
2069 g_typelib_new_from_memory (guchar *memory, gsize len)
2070 {
2071   GTypelib *meta;
2072
2073   meta = g_new0 (GTypelib, 1);
2074   meta->data = memory;
2075   meta->len = len;
2076   meta->owns_memory = TRUE;
2077   meta->modules = NULL;
2078
2079   return meta;
2080 }
2081
2082 /**
2083  * g_typelib_new_from_const_memory:
2084  * @memory: address of memory chunk containing the typelib
2085  * @len: length of memory chunk containing the typelib
2086  * 
2087  * Creates a new #GTypelib from a memory location.
2088  * 
2089  * Return value: the new #GTypelib
2090  **/
2091 GTypelib *
2092 g_typelib_new_from_const_memory (const guchar *memory, gsize len)
2093 {
2094   GTypelib *meta;
2095
2096   meta = g_new0 (GTypelib, 1);
2097   meta->data = (guchar *) memory;
2098   meta->len = len;
2099   meta->owns_memory = FALSE;
2100   meta->modules = NULL;
2101
2102   return meta;
2103 }
2104
2105 /**
2106  * g_typelib_new_from_mapped_file:
2107  * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
2108  * 
2109  * Creates a new #GTypelib from a #GMappedFile.
2110  * 
2111  * Return value: the new #GTypelib
2112  **/
2113 GTypelib *
2114 g_typelib_new_from_mapped_file (GMappedFile *mfile)
2115 {
2116   GTypelib *meta;
2117
2118   meta = g_new0 (GTypelib, 1);
2119   meta->mfile = mfile;
2120   meta->owns_memory = FALSE;
2121   meta->data = (guchar *) g_mapped_file_get_contents (mfile);
2122   meta->len = g_mapped_file_get_length (mfile);
2123
2124   return meta;
2125 }
2126
2127 /**
2128  * g_typelib_free:
2129  * @typelib: a #GTypelib
2130  * 
2131  * Free a #GTypelib.
2132  **/
2133 void
2134 g_typelib_free (GTypelib *typelib)
2135 {
2136   if (typelib->mfile)
2137     g_mapped_file_free (typelib->mfile);
2138   else
2139     if (typelib->owns_memory)
2140       g_free (typelib->data);
2141   if (typelib->modules)
2142     {
2143       g_list_foreach (typelib->modules, (GFunc) g_module_close, NULL);
2144       g_list_free (typelib->modules);
2145     }
2146   g_free (typelib);
2147 }
2148
2149 const gchar *
2150 g_typelib_get_namespace (GTypelib *typelib)
2151 {
2152   return g_typelib_get_string (typelib, ((Header *) typelib->data)->namespace);
2153 }
2154
2155 /**
2156  * g_typelib_symbol:
2157  * @typelib: the typelib
2158  * @symbol_name: name of symbol to be loaded
2159  * @symbol: returns a pointer to the symbol value
2160  *
2161  * Loads a symbol from #GTypelib.
2162  *
2163  * Return value: #TRUE on success
2164  **/
2165 gboolean
2166 g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
2167 {
2168   GList *l;
2169   
2170   _g_typelib_ensure_open (typelib);
2171
2172   /*
2173    * The reason for having multiple modules dates from gir-repository
2174    * when it was desired to inject code (accessors, etc.) into an
2175    * existing library.  In that situation, the first module listed
2176    * will be the custom one, which overrides the main one.  A bit
2177    * inefficient, but the problem will go away when gir-repository
2178    * does.
2179    * 
2180    * For modules with no shared library, we dlopen'd the current
2181    * process above.  
2182    */
2183   for (l = typelib->modules; l; l = l->next)
2184     {
2185       GModule *module = l->data;
2186
2187       if (g_module_symbol (module, symbol_name, symbol))
2188         return TRUE;
2189     }
2190
2191   return FALSE;
2192 }