7bc2f701989c698c63a0e491f4031ab38b30dd19
[m6w6/ext-psi] / src / validator.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/param.h>
5 #include <dlfcn.h>
6
7 #include <jit/jit.h>
8
9 #include "php.h"
10 #include "php_psi.h"
11 #include "validator.h"
12
13 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
14 {
15 if (!V) {
16 V = malloc(sizeof(*V));
17 }
18 memset(V, 0, sizeof(*V));
19
20 PSI_DataExchange((PSI_Data *) V, (PSI_Data *) P);
21
22 return V;
23 }
24
25 void PSI_ValidatorDtor(PSI_Validator *V)
26 {
27 PSI_DataDtor((PSI_Data *) V);
28 memset(V, 0, sizeof(*V));
29 }
30
31 void PSI_ValidatorFree(PSI_Validator **V)
32 {
33 if (*V) {
34 PSI_ValidatorDtor(*V);
35 free(*V);
36 *V = NULL;
37 }
38 }
39
40 static int validate_lib(PSI_Validator *V) {
41 char lib[MAXPATHLEN];
42 const char *ptr = V->lib;
43 size_t len;
44
45 if (!ptr) {
46 /* FIXME: assume stdlib */
47 return 1;
48 } else if (!strchr(ptr, '/')) {
49 #ifdef DARWIN
50 len = snprintf(lib, MAXPATHLEN, "lib%s.dylib", ptr);
51 #else
52 len = snprintf(lib, MAXPATHLEN, "lib%s.so", ptr);
53 #endif
54 if (MAXPATHLEN == len) {
55 V->error(PSI_WARNING, "Library name too long: '%s'", ptr);
56 }
57 lib[len] = 0;
58 ptr = lib;
59 }
60 if (!(V->dlopened = dlopen(ptr, RTLD_LAZY|RTLD_LOCAL))) {
61 V->error(PSI_WARNING, "Could not open library '%s': %s.", V->lib, dlerror());
62 return 0;
63 }
64 return 1;
65 }
66
67 static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) {
68 size_t i;
69
70 if (type->real) {
71 return 1;
72 }
73 for (i = 0; i < defs->count; ++i) {
74 if (!strcmp(defs->list[i]->alias, type->name)) {
75 type->real = defs->list[i]->type;
76 return 1;
77 }
78 }
79 return 0;
80 }
81 static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) {
82 size_t i;
83
84 if (type->strct) {
85 return 1;
86 }
87 for (i = 0; i < structs->count; ++i) {
88 if (!strcmp(structs->list[i]->name, type->name)) {
89 type->strct = structs->list[i];
90 return 1;
91 }
92 }
93 return 0;
94 }
95 static inline int validate_decl_type(PSI_Validator *V, decl_type *type) {
96 switch (type->type) {
97 case PSI_T_NAME:
98 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
99 return 0;
100 }
101 return validate_decl_type(V, type->real);
102 case PSI_T_STRUCT:
103 if (!V->structs || !locate_decl_type_struct(V->structs, type)) {
104 return 0;
105 }
106 break;
107 }
108 return 1;
109 }
110 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
111 /* FIXME: check def->alias */
112 if (def->type->type == PSI_T_NAME) {
113 V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
114 def->type->name, def->alias);
115 return 0;
116 }
117 return 1;
118 }
119 static inline int validate_typedefs(PSI_Validator *V) {
120 size_t i;
121
122 for (i = 0; i < V->defs->count; ++i) {
123 if (!validate_typedef(V, V->defs->list[i])) {
124 return 0;
125 }
126 }
127
128 return 1;
129 }
130 static const char * const abi_ccs[] = {
131 "default", /* \ */
132 "extern", /* > - all the same */
133 "cdecl", /* / */
134 "stdcall",
135 "fastcall",
136 };
137 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
138 size_t i;
139
140 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) {
141 if (strcasecmp(abi->convention, abi_ccs[i])) {
142 return 1;
143 }
144 }
145 V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
146 return 0;
147 }
148 static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) {
149 if (!validate_decl_type(V, arg->type)) {
150 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s'",
151 arg->type->name, arg->var->name);
152 return 0;
153 }
154 return 1;
155 }
156 static inline int validate_decl_args(PSI_Validator *V, decl_args *args) {
157 size_t i;
158
159 for (i = 0; i < args->count; ++i) {
160 if (!validate_decl_arg(V, args->args[i])) {
161 return 0;
162 }
163 }
164 return 1;
165 }
166 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
167 {
168 if (!strcmp(func->var->name, "dlsym")) {
169 V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
170 return 0;
171 }
172
173 if (!validate_decl_arg(V, func)) {
174 return 0;
175 }
176 #ifndef RTLD_NEXT
177 # define RTLD_NEXT ((void *) -1l)
178 #endif
179 decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name);
180 if (!decl->dlptr) {
181 V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
182 func->var->name, dlerror());
183 }
184 return 1;
185 }
186 static inline int validate_decl(PSI_Validator *V, decl *decl) {
187 if (!validate_decl_abi(V, decl->abi)) {
188 return 0;
189 }
190 if (!validate_decl_func(V, decl, decl->func)) {
191 return 0;
192 }
193 if (decl->args && !validate_decl_args(V, decl->args)) {
194 return 0;
195 }
196 return 1;
197 }
198 static inline int validate_decls(PSI_Validator *V) {
199 size_t i;
200
201 for (i = 0; i < V->decls->count; ++i) {
202 if (!validate_decl(V, V->decls->list[i])) {
203 return 0;
204 }
205 }
206 return 1;
207 }
208 static inline int validate_struct(PSI_Validator *V, decl_struct *s) {
209 size_t i;
210
211 if (!validate_decl_args(V, s->args)) {
212 return 0;
213 }
214
215 s->layout = calloc(s->args->count, sizeof(*s->layout));
216 for (i = 0; i < s->args->count; ++i) {
217 decl_arg *darg = s->args->args[i];
218 decl_type *type = real_decl_type(darg->type);
219 token_t t = darg->var->pointer_level ? PSI_T_POINTER : type->type;
220
221 if (i) {
222 decl_struct_layout *l = &s->layout[i-1];
223 s->layout[i].pos = psi_t_align(t, l->pos + l->len);
224 } else {
225 s->layout[i].pos = 0;
226 }
227 s->layout[i].len = psi_t_size(t);
228 }
229 return 1;
230 }
231 static inline int validate_structs(PSI_Validator *V) {
232 size_t i;
233
234 for (i = 0; i < V->structs->count; ++i) {
235 if (!validate_struct(V, V->structs->list[i])) {
236 return 0;
237 }
238 }
239 return 1;
240 }
241
242 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
243 /* FIXME */
244 return 1;
245 }
246 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
247 return 1;
248 }
249 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
250 size_t i;
251
252 for (i = 0; i < args->count; ++i) {
253 if (!validate_impl_arg(V, impl, args->args[i])) {
254 return 0;
255 }
256 }
257 return 1;
258 }
259 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
260 /* FIXME: does name need any validation? */
261 if (!validate_impl_type(V, impl, func->return_type)) {
262 return 0;
263 }
264 if (func->args && !validate_impl_args(V, impl, func->args)) {
265 return 0;
266 }
267 return 1;
268 }
269 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
270 size_t i;
271
272 for (i = 0; i < decls->count; ++i) {
273 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
274 return decls->list[i];
275 }
276 }
277 return NULL;
278 }
279
280 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
281 /* okay,
282 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
283 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
284 * - we can have any count of set stmts; processing out vars
285 * - we can have any count of free stmts; freeing any out vars
286 */
287 size_t i, j, k;
288 return_stmt *ret;
289 decl *decl;
290
291 if (!stmts) {
292 V->error(PSI_WARNING, "Missing body for implementation %s!",
293 impl->func->name);
294 return 0;
295 }
296 if (stmts->ret.count != 1) {
297 if (stmts->ret.count > 1) {
298 V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
299 " found %zu, exactly one is needed",
300 impl->func->name, stmts->ret.count);
301 } else {
302 V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
303 impl->func->name);
304 }
305 return 0;
306 }
307
308 ret = stmts->ret.list[0];
309 decl = locate_impl_decl(V->decls, ret);
310 if (!decl) {
311 V->error(PSI_WARNING, "Missing declaration for implementation %s",
312 impl->func->name);
313 return 0;
314 }
315
316 /* check that we have a let stmt for every decl arg */
317 if (decl->args) for (i = 0; i < decl->args->count; ++i) {
318 decl_arg *darg = decl->args->args[i];
319 int check = 0;
320
321 for (j = 0; j < stmts->let.count; ++j) {
322 let_stmt *let = stmts->let.list[j];
323
324 if (!strcmp(let->var->name, darg->var->name)) {
325 darg->let = let;
326 check = 1;
327 break;
328 }
329 }
330 if (!check) {
331 V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
332 " of declaration '%s' for implementation '%s'",
333 darg->type->name, (int) darg->var->pointer_level, "*****",
334 darg->var->name, decl->func->var->name, impl->func->name);
335 return 0;
336 }
337 }
338 /* check that the let_value references a known variable or NULL */
339 for (i = 0; i < stmts->let.count; ++i) {
340 let_stmt *let = stmts->let.list[i];
341 int check = 0;
342
343 if (let->val && let->val->func && let->val->func->alloc) {
344 if (!validate_decl_type(V, let->val->func->alloc->type)) {
345 V->error(PSI_WARNING, "Cannot use '%s' as type for calloc in `let` statement",
346 let->val->func->alloc->type->name);
347 return 0;
348 }
349 }
350 if (let->val && let->val->var) {
351 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
352 impl_arg *iarg = impl->func->args->args[j];
353
354 if (!strcmp(let->val->var->name, iarg->var->name)) {
355 let->arg = iarg;
356 check = 1;
357 break;
358 }
359 }
360 if (!check) {
361 V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
362 " for variable '%s' of implementation '%s'",
363 let->val->var->name, let->var->name, impl->func->name);
364 return 0;
365 }
366 }
367 }
368 /* check that set stmts reference known variables */
369 for (i = 0; i < stmts->set.count; ++i) {
370 set_stmt *set = stmts->set.list[i];
371 int check = 0;
372
373 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
374 impl_arg *iarg = impl->func->args->args[j];
375
376 if (!strcmp(set->var->name, iarg->var->name)) {
377 set->arg = iarg;
378 check = 1;
379 break;
380 }
381 }
382 if (!check) {
383 V->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement"
384 " of implementation '%s'",
385 set->var->name, impl->func->name);
386 return 0;
387 }
388
389 for (j = 0; j < set->val->vars->count; ++j) {
390 decl_var *set_var = set->val->vars->vars[j];
391
392 check = 0;
393 if (decl->args) for (k = 0; k < decl->args->count; ++k) {
394 decl_arg *set_arg = decl->args->args[k];
395
396 if (!strcmp(set_var->name, set_arg->var->name)) {
397 check = 1;
398 set_var->arg = set_arg;
399 break;
400 }
401 }
402
403 if (!check) {
404 V->error(PSI_WARNING, "Unknown value '%s' of `set` statement"
405 " for variable '$%s' of implementation '%s'",
406 set_var->name, set->arg->var->name, impl->func->name);
407 return 0;
408 }
409 }
410 }
411 /* check free stmts */
412 for (i = 0; i < stmts->fre.count; ++i) {
413 free_stmt *fre = stmts->fre.list[i];
414
415 for (j = 0; j < fre->vars->count; ++j) {
416 decl_var *free_var = fre->vars->vars[j];
417 int check = 0;
418
419 if (!strcmp(free_var->name, decl->func->var->name)) {
420 continue;
421 }
422 if (decl->args) for (k = 0; k < decl->args->count; ++k) {
423 decl_arg *free_arg = decl->args->args[k];
424
425 if (!strcmp(free_var->name, free_arg->var->name)) {
426 check = 1;
427 free_var->arg = free_arg;
428 break;
429 }
430 }
431
432 if (!check) {
433 V->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
434 " of implementation '%s'",
435 free_var->name, impl->func->name);
436 return 0;
437 }
438 }
439 }
440
441 impl->decl = decl;
442
443 return 1;
444 }
445
446 static inline int validate_impl(PSI_Validator *V, impl *impl) {
447 if (!validate_impl_func(V, impl, impl->func)) {
448 return 0;
449 }
450 if (!validate_impl_stmts(V, impl, impl->stmts)) {
451 return 0;
452 }
453 return 1;
454 }
455 static inline int validate_impls(PSI_Validator *V) {
456 size_t i;
457
458 for (i = 0; i < V->impls->count; ++i) {
459 if (!validate_impl(V, V->impls->list[i])) {
460 return 0;
461 }
462 }
463 return 1;
464 }
465
466 int PSI_ValidatorValidate(PSI_Validator *V)
467 {
468 if (!validate_lib(V)) {
469 return 0;
470 }
471 if (V->defs && !validate_typedefs(V)) {
472 return 0;
473 }
474 if (V->structs && !validate_structs(V)) {
475 return 0;
476 }
477 if (V->decls && !validate_decls(V)) {
478 return 0;
479 }
480 if (!V->impls || !validate_impls(V)) {
481 return 0;
482 }
483 return 1;
484 }