cf0695f0138ca19c34c9fd21088dd296295e7d46
[m6w6/ext-psi] / src / context_validate.c
1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include "php.h"
6
7 #include <sys/param.h>
8 #include <dlfcn.h>
9
10 #include "php_psi.h"
11 #include "php_psi_stdinc.h"
12 #include "php_psi_stdtypes.h"
13 #include "php_psi_macros.h"
14 #include "php_psi_redirs.h"
15
16 #include "calc.h"
17 #include "marshal.h"
18 #include "engine.h"
19
20 static int validate_lib(PSI_Data *data, void **dlopened) {
21 char lib[MAXPATHLEN];
22 const char *ptr = data->psi.file.ln;
23 size_t len;
24
25 if (!ptr) {
26 /* FIXME: assume stdlib */
27 return 1;
28 } else if (!strchr(ptr, '/')) {
29 len = snprintf(lib, MAXPATHLEN, "lib%s.%s", ptr, PHP_PSI_SHLIB_SUFFIX);
30 if (MAXPATHLEN == len) {
31 data->error(data, NULL, PSI_WARNING, "Library name too long: '%s'", ptr);
32 }
33 lib[len] = 0;
34 ptr = lib;
35 }
36 if (!(*dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
37 data->error(data, NULL, PSI_WARNING, "Could not open library '%s': %s.",
38 data->psi.file.ln, dlerror());
39 return 0;
40 }
41 return 1;
42 }
43
44 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
45 size_t i;
46 struct psi_std_type *stdtyp;
47
48 if (type->real) {
49 return 1;
50 }
51 if (defs) for (i = 0; i < defs->count; ++i) {
52 decl_arg *def = defs->list[i];
53
54 if (def->type->type != type->type && !strcmp(def->var->name, type->name)) {
55 type->real = def->type;
56 return 1;
57 }
58 }
59 for (stdtyp = &psi_std_types[0]; stdtyp->type_tag; ++stdtyp) {
60 if (!strcmp(type->name, stdtyp->alias ?: stdtyp->type_name)) {
61 type->type = stdtyp->type_tag;
62 return 1;
63 }
64 }
65
66 return 0;
67 }
68
69 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
70 size_t i;
71
72 if (type->strct) {
73 return 1;
74 }
75 if (structs) for (i = 0; i < structs->count; ++i) {
76 if (!strcmp(structs->list[i]->name, type->name)) {
77 type->strct = structs->list[i];
78 return 1;
79 }
80 }
81 return 0;
82 }
83
84 static inline int locate_decl_type_union(decl_unions *unions, decl_type *type) {
85 size_t i;
86
87 if (type->unn) {
88 return 1;
89 }
90 if (unions) for (i = 0; i < unions->count; ++i) {
91 if (!strcmp(unions->list[i]->name, type->name)) {
92 type->unn = unions->list[i];
93 return 1;
94 }
95 }
96 return 0;
97 }
98
99 static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) {
100 size_t i;
101
102 if (type->enm) {
103 return 1;
104 }
105 if (enums) for (i = 0; i < enums->count; ++i) {
106 if (!strcmp(enums->list[i]->name, type->name)) {
107 type->enm = enums->list[i];
108 return 1;
109 }
110 }
111 return 0;
112 }
113
114 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
115 static inline int validate_decl_union(PSI_Data *data, decl_union *u);
116 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e);
117
118 static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
119 switch (type->type) {
120 case PSI_T_CHAR:
121 case PSI_T_SHORT:
122 case PSI_T_INT:
123 case PSI_T_LONG:
124 case PSI_T_NAME:
125 if (!locate_decl_type_alias(data->defs, type)) {
126 return 0;
127 }
128 if (type->real) {
129 return validate_decl_type(data, type->real);
130 }
131 return 1;
132 case PSI_T_STRUCT:
133 if (!locate_decl_type_struct(data->structs, type)) {
134 return 0;
135 }
136 break;
137 case PSI_T_UNION:
138 if (!locate_decl_type_union(data->unions, type)) {
139 return 0;
140 }
141 break;
142 case PSI_T_ENUM:
143 if (!locate_decl_type_enum(data->enums, type)) {
144 return 0;
145 }
146 }
147 return 1;
148 }
149 static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
150 if (!validate_decl_type(data, def->type)) {
151 data->error(data, def->token, PSI_WARNING,
152 "Type '%s' cannot be aliased to %s'%s'",
153 def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",
154 def->var->name);
155 return 0;
156 }
157 return 1;
158 }
159
160 static inline int validate_constant(PSI_Data *data, constant *c) {
161 /* FIXME */
162 return 1;
163 }
164
165 static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
166 if (!validate_decl_type(data, arg->type)) {
167 data->error(data, arg->type->token, PSI_WARNING,
168 "Cannot use '%s' as type for '%s'",
169 arg->type->name, arg->var->name);
170 return 0;
171 }
172 return 1;
173 }
174
175 static int psi_sort_struct_arg_cmp(const void *_a, const void *_b) {
176 decl_arg *a = *(decl_arg **)_a, *b = *(decl_arg **)_b;
177
178 if (a->layout->pos == b->layout->pos) {
179 if (a->layout->len == b->layout->len) {
180 return 0;
181 } else if (a->layout->len > b->layout->len) {
182 return -1;
183 } else {
184 return 1;
185 }
186 } else if (a->layout->pos > b->layout->pos) {
187 return 1;
188 } else {
189 return -1;
190 }
191 }
192 static void psi_sort_struct_arg_swp(void *a, void *b) {
193 decl_arg **_a = a, **_b = b, *_c;
194
195 _c = *_b;
196 *_b = *_a;
197 *_a = _c;
198 }
199 static inline void psi_sort_struct_args(void **args, size_t count) {
200 zend_insert_sort(args, count, sizeof(*args),
201 psi_sort_struct_arg_cmp, psi_sort_struct_arg_swp);
202 }
203
204 static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg, void *current) {
205 decl_type *real = real_decl_type(darg->type);
206
207 /* pre-validate any structs/unions/enums */
208 switch (real->type) {
209 case PSI_T_STRUCT:
210 if (current && current == real->strct) {
211 return 1;
212 }
213 if (!validate_decl_struct(data, real->strct)) {
214 return 0;
215 }
216 break;
217 case PSI_T_UNION:
218 if (current && current == real->unn) {
219 return 1;
220 }
221 if (!validate_decl_union(data, real->unn)) {
222 return 0;
223 }
224 break;
225 case PSI_T_ENUM:
226 if (current && current == real->enm) {
227 return 1;
228 }
229 if (!validate_decl_enum(data, real->enm)) {
230 return 0;
231 }
232 break;
233 }
234
235 return 1;
236 }
237
238 static inline size_t sizeof_decl_arg(decl_arg *darg) {
239 size_t size;
240 decl_type *real = real_decl_type(darg->type);
241
242 if (darg->var->array_size) {
243 if (darg->var->pointer_level > 2) {
244 size = psi_t_size(PSI_T_POINTER) * darg->var->array_size;
245 } else {
246 size = psi_t_size(real->type) * darg->var->array_size;
247 }
248 } else if (darg->var->pointer_level) {
249 size = psi_t_size(PSI_T_POINTER);
250 } else {
251 switch (real->type) {
252 case PSI_T_UNION:
253 size = real->unn->size;
254 break;
255 case PSI_T_STRUCT:
256 size = real->strct->size;
257 break;
258 case PSI_T_ENUM:
259 default:
260 size = psi_t_size(real->type);
261 break;
262 }
263 }
264
265 ZEND_ASSERT(size);
266
267 return size;
268 }
269
270 static inline size_t alignof_decl_type(decl_type *t);
271 static inline size_t alignof_decl_arg(decl_arg *darg);
272 static inline size_t alignof_decl_union(decl_union *u);
273 static inline size_t alignof_decl_struct(decl_struct *s);
274
275 static inline size_t alignof_decl_args(decl_args *args) {
276 size_t i, maxalign = 0;
277
278 for (i = 0; i < args->count; ++i) {
279 decl_arg *darg = args->args[i];
280 size_t align = alignof_decl_arg(darg);
281
282 if (align > maxalign) {
283 maxalign = align;
284 }
285 }
286
287 return maxalign;
288 }
289
290 static inline size_t alignof_decl_struct(decl_struct *s) {
291 if (!s->align) {
292 s->align = alignof_decl_args(s->args);
293 }
294 return s->align;
295 }
296
297 static inline size_t alignof_decl_union(decl_union *u) {
298 if (!u->align) {
299 u->align = alignof_decl_args(u->args);
300 }
301 return u->align;
302 }
303
304 static inline size_t alignof_decl_type(decl_type *t) {
305 decl_type *real = real_decl_type(t);
306 size_t align;
307
308 switch (real->type) {
309 case PSI_T_STRUCT:
310 align = alignof_decl_struct(real->strct);
311 break;
312 case PSI_T_UNION:
313 align = alignof_decl_union(real->unn);
314 break;
315 case PSI_T_ENUM:
316 default:
317 align = psi_t_alignment(real->type);
318 }
319
320 return align;
321 }
322
323 static inline size_t alignof_decl_arg(decl_arg *darg) {
324 size_t align;
325
326 if (darg->var->pointer_level && (!darg->var->array_size || darg->var->pointer_level > 2)) {
327 align = psi_t_alignment(PSI_T_POINTER);
328 } else {
329 align = alignof_decl_type(darg->type);
330 }
331
332 return align;
333 }
334
335 static inline size_t align_decl_arg(decl_arg *darg, size_t *pos, size_t *len) {
336 size_t align = alignof_decl_arg(darg);
337
338 ZEND_ASSERT(align);
339
340 *len = sizeof_decl_arg(darg);
341 *pos = psi_align(align, *pos);
342
343 return align;
344 }
345
346 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
347 size_t i, pos, len, size, align;
348
349 if (!s->size && !s->args->count) {
350 data->error(data, s->token, PSI_WARNING,
351 "Cannot compute size of empty struct %s",
352 s->name);
353 return 0;
354 }
355
356 for (i = 0; i < s->args->count; ++i) {
357 decl_arg *darg = s->args->args[i];
358
359 if (!validate_decl_arg(data, darg)) {
360 return 0;
361 }
362
363 ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
364 darg->var->arg = darg;
365
366 if (!validate_decl_struct_darg(data, darg, s)) {
367 return 0;
368 } else if (darg->layout) {
369 pos = darg->layout->pos;
370
371 align = align_decl_arg(darg, &pos, &len);
372
373 if (darg->layout->len != len) {
374 data->error(data, darg->token, PSI_WARNING,
375 "Computed size %zu of %s.%s does not match"
376 " pre-defined size %zu of type '%s'",
377 len, s->name, darg->var->name, darg->layout->len,
378 darg->type->name);
379 }
380 if (darg->layout->pos != pos) {
381 data->error(data, darg->token, PSI_WARNING,
382 "Computed offset %zu of %s.%s does not match"
383 " pre-defined offset %zu",
384 pos, s->name, darg->var->name, darg->layout->pos);
385 }
386 } else {
387 if (i) {
388 pos = s->args->args[i-1]->layout->pos +
389 s->args->args[i-1]->layout->len;
390 } else {
391 pos = 0;
392 }
393
394 align = align_decl_arg(darg, &pos, &len);
395 darg->layout = init_decl_struct_layout(pos, len);
396 }
397
398 if (align > s->align) {
399 s->align = align;
400 }
401 }
402
403 psi_sort_struct_args((void **) s->args->args, s->args->count);
404
405 if (s->args->count) {
406 decl_arg *darg = s->args->args[s->args->count-1];
407
408 size = darg->layout->pos + darg->layout->len;
409 if (s->size < size) {
410 s->size = psi_align(size, s->align);
411 }
412 }
413
414 return 1;
415 }
416
417 static inline int validate_decl_union(PSI_Data *data, decl_union *u) {
418 size_t i, pos, len, size = 0, align;
419
420 if (!u->size && !u->args->count) {
421 data->error(data, u->token, PSI_WARNING,
422 "Cannot compute size of empty union %s",
423 u->name);
424 return 0;
425 }
426
427 for (i = 0; i < u->args->count; ++i) {
428 decl_arg *darg = u->args->args[i];
429
430 if (!validate_decl_arg(data, darg)) {
431 return 0;
432 }
433
434 ZEND_ASSERT(!darg->var->arg || darg->var->arg == darg);
435 darg->var->arg = darg;
436
437 if (!validate_decl_struct_darg(data, darg, u)) {
438 return 0;
439 } else if (darg->layout) {
440 pos = darg->layout->pos;
441
442 align = align_decl_arg(darg, &pos, &len);
443
444 if (darg->layout->pos != 0) {
445 data->error(data, darg->token, PSI_WARNING,
446 "Offset of %s.%s should be 0",
447 u->name, darg->var->name);
448 darg->layout->pos = 0;
449 }
450 if (darg->layout->len != len) {
451 data->error(data, darg->token, PSI_WARNING,
452 "Computed size %zu of %s.%s does not match"
453 " pre-defined size %zu of type '%s'",
454 len, u->name, darg->var->name, darg->layout->len,
455 darg->type->name);
456 }
457 } else {
458 pos = 0;
459
460 align = align_decl_arg(darg, &pos, &len);
461 darg->layout = init_decl_struct_layout(pos, len);
462
463 }
464 if (len > size) {
465 size = len;
466 }
467 if (align > u->align) {
468 u->align = align;
469 }
470 }
471
472 psi_sort_struct_args((void **) u->args->args, u->args->count);
473
474 if (u->size < size) {
475 u->size = psi_align(size, u->align);
476 }
477
478 return 1;
479 }
480
481 static const char * const abi_ccs[] = {
482 "default", /* \ */
483 "extern", /* > - all the same */
484 "cdecl", /* / */
485 "mscdecl",
486 "stdcall",
487 "fastcall",
488 };
489 static inline int validate_decl_abi(PSI_Data *data, decl_abi *abi) {
490 size_t i;
491
492 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) {
493 if (strcasecmp(abi->convention, abi_ccs[i])) {
494 return 1;
495 }
496 }
497 return 0;
498 }
499 static inline int validate_decl_func(PSI_Data *data, void *dl, decl *decl, decl_arg *func)
500 {
501 struct psi_func_redir *redir;
502
503 if (!strcmp(func->var->name, "dlsym")) {
504 data->error(data, func->token, PSI_WARNING, "Cannot dlsym dlsym (sic!)");
505 return 0;
506 }
507
508 if (!validate_decl_arg(data, func)) {
509 return 0;
510 }
511 for (redir = &psi_func_redirs[0]; redir->name; ++redir) {
512 if (!strcmp(func->var->name, redir->name)) {
513 decl->call.sym = redir->func;
514 }
515 }
516 if (!decl->call.sym) {
517 #ifndef RTLD_NEXT
518 # define RTLD_NEXT ((void *) -1l)
519 #endif
520 decl->call.sym = dlsym(dl ?: RTLD_NEXT, func->var->name);
521 if (!decl->call.sym) {
522 data->error(data, func->token, PSI_WARNING,
523 "Failed to locate symbol '%s': %s",
524 func->var->name, dlerror() ?: "not found");
525 }
526 }
527 return 1;
528 }
529
530 static inline int validate_decl(PSI_Data *data, void *dl, decl *decl) {
531 if (!validate_decl_abi(data, decl->abi)) {
532 data->error(data, decl->abi->token, PSI_WARNING,
533 "Invalid calling convention: '%s'", decl->abi->token->text);
534 return 0;
535 }
536 if (!validate_decl_func(data, dl, decl, decl->func)) {
537 return 0;
538 }
539 if (decl->args) {
540 size_t i;
541
542 for (i = 0; i < decl->args->count; ++i) {
543 if (!validate_decl_arg(data, decl->args->args[i])) {
544 return 0;
545 }
546 }
547 }
548 return 1;
549 }
550 static inline decl_arg *locate_decl_var_arg(decl_var *var, decl_args *args, decl_arg *func) {
551 size_t i;
552
553 if (args) for (i = 0; i < args->count; ++i) {
554 decl_arg *arg = args->args[i];
555
556 if (!strcmp(var->name, arg->var->name)) {
557 ZEND_ASSERT(!var->arg || var->arg == arg);
558 return var->arg = arg;
559 }
560 }
561 if (func && !strcmp(var->name, func->var->name)) {
562 return var->arg = func;
563 }
564
565 return NULL;
566 }
567 static inline decl_arg *locate_struct_member(decl_struct *s, decl_var *var) {
568 if (s->args) {
569 return locate_decl_var_arg(var, s->args, NULL);
570 }
571
572 return NULL;
573 }
574 static inline constant *locate_num_exp_constant(num_exp *exp, constants *consts) {
575 size_t i;
576
577 for (i = 0; i < consts->count; ++i) {
578 constant *cnst = consts->list[i];
579
580 if (!strcmp(cnst->name, exp->u.numb)) {
581 free(exp->u.numb);
582 return exp->u.cnst = cnst;
583 }
584 }
585
586 return NULL;
587 }
588 static inline decl_enum_item *locate_num_exp_enum_item_ex(num_exp *exp, decl_enum *e) {
589 size_t k;
590
591 if (e) for (k = 0; k < e->items->count; ++k) {
592 decl_enum_item *i = e->items->list[k];
593
594 if (!strcmp(i->name, exp->u.dvar->name)) {
595 free_decl_var(exp->u.dvar);
596 exp->t = PSI_T_ENUM;
597 exp->u.enm = i;
598 return i;
599 }
600 }
601 return NULL;
602 }
603 static inline decl_enum_item *locate_num_exp_enum_item(num_exp *exp, decl_enums *enums) {
604 size_t j;
605
606 if (enums) for (j = 0; j < enums->count; ++j) {
607 decl_enum *e = enums->list[j];
608 decl_enum_item *i = locate_num_exp_enum_item_ex(exp, e);
609
610 if (i) {
611 return i;
612 }
613 }
614 return NULL;
615 }
616 static inline int validate_num_exp(PSI_Data *data, num_exp *exp, decl_args *dargs, decl_arg *func, decl_enum *enm) {
617 if (exp->operand) {
618 switch (exp->operator) {
619 case PSI_T_PLUS:
620 exp->calculator = psi_calc_add;
621 break;
622 case PSI_T_MINUS:
623 exp->calculator = psi_calc_sub;
624 break;
625 case PSI_T_ASTERISK:
626 exp->calculator = psi_calc_mul;
627 break;
628 case PSI_T_SLASH:
629 exp->calculator = psi_calc_div;
630 break;
631 EMPTY_SWITCH_DEFAULT_CASE();
632 }
633 if (!validate_num_exp(data, exp->operand, dargs, func, enm)) {
634 return 0;
635 }
636 }
637 switch (exp->t) {
638 case PSI_T_NAME:
639 if (!locate_decl_var_arg(exp->u.dvar, dargs, func)) {
640 if (!locate_num_exp_enum_item(exp, data->enums) && !locate_num_exp_enum_item_ex(exp, enm)) {
641 data->error(data, exp->token, PSI_WARNING, "Unknown variable '%s' in numeric expression",
642 exp->u.dvar->name);
643 return 0;
644 }
645 }
646 return 1;
647 case PSI_T_NSNAME:
648 if (!locate_num_exp_constant(exp, data->consts)) {
649 data->error(data, exp->token, PSI_WARNING, "Unknown constant '%s' in numeric expression",
650 exp->u.numb);
651 return 0;
652 }
653 return 1;
654 case PSI_T_NUMBER:
655 case PSI_T_ENUM:
656 return 1;
657 default:
658 return 0;
659 }
660 }
661
662 static inline int validate_decl_enum(PSI_Data *data, decl_enum *e) {
663 size_t j;
664
665 if (!e->items || !e->items->count) {
666 data->error(data, e->token, PSI_WARNING, "Empty enum '%s'", e->name);
667 return 0;
668 }
669
670 for (j = 0; j < e->items->count; ++j) {
671 decl_enum_item *i = e->items->list[j];
672
673 if (!i->num) {
674 if (j) {
675 i->inc.t = PSI_T_NUMBER;
676 i->inc.u.numb = "1";
677 i->inc.operator = PSI_T_PLUS;
678 i->inc.operand = i->prev->num ?: &i->prev->inc;
679 i->num = &i->inc;
680 } else {
681 i->inc.t = PSI_T_NUMBER;
682 i->inc.u.numb = "0";
683 i->num = &i->inc;
684 }
685 }
686 if (!validate_num_exp(data, i->num, NULL, NULL, e)) {
687 return 0;
688 }
689 }
690
691 return 1;
692 }
693
694 static inline int validate_set_value_handler(set_value *set) {
695 switch (set->func->type) {
696 case PSI_T_TO_BOOL:
697 set->func->handler = psi_to_bool;
698 break;
699 case PSI_T_TO_INT:
700 set->func->handler = psi_to_int;
701 break;
702 case PSI_T_TO_FLOAT:
703 set->func->handler = psi_to_double;
704 break;
705 case PSI_T_TO_STRING:
706 set->func->handler = psi_to_string;
707 break;
708 case PSI_T_TO_ARRAY:
709 set->func->handler = psi_to_array;
710 break;
711 case PSI_T_TO_OBJECT:
712 set->func->handler = psi_to_object;
713 break;
714 case PSI_T_VOID:
715 set->func->handler = psi_to_void;
716 break;
717 case PSI_T_ELLIPSIS:
718 if (set->outer.set && set->outer.set->func->type == PSI_T_TO_ARRAY) {
719 set->func->handler = psi_to_recursive;
720 set->inner = set->outer.set->inner;
721 set->count = set->outer.set->count;
722 break;
723 }
724 /* no break */
725 default:
726 return 0;
727 }
728 return 1;
729 }
730 static inline void decl_var_arg_v(decl_args *args, va_list argp) {
731 int argc;
732 decl_arg **argv;
733
734 memset(args, 0, sizeof(*args));
735
736 while ((argc = va_arg(argp, int))) {
737 argv = va_arg(argp, decl_arg **);
738 while (argc--) {
739 add_decl_arg(args, *argv++);
740 }
741 }
742 }
743 static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg *ref, decl_args *ref_list) {
744 size_t i;
745 decl_type *ref_type;
746 decl_var *set_var = set->vars->vars[0];
747
748 if (!validate_set_value_handler(set)) {
749 data->error(data, set->func->token, PSI_WARNING, "Invalid cast '%s' in `set` statement", set->func->name);
750 return 0;
751 }
752
753 for (i = 0; i < set->vars->count; ++i) {
754 decl_var *svar = set->vars->vars[i];
755 if (!svar->arg && !locate_decl_var_arg(svar, ref_list, NULL)) {
756 data->error(data, svar->token, PSI_WARNING, "Unknown variable '%s' in `set` statement", svar->name);
757 return 0;
758 }
759 }
760
761 if (!ref) {
762 ref = set_var->arg;
763 }
764 ref_type = real_decl_type(ref->type);
765
766 if (set->count) {
767 int is_to_array = (set->func->type == PSI_T_TO_ARRAY);
768 int is_pointer_to_struct = (ref_type->type == PSI_T_STRUCT && ref->var->pointer_level);
769
770 if (!is_to_array && !is_pointer_to_struct) {
771 data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts only work with "
772 "to_array() casts on structs or pointers: %s(%s...", set->func->name, set->vars->vars[0]->name);
773 return 0;
774 }
775 }
776 if (set->num) {
777 if (!validate_num_exp(data, set->num, ref_list, ref, NULL)) {
778 return 0;
779 }
780 }
781
782 if (ref_type->type == PSI_T_STRUCT) {
783 /* to_array(struct, to_...) */
784 if (!set->outer.set || set->outer.set->inner != set->inner) {
785 for (i = 0; i < set->count; ++i) {
786 decl_var *sub_var = set->inner[i]->vars->vars[0];
787 decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var);
788
789 if (sub_ref) {
790 if (!validate_set_value_ex(data, set->inner[i], sub_ref, ref_type->strct->args)) {
791 return 0;
792 }
793 }
794 }
795 }
796 } else if (set->count == 1) {
797 /* to_array(ptr, to_string(*ptr)) */
798 decl_var *sub_var = set->inner[0]->vars->vars[0];
799 decl_arg *sub_ref = locate_decl_var_arg(sub_var, ref_list, ref);
800
801 if (sub_ref) {
802 if (strcmp(sub_var->name, set_var->name)) {
803 data->error(data, sub_var->token, E_WARNING, "Inner `set` statement casts on pointers must reference the same variable");
804 return 0;
805 }
806 if (!validate_set_value_ex(data, set->inner[0], sub_ref, ref_list)) {
807 return 0;
808 }
809 }
810 } else if (set->count > 1) {
811 data->error(data, set->func->token, E_WARNING, "Inner `set` statement casts on pointers may only occur once");
812 return 0;
813 }
814
815 return 1;
816 }
817 static inline int validate_set_value(PSI_Data *data, set_value *set, ...) {
818 va_list argp;
819 decl_args args = {0};
820 int check;
821
822 va_start(argp, set);
823 decl_var_arg_v(&args, argp);
824 va_end(argp);
825
826 check = validate_set_value_ex(data, set, NULL, &args);
827 if (args.args) {
828 free(args.args);
829 }
830 return check;
831 }
832 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
833 if (decls) {
834 size_t i;
835
836 for (i = 0; i < decls->count; ++i) {
837 if (!strcmp(decls->list[i]->func->var->name, ret->set->vars->vars[0]->name)) {
838 ret->decl = decls->list[i]->func;
839 return decls->list[i];
840 }
841 }
842 }
843
844 return NULL;
845 }
846 static inline int validate_impl_ret_stmt(PSI_Data *data, impl *impl) {
847 return_stmt *ret;
848
849 /* we must have exactly one ret stmt delcaring the native func to call */
850 /* and which type cast to apply */
851 if (impl->stmts->ret.count != 1) {
852 if (impl->stmts->ret.count > 1) {
853 data->error(data, impl->stmts->ret.list[1]->token, PSI_WARNING,
854 "Too many `return` statements for implmentation %s;"
855 " found %zu, exactly one is needed",
856 impl->func->name, impl->stmts->ret.count);
857 } else {
858 data->error(data, impl->func->token, PSI_WARNING,
859 "Missing `return` statement for implementation %s",
860 impl->func->name);
861 }
862 return 0;
863 }
864
865 ret = impl->stmts->ret.list[0];
866
867 if (!(impl->decl = locate_impl_decl(data->decls, ret))) {
868 data->error(data, ret->token, PSI_WARNING,
869 "Missing declaration '%s' for `return` statment for implementation %s",
870 ret->set->vars->vars[0]->name, impl->func->name);
871 return 0;
872 }
873
874 if (!validate_set_value(data, ret->set, 1, &ret->decl, impl->decl->args ? (int) impl->decl->args->count : 0, impl->decl->args ? impl->decl->args->args : NULL, 0)) {
875 return 0;
876 }
877
878 impl->decl->impl = impl;
879
880 return 1;
881 }
882
883 static inline int validate_impl_let_stmts(PSI_Data *data, impl *impl) {
884 size_t i, j;
885 /* we can have multiple let stmts */
886
887 /* check that we have a decl arg for every let stmt */
888 for (i = 0; i < impl->stmts->let.count; ++i) {
889 let_stmt *let = impl->stmts->let.list[i];
890 decl_var *let_var;
891 int check = 0;
892
893 if (let->val && let->val->kind == PSI_LET_TMP) {
894 let_var = let->val->data.var;
895 } else {
896 let_var = let->var;
897 }
898
899 if (!locate_decl_var_arg(let_var, impl->decl->args, impl->decl->func)) {
900 data->error(data, let_var->token, PSI_WARNING, "Unknown variable '%s' in `let` statement"
901 " of implementation '%s'", let_var->name, impl->func->name);
902 return 0;
903 }
904
905 switch (let->val->kind) {
906 case PSI_LET_NULL:
907 break;
908 case PSI_LET_TMP:
909 /* e.g. let bar = &strval($bar); // decl_arg(char **bar) */
910 /* e.g. let foo = *bar; */
911 let->var->pointer_level = let->val->data.var->pointer_level;
912 let->var->arg = init_decl_arg(
913 init_decl_type(
914 real_decl_type(let->val->data.var->arg->type)->type,
915 real_decl_type(let->val->data.var->arg->type)->name),
916 init_decl_var(
917 let->var->name,
918 let->var->pointer_level,
919 let->var->array_size));
920 break;
921 case PSI_LET_NUMEXP:
922 if (!validate_num_exp(data, let->val->data.num, impl->decl->args, impl->decl->func, NULL)) {
923 return 0;
924 }
925 break;
926 case PSI_LET_CALLOC:
927 if (!validate_num_exp(data, let->val->data.alloc->nmemb, impl->decl->args, impl->decl->func, NULL)) {
928 return 0;
929 }
930 if (!validate_num_exp(data, let->val->data.alloc->size, impl->decl->args, impl->decl->func, NULL)) {
931 return 0;
932 }
933 break;
934 case PSI_LET_FUNC:
935 if (impl->func->args) {
936 for (j = 0; j < impl->func->args->count; ++j) {
937 impl_arg *iarg = impl->func->args->args[j];
938
939 if (!strcmp(let->val->data.func->var->name, iarg->var->name)) {
940 let->val->data.func->arg = iarg;
941 check = 1;
942 break;
943 }
944 }
945 }
946 if (!check) {
947 data->error(data, let->var->token, PSI_WARNING, "Unknown value '$%s' of `let` statement"
948 " for variable '%s' of implementation '%s'",
949 let->val->data.func->var->name, let->var->name, impl->func->name);
950 return 0;
951 }
952 break;
953 }
954 }
955
956 /* check that we have a let stmt for every decl arg */
957 if (impl->decl->args) for (i = 0; i < impl->decl->args->count; ++i) {
958 decl_arg *darg = impl->decl->args->args[i];
959 int check = 0;
960
961 for (j = 0; j < impl->stmts->let.count; ++j) {
962 let_stmt *let = impl->stmts->let.list[j];
963
964 if (!strcmp(let->var->name, darg->var->name)) {
965 darg->let = let;
966 check = 1;
967 break;
968 }
969 }
970 if (!check) {
971 data->error(data, impl->func->token, PSI_WARNING,
972 "Missing `let` statement for arg '%s %.*s%s'"
973 " of declaration '%s' for implementation '%s'",
974 darg->type->name, (int) darg->var->pointer_level, "*****",
975 darg->var->name, impl->decl->func->var->name, impl->func->name);
976 return 0;
977 }
978 }
979
980 return 1;
981 }
982 static inline int validate_impl_set_stmts(PSI_Data *data, impl *impl) {
983 size_t i, j, k;
984 /* we can have any count of set stmts; processing out vars */
985 /* check that set stmts reference known variables */
986 for (i = 0; i < impl->stmts->set.count; ++i) {
987 set_stmt *set = impl->stmts->set.list[i];
988 int check = 0;
989
990 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
991 impl_arg *iarg = impl->func->args->args[j];
992
993 if (!strcmp(set->var->name, iarg->var->name)) {
994 set->arg = iarg;
995 check = 1;
996 break;
997 }
998 }
999 if (!check) {
1000 data->error(data, set->var->token, PSI_WARNING, "Unknown variable '$%s' of `set` statement"
1001 " of implementation '%s'",
1002 set->var->name, impl->func->name);
1003 return 0;
1004 }
1005
1006 for (j = 0; j < set->val->vars->count; ++j) {
1007 decl_var *set_var = set->val->vars->vars[j];
1008
1009 check = 0;
1010 if (impl->decl->args) {
1011 for (k = 0; k < impl->decl->args->count; ++k) {
1012 decl_arg *set_arg = impl->decl->args->args[k];
1013
1014 if (!strcmp(set_var->name, set_arg->var->name)) {
1015 check = 1;
1016 set_var->arg = set_arg;
1017 if (!validate_set_value(data, set->val, 1, &set_arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1018 return 0;
1019 }
1020 break;
1021 }
1022 }
1023 }
1024 if (!check) {
1025 for (k = 0; k < impl->stmts->let.count; ++k) {
1026 let_stmt *let = impl->stmts->let.list[k];
1027
1028 /* check temp vars */
1029 if (let->val && let->val->kind == PSI_LET_TMP) {
1030 if (!strcmp(set_var->name, let->var->name)) {
1031 check = 1;
1032 set_var->arg = let->var->arg;
1033 if (!validate_set_value(data, set->val, 1, &set_var->arg, 1, &impl->decl->func, impl->decl->args->count, impl->decl->args->args, 0)) {
1034 return 0;
1035 }
1036 break;
1037 }
1038 }
1039 }
1040 }
1041
1042 if (!check) {
1043 data->error(data, set_var->token, PSI_WARNING, "Unknown value '%s' of `set` statement"
1044 " for variable '$%s' of implementation '%s'",
1045 set_var->name, set->arg->var->name, impl->func->name);
1046 return 0;
1047 }
1048 }
1049 }
1050 return 1;
1051 }
1052 static inline decl *locate_free_decl(decls *decls, free_call *f) {
1053 if (decls) {
1054 size_t i;
1055
1056 for (i = 0; i < decls->count; ++i) {
1057 if (!strcmp(decls->list[i]->func->var->name, f->func)) {
1058 f->decl = decls->list[i];
1059 return decls->list[i];
1060 }
1061 }
1062 }
1063
1064 return NULL;
1065 }
1066 static inline int validate_impl_free_stmts(PSI_Data *data, impl *impl) {
1067 size_t i, j, k, l;
1068 /* we can have any count of free stmts; freeing any out vars */
1069 for (i = 0; i < impl->stmts->fre.count; ++i) {
1070 free_stmt *fre = impl->stmts->fre.list[i];
1071
1072 for (j = 0; j < fre->calls->count; ++j) {
1073 free_call *free_call = fre->calls->list[j];
1074
1075 /* first find the decl of the free func */
1076 if (!locate_free_decl(data->decls, free_call)) {
1077 data->error(data, free_call->token, PSI_WARNING,
1078 "Missing declaration '%s' in `free` statement"
1079 " of implementation '%s'",
1080 free_call->func, impl->func->name);
1081 return 0;
1082 }
1083
1084
1085
1086 /* now check for known vars */
1087 for (l = 0; l < free_call->vars->count; ++l) {
1088 int check = 0;
1089 decl_var *free_var = free_call->vars->vars[l];
1090
1091 if (!strcmp(free_var->name, impl->decl->func->var->name)) {
1092 check = 1;
1093 free_var->arg = impl->decl->func;
1094 } else if (impl->decl->args) {
1095 for (k = 0; k < impl->decl->args->count; ++k) {
1096 decl_arg *free_arg = impl->decl->args->args[k];
1097
1098 if (!strcmp(free_var->name, free_arg->var->name)) {
1099 check = 1;
1100 free_var->arg = free_arg;
1101 break;
1102 }
1103 }
1104 }
1105
1106 if (!check) {
1107 data->error(data, free_var->token, PSI_WARNING,
1108 "Unknown variable '%s' of `free` statement"
1109 " of implementation '%s'",
1110 free_var->name, impl->func->name);
1111 return 0;
1112 }
1113 }
1114 }
1115 }
1116 return 1;
1117 }
1118 static inline int validate_impl_stmts(PSI_Data *data, impl *impl) {
1119 if (!impl->stmts) {
1120 data->error(data, impl->func->token, PSI_WARNING,
1121 "Missing body for implementation %s!",
1122 impl->func->name);
1123 return 0;
1124 }
1125
1126 if (!validate_impl_ret_stmt(data, impl)) {
1127 return 0;
1128 }
1129
1130 if (!validate_impl_let_stmts(data, impl)) {
1131 return 0;
1132 }
1133 if (!validate_impl_set_stmts(data, impl)) {
1134 return 0;
1135 }
1136 if (!validate_impl_free_stmts(data, impl)) {
1137 return 0;
1138 }
1139
1140 return 1;
1141 }
1142
1143 static inline int validate_impl_args(PSI_Data *data, impl *impl) {
1144 int def = 0;
1145 size_t i;
1146
1147 for (i = 0; i < impl->func->args->count; ++i) {
1148 impl_arg *iarg = impl->func->args->args[i];
1149
1150 if (iarg->def) {
1151 def = 1;
1152 } else if (def) {
1153 data->error(data, impl->func->token, PSI_WARNING,
1154 "Non-optional argument %zu '$%s' of implementation '%s'"
1155 " follows optional argument",
1156 i+1, iarg->var->name, impl->func->name);
1157 return 0;
1158 }
1159 }
1160
1161 return 1;
1162 }
1163
1164 static inline int validate_impl(PSI_Data *data, impl *impl) {
1165 if (!validate_impl_args(data, impl)) {
1166 return 0;
1167 }
1168 return validate_impl_stmts(data, impl);
1169 }
1170
1171
1172 int PSI_ContextValidate(PSI_Context *C, PSI_Parser *P)
1173 {
1174 PSI_Data *D;
1175 void *dlopened = NULL;
1176 size_t i, count = C->count++, check_round, check_count;
1177 decl_typedefs *check_defs = P->defs;
1178 decl_structs *check_structs = P->structs;
1179 decl_unions *check_unions = P->unions;
1180 decl_enums *check_enums = P->enums;
1181 unsigned silent = C->flags & PSI_PARSER_SILENT;
1182
1183 C->data = realloc(C->data, C->count * sizeof(*C->data));
1184 D = PSI_DataExchange(&C->data[count], PSI_DATA(P));
1185
1186 #define REVALIDATE(what) do { \
1187 if (check_round && check_ ##what) { \
1188 free(check_ ##what->list); \
1189 free(check_ ##what); \
1190 } \
1191 check_ ##what = recheck_ ##what; \
1192 } while (0)
1193 #define CHECK_TOTAL (CHECK_COUNT(defs) + CHECK_COUNT(structs) + CHECK_COUNT(enums))
1194 #define CHECK_COUNT(of) (check_ ##of ? check_ ##of->count : 0)
1195
1196 if (!silent) {
1197 /* no warnings on first round */
1198 C->flags |= PSI_PARSER_SILENT;
1199 }
1200 for (check_round = 0, check_count = 0; CHECK_TOTAL && check_count != CHECK_TOTAL; ++check_round) {
1201 decl_typedefs *recheck_defs = NULL;
1202 decl_structs *recheck_structs = NULL;
1203 decl_unions *recheck_unions = NULL;
1204 decl_enums *recheck_enums = NULL;
1205
1206 check_count = CHECK_TOTAL;
1207
1208 for (i = 0; i < CHECK_COUNT(defs); ++i) {
1209 if (validate_decl_typedef(PSI_DATA(C), check_defs->list[i])) {
1210 C->defs = add_decl_typedef(C->defs, check_defs->list[i]);
1211 } else {
1212 recheck_defs = add_decl_typedef(recheck_defs, check_defs->list[i]);
1213 }
1214 }
1215 for (i = 0; i < CHECK_COUNT(structs); ++i) {
1216 if (validate_decl_struct(PSI_DATA(C), check_structs->list[i])) {
1217 C->structs = add_decl_struct(C->structs, check_structs->list[i]);
1218 } else {
1219 recheck_structs = add_decl_struct(recheck_structs, check_structs->list[i]);
1220 }
1221 }
1222 for (i = 0; i < CHECK_COUNT(unions); ++i) {
1223 if (validate_decl_union(PSI_DATA(C), check_unions->list[i])) {
1224 C->unions = add_decl_union(C->unions, check_unions->list[i]);
1225 } else {
1226 recheck_unions = add_decl_union(recheck_unions, check_unions->list[i]);
1227 }
1228 }
1229 for (i = 0; i < CHECK_COUNT(enums); ++i) {
1230 if (validate_decl_enum(PSI_DATA(C), check_enums->list[i])) {
1231 C->enums = add_decl_enum(C->enums, check_enums->list[i]);
1232 } else {
1233 recheck_enums = add_decl_enum(recheck_enums, check_enums->list[i]);
1234 }
1235 }
1236
1237 REVALIDATE(defs);
1238 REVALIDATE(structs);
1239 REVALIDATE(unions);
1240 REVALIDATE(enums);
1241
1242 if (check_round == 0 && !silent) {
1243 C->flags &= ~PSI_PARSER_SILENT;
1244 }
1245 }
1246
1247
1248 if (D->consts) {
1249 for (i = 0; i < D->consts->count; ++i) {
1250 if (validate_constant(PSI_DATA(C), D->consts->list[i])) {
1251 C->consts = add_constant(C->consts, D->consts->list[i]);
1252 }
1253 }
1254 }
1255
1256 if (!validate_lib(D, &dlopened)) {
1257 return 0;
1258 }
1259
1260 add_decl_lib(&C->psi.libs, dlopened);
1261
1262 if (D->decls) {
1263 for (i = 0; i < D->decls->count; ++i) {
1264 if (validate_decl(PSI_DATA(C), dlopened, D->decls->list[i])) {
1265 C->decls = add_decl(C->decls, D->decls->list[i]);
1266 }
1267 }
1268 }
1269 if (D->impls) {
1270 for (i = 0; i < D->impls->count; ++i) {
1271 if (validate_impl(PSI_DATA(C), D->impls->list[i])) {
1272 C->impls = add_impl(C->impls, D->impls->list[i]);
1273 }
1274 }
1275 }
1276
1277 return 1;
1278 }
1279
1280 int PSI_ContextValidateData(PSI_Data *dest, PSI_Data *source)
1281 {
1282 size_t i;
1283 int errors = 0;
1284
1285 if (source->defs) for (i = 0; i < source->defs->count; ++i) {
1286 decl_arg *def = source->defs->list[i];
1287
1288 if (validate_decl_typedef(source, def)) {
1289 if (dest) {
1290 dest->defs = add_decl_typedef(dest->defs, def);
1291 }
1292 } else {
1293 ++errors;
1294 }
1295 }
1296
1297 if (source->consts) for (i = 0; i < source->consts->count; ++i) {
1298 constant *constant = source->consts->list[i];
1299
1300 if (validate_constant(source, constant)) {
1301 if (dest) {
1302 dest->consts = add_constant(dest->consts, constant);
1303 }
1304 } else {
1305 ++errors;
1306 }
1307 }
1308
1309 if (source->structs) for (i = 0; i < source->structs->count; ++i) {
1310 decl_struct *dstruct = source->structs->list[i];
1311
1312 if (validate_decl_struct(source, dstruct)) {
1313 if (dest) {
1314 dest->structs = add_decl_struct(dest->structs, dstruct);
1315 }
1316 } else {
1317 ++errors;
1318 }
1319 }
1320
1321 if (source->unions) for (i = 0; i < source->unions->count; ++i) {
1322 decl_union *dunion = source->unions->list[i];
1323
1324 if (validate_decl_union(source, dunion)) {
1325 if (dest) {
1326 dest->unions = add_decl_union(dest->unions, dunion);
1327 }
1328 } else {
1329 ++errors;
1330 }
1331 }
1332
1333 if (source->enums) for (i = 0; i < source->enums->count; ++i) {
1334 decl_enum *denum = source->enums->list[i];
1335
1336 if (validate_decl_enum(source, denum)) {
1337 if (dest) {
1338 dest->enums = add_decl_enum(dest->enums, denum);
1339 }
1340 } else {
1341 ++errors;
1342 }
1343 }
1344
1345 if (source->decls) for (i = 0; i < source->decls->count; ++i) {
1346 decl *decl = source->decls->list[i];
1347
1348 if (validate_decl(source, NULL, decl)) {
1349 if (dest) {
1350 dest->decls = add_decl(dest->decls, decl);
1351 }
1352 } else {
1353 ++errors;
1354 }
1355 }
1356
1357 if (source->impls) for (i = 0; i < source->impls->count; ++i) {
1358 impl *impl = source->impls->list[i];
1359
1360 if (validate_impl(source, impl)) {
1361 if (dest) {
1362 dest->impls = add_impl(dest->impls, impl);
1363 }
1364 } else {
1365 ++errors;
1366 }
1367 }
1368
1369 return errors;
1370 }