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