flush
[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_arg *arg, decl_type *type) {
96 switch (type->type) {
97 case PSI_T_NAME:
98 if (!V->defs || !locate_decl_type_alias(V->defs, type)) {
99 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
100 " Use 'typedef <type> <alias>;' statement",
101 type->name, arg->var->name);
102 return 0;
103 }
104 return validate_decl_type(V, arg, type->real);
105 case PSI_T_STRUCT:
106 if (!V->structs || !locate_decl_type_struct(V->structs, type)) {
107 V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';"
108 " Use 'typedef struct <name> <alias>;' statement",
109 type->name, arg->var->name);
110 return 0;
111 }
112 break;
113 }
114 return 1;
115 }
116 static inline int validate_typedef(PSI_Validator *V, decl_typedef *def) {
117 /* FIXME: check def->alias */
118 if (def->type->type == PSI_T_NAME) {
119 V->error(PSI_WARNING, "Type '%s' cannot be aliased to '%s'",
120 def->type->name, def->alias);
121 return 0;
122 }
123 return 1;
124 }
125 static inline int validate_typedefs(PSI_Validator *V) {
126 size_t i;
127
128 for (i = 0; i < V->defs->count; ++i) {
129 if (!validate_typedef(V, V->defs->list[i])) {
130 return 0;
131 }
132 }
133
134 return 1;
135 }
136 static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func)
137 {
138 if (!strcmp(func->var->name, "dlsym")) {
139 V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)");
140 return 0;
141 }
142
143 if (!validate_decl_type(V, func, func->type)) {
144 return 0;
145 }
146 #ifndef RTLD_NEXT
147 # define RTLD_NEXT ((void *) -1l)
148 #endif
149 decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name);
150 if (!decl->dlptr) {
151 V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
152 func->var->name, dlerror());
153 }
154 return 1;
155 }
156 static const char * const abi_ccs[] = {
157 "default", /* \ */
158 "extern", /* > - all the same */
159 "cdecl", /* / */
160 "stdcall",
161 "fastcall",
162 };
163 static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) {
164 size_t i;
165
166 for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) {
167 if (strcasecmp(abi->convention, abi_ccs[i])) {
168 return 1;
169 }
170 }
171 V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention);
172 return 0;
173 }
174 static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) {
175 if (!validate_decl_type(V, arg, arg->type)) {
176 return 0;
177 }
178 return 1;
179 }
180 static inline int validate_decl_args(PSI_Validator *V, decl_args *args) {
181 size_t i;
182
183 for (i = 0; i < args->count; ++i) {
184 if (!validate_decl_arg(V, args->args[i])) {
185 return 0;
186 }
187 }
188 return 1;
189 }
190 static inline int validate_decl(PSI_Validator *V, decl *decl) {
191 if (!validate_decl_abi(V, decl->abi)) {
192 return 0;
193 }
194 if (!validate_decl_func(V, decl, decl->func)) {
195 return 0;
196 }
197 if (decl->args && !validate_decl_args(V, decl->args)) {
198 return 0;
199 }
200 return 1;
201 }
202 static inline int validate_decls(PSI_Validator *V) {
203 size_t i;
204
205 for (i = 0; i < V->decls->count; ++i) {
206 if (!validate_decl(V, V->decls->list[i])) {
207 return 0;
208 }
209 }
210 return 1;
211 }
212 static inline int validate_struct(PSI_Validator *V, decl_struct *s) {
213 size_t i;
214
215 if (!validate_decl_args(V, s->args)) {
216 return 0;
217 }
218
219 s->layout = calloc(s->args->count, sizeof(*s->layout));
220 for (i = 0; i < s->args->count; ++i) {
221 decl_arg *darg = s->args->args[i];
222 decl_type *type = real_decl_type(darg->type);
223 token_t t = darg->var->pointer_level ? PSI_T_POINTER : type->type;
224
225 if (i) {
226 decl_struct_layout *l = &s->layout[i-1];
227 s->layout[i].pos = psi_t_align(t, l->pos + l->len);
228 } else {
229 s->layout[i].pos = 0;
230 }
231 s->layout[i].len = psi_t_size(t);
232 }
233 return 1;
234 }
235 static inline int validate_structs(PSI_Validator *V) {
236 size_t i;
237
238 for (i = 0; i < V->structs->count; ++i) {
239 if (!validate_struct(V, V->structs->list[i])) {
240 return 0;
241 }
242 }
243 return 1;
244 }
245
246 static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) {
247 /* FIXME */
248 return 1;
249 }
250 static inline int validate_impl_arg(PSI_Validator *V, impl *impl, impl_arg *arg) {
251 return 1;
252 }
253 static inline int validate_impl_args(PSI_Validator *V, impl *impl, impl_args *args) {
254 size_t i;
255
256 for (i = 0; i < args->count; ++i) {
257 if (!validate_impl_arg(V, impl, args->args[i])) {
258 return 0;
259 }
260 }
261 return 1;
262 }
263 static inline int validate_impl_func(PSI_Validator *V, impl *impl, impl_func *func) {
264 /* FIXME: does name need any validation? */
265 if (!validate_impl_type(V, impl, func->return_type)) {
266 return 0;
267 }
268 if (func->args && !validate_impl_args(V, impl, func->args)) {
269 return 0;
270 }
271 return 1;
272 }
273 static inline decl *locate_impl_decl(decls *decls, return_stmt *ret) {
274 size_t i;
275
276 for (i = 0; i < decls->count; ++i) {
277 if (!strcmp(decls->list[i]->func->var->name, ret->decl->name)) {
278 return decls->list[i];
279 }
280 }
281 return NULL;
282 }
283
284 static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *stmts) {
285 /* okay,
286 * - we must have exactly one ret stmt delcaring the native func to call and which type cast to apply
287 * - we can have multiple let stmts; every arg of the ret stmts var (the function to call) must have one
288 * - we can have any count of set stmts; processing out vars
289 * - we can have any count of free stmts; freeing any out vars
290 */
291 size_t i, j, k;
292 return_stmt *ret;
293 decl *decl;
294
295 if (!stmts) {
296 V->error(PSI_WARNING, "Missing body for implementation %s!",
297 impl->func->name);
298 return 0;
299 }
300 if (stmts->ret.count != 1) {
301 if (stmts->ret.count > 1) {
302 V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
303 " found %zu, exactly one is needed",
304 impl->func->name, stmts->ret.count);
305 } else {
306 V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
307 impl->func->name);
308 }
309 return 0;
310 }
311
312 ret = stmts->ret.list[0];
313 decl = locate_impl_decl(V->decls, ret);
314 if (!decl) {
315 V->error(PSI_WARNING, "Missing declaration for implementation %s",
316 impl->func->name);
317 return 0;
318 }
319
320 /* check that we have a let stmt for every decl arg */
321 if (decl->args) for (i = 0; i < decl->args->count; ++i) {
322 decl_arg *darg = decl->args->args[i];
323 int check = 0;
324
325 for (j = 0; j < stmts->let.count; ++j) {
326 let_stmt *let = stmts->let.list[j];
327
328 if (!strcmp(let->var->name, darg->var->name)) {
329 darg->let = let;
330 check = 1;
331 break;
332 }
333 }
334 if (!check) {
335 V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
336 " of declaration '%s' for implementation '%s'",
337 darg->type->name, (int) darg->var->pointer_level, "*****",
338 darg->var->name, decl->func->var->name, impl->func->name);
339 return 0;
340 }
341 }
342 /* check that the let_value references a known variable or NULL */
343 for (i = 0; i < stmts->let.count; ++i) {
344 let_stmt *let = stmts->let.list[i];
345 int check = 0;
346
347 if (let->val && let->val->var) {
348 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
349 impl_arg *iarg = impl->func->args->args[j];
350
351 if (!strcmp(let->val->var->name, iarg->var->name)) {
352 let->arg = iarg;
353 check = 1;
354 break;
355 }
356 }
357 if (!check) {
358 V->error(PSI_WARNING, "Unknown value '$%s' of `let` statement"
359 " for variable '%s' of implementation '%s'",
360 let->val->var->name, let->var->name, impl->func->name);
361 return 0;
362 }
363 }
364 }
365 /* check that set stmts reference known variables */
366 for (i = 0; i < stmts->set.count; ++i) {
367 set_stmt *set = stmts->set.list[i];
368 int check = 0;
369
370 if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
371 impl_arg *iarg = impl->func->args->args[j];
372
373 if (!strcmp(set->var->name, iarg->var->name)) {
374 set->arg = iarg;
375 check = 1;
376 break;
377 }
378 }
379 if (!check) {
380 V->error(PSI_WARNING, "Unknown variable '$%s' of `set` statement"
381 " of implementation '%s'",
382 set->var->name, impl->func->name);
383 return 0;
384 }
385
386 for (j = 0; j < set->val->vars->count; ++j) {
387 decl_var *set_var = set->val->vars->vars[j];
388
389 check = 0;
390 if (decl->args) for (k = 0; k < decl->args->count; ++k) {
391 decl_arg *set_arg = decl->args->args[k];
392
393 if (!strcmp(set_var->name, set_arg->var->name)) {
394 check = 1;
395 set_var->arg = set_arg;
396 break;
397 }
398 }
399
400 if (!check) {
401 V->error(PSI_WARNING, "Unknown value '%s' of `set` statement"
402 " for variable '$%s' of implementation '%s'",
403 set_var->name, set->arg->var->name, impl->func->name);
404 return 0;
405 }
406 }
407 }
408 /* check free stmts */
409 for (i = 0; i < stmts->fre.count; ++i) {
410 free_stmt *fre = stmts->fre.list[i];
411
412 for (j = 0; j < fre->vars->count; ++j) {
413 decl_var *free_var = fre->vars->vars[j];
414 int check = 0;
415
416 if (!strcmp(free_var->name, decl->func->var->name)) {
417 continue;
418 }
419 if (decl->args) for (k = 0; k < decl->args->count; ++k) {
420 decl_arg *free_arg = decl->args->args[k];
421
422 if (!strcmp(free_var->name, free_arg->var->name)) {
423 check = 1;
424 free_var->arg = free_arg;
425 break;
426 }
427 }
428
429 if (!check) {
430 V->error(PSI_WARNING, "Unknown variable '%s' of `free` statement"
431 " of implementation '%s'",
432 free_var->name, impl->func->name);
433 return 0;
434 }
435 }
436 }
437
438 impl->decl = decl;
439
440 return 1;
441 }
442
443 static inline int validate_impl(PSI_Validator *V, impl *impl) {
444 if (!validate_impl_func(V, impl, impl->func)) {
445 return 0;
446 }
447 if (!validate_impl_stmts(V, impl, impl->stmts)) {
448 return 0;
449 }
450 return 1;
451 }
452 static inline int validate_impls(PSI_Validator *V) {
453 size_t i;
454
455 for (i = 0; i < V->impls->count; ++i) {
456 if (!validate_impl(V, V->impls->list[i])) {
457 return 0;
458 }
459 }
460 return 1;
461 }
462
463 int PSI_ValidatorValidate(PSI_Validator *V)
464 {
465 if (!validate_lib(V)) {
466 return 0;
467 }
468 if (V->defs && !validate_typedefs(V)) {
469 return 0;
470 }
471 if (V->structs && !validate_structs(V)) {
472 return 0;
473 }
474 if (V->decls && !validate_decls(V)) {
475 return 0;
476 }
477 if (!V->impls || !validate_impls(V)) {
478 return 0;
479 }
480 return 1;
481 }