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