X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-psi;a=blobdiff_plain;f=src%2Fvalidator.c;h=7bc2f701989c698c63a0e491f4031ab38b30dd19;hp=44ea4ab11c2108385636c3707431dd6fa7e6aaef;hb=d60f4bbdd315ddf42dbafeff0fd3d87d2e7a51f7;hpb=277d56eeb14cb124042362cb9d5f6e387487748c diff --git a/src/validator.c b/src/validator.c index 44ea4ab..7bc2f70 100644 --- a/src/validator.c +++ b/src/validator.c @@ -6,6 +6,8 @@ #include +#include "php.h" +#include "php_psi.h" #include "validator.h" PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P) @@ -61,6 +63,7 @@ static int validate_lib(PSI_Validator *V) { } return 1; } + static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { size_t i; @@ -75,14 +78,32 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { } return 0; } -static inline int validate_decl_type(PSI_Validator *V, decl_arg *arg, decl_type *type) { - if (type->type == PSI_T_NAME) { +static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) { + size_t i; + + if (type->strct) { + return 1; + } + for (i = 0; i < structs->count; ++i) { + if (!strcmp(structs->list[i]->name, type->name)) { + type->strct = structs->list[i]; + return 1; + } + } + return 0; +} +static inline int validate_decl_type(PSI_Validator *V, decl_type *type) { + switch (type->type) { + case PSI_T_NAME: if (!V->defs || !locate_decl_type_alias(V->defs, type)) { - V->error(PSI_WARNING, "Cannot use '%s' as type for '%s';" - " Use 'typedef ;' statement", - type->name, arg->var->name); return 0; } + return validate_decl_type(V, type->real); + case PSI_T_STRUCT: + if (!V->structs || !locate_decl_type_struct(V->structs, type)) { + return 0; + } + break; } return 1; } @@ -106,24 +127,6 @@ static inline int validate_typedefs(PSI_Validator *V) { return 1; } -static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) -{ - if (!strcmp(func->var->name, "dlsym")) { - V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); - return 0; - } - - if (!validate_decl_type(V, func, func->type)) { - return 0; - } - - decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name); - if (!decl->dlptr) { - V->error(PSI_WARNING, "Failed to located symbol '%s': %s", - func->var->name, dlerror()); - } - return 1; -} static const char * const abi_ccs[] = { "default", /* \ */ "extern", /* > - all the same */ @@ -134,7 +137,7 @@ static const char * const abi_ccs[] = { static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { size_t i; - for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++ i) { + for (i = 0; i < sizeof(abi_ccs)/sizeof(char*); ++i) { if (strcasecmp(abi->convention, abi_ccs[i])) { return 1; } @@ -142,22 +145,44 @@ static inline int validate_decl_abi(PSI_Validator *V, decl_abi *abi) { V->error(PSI_WARNING, "Invalid calling convention: '%s'", abi->convention); return 0; } -static inline int validate_decl_arg(PSI_Validator *V, decl *decl, decl_arg *arg) { - if (!validate_decl_type(V, arg, arg->type)) { +static inline int validate_decl_arg(PSI_Validator *V, decl_arg *arg) { + if (!validate_decl_type(V, arg->type)) { + V->error(PSI_WARNING, "Cannot use '%s' as type for '%s'", + arg->type->name, arg->var->name); return 0; } return 1; } -static inline int validate_decl_args(PSI_Validator *V, decl *decl, decl_args *args) { +static inline int validate_decl_args(PSI_Validator *V, decl_args *args) { size_t i; for (i = 0; i < args->count; ++i) { - if (!validate_decl_arg(V, decl, args->args[i])) { + if (!validate_decl_arg(V, args->args[i])) { return 0; } } return 1; } +static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *func) +{ + if (!strcmp(func->var->name, "dlsym")) { + V->error(PSI_WARNING, "Cannot dlsym dlsym (sic!)"); + return 0; + } + + if (!validate_decl_arg(V, func)) { + return 0; + } +#ifndef RTLD_NEXT +# define RTLD_NEXT ((void *) -1l) +#endif + decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name); + if (!decl->dlptr) { + V->error(PSI_WARNING, "Failed to located symbol '%s': %s", + func->var->name, dlerror()); + } + return 1; +} static inline int validate_decl(PSI_Validator *V, decl *decl) { if (!validate_decl_abi(V, decl->abi)) { return 0; @@ -165,7 +190,7 @@ static inline int validate_decl(PSI_Validator *V, decl *decl) { if (!validate_decl_func(V, decl, decl->func)) { return 0; } - if (decl->args && !validate_decl_args(V, decl, decl->args)) { + if (decl->args && !validate_decl_args(V, decl->args)) { return 0; } return 1; @@ -180,6 +205,39 @@ static inline int validate_decls(PSI_Validator *V) { } return 1; } +static inline int validate_struct(PSI_Validator *V, decl_struct *s) { + size_t i; + + if (!validate_decl_args(V, s->args)) { + return 0; + } + + s->layout = calloc(s->args->count, sizeof(*s->layout)); + for (i = 0; i < s->args->count; ++i) { + decl_arg *darg = s->args->args[i]; + decl_type *type = real_decl_type(darg->type); + token_t t = darg->var->pointer_level ? PSI_T_POINTER : type->type; + + if (i) { + decl_struct_layout *l = &s->layout[i-1]; + s->layout[i].pos = psi_t_align(t, l->pos + l->len); + } else { + s->layout[i].pos = 0; + } + s->layout[i].len = psi_t_size(t); + } + return 1; +} +static inline int validate_structs(PSI_Validator *V) { + size_t i; + + for (i = 0; i < V->structs->count; ++i) { + if (!validate_struct(V, V->structs->list[i])) { + return 0; + } + } + return 1; +} static inline int validate_impl_type(PSI_Validator *V, impl *impl, impl_type *type) { /* FIXME */ @@ -238,7 +296,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * if (stmts->ret.count != 1) { if (stmts->ret.count > 1) { V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;" - "found %zu, exactly one is needed", + " found %zu, exactly one is needed", impl->func->name, stmts->ret.count); } else { V->error(PSI_WARNING, "Missing `ret` statement for implementation %s", @@ -256,7 +314,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * } /* check that we have a let stmt for every decl arg */ - for (i = 0; i < decl->args->count; ++i) { + if (decl->args) for (i = 0; i < decl->args->count; ++i) { decl_arg *darg = decl->args->args[i]; int check = 0; @@ -271,7 +329,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * } if (!check) { V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'" - "of declaration '%s' for implementation '%s'", + " of declaration '%s' for implementation '%s'", darg->type->name, (int) darg->var->pointer_level, "*****", darg->var->name, decl->func->var->name, impl->func->name); return 0; @@ -282,8 +340,15 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * let_stmt *let = stmts->let.list[i]; int check = 0; + if (let->val && let->val->func && let->val->func->alloc) { + if (!validate_decl_type(V, let->val->func->alloc->type)) { + V->error(PSI_WARNING, "Cannot use '%s' as type for calloc in `let` statement", + let->val->func->alloc->type->name); + return 0; + } + } if (let->val && let->val->var) { - for (j = 0; j < impl->func->args->count; ++j) { + if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { impl_arg *iarg = impl->func->args->args[j]; if (!strcmp(let->val->var->name, iarg->var->name)) { @@ -305,7 +370,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * set_stmt *set = stmts->set.list[i]; int check = 0; - for (j = 0; j < impl->func->args->count; ++j) { + if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) { impl_arg *iarg = impl->func->args->args[j]; if (!strcmp(set->var->name, iarg->var->name)) { @@ -325,7 +390,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * decl_var *set_var = set->val->vars->vars[j]; check = 0; - for (k = 0; k < decl->args->count; ++k) { + if (decl->args) for (k = 0; k < decl->args->count; ++k) { decl_arg *set_arg = decl->args->args[k]; if (!strcmp(set_var->name, set_arg->var->name)) { @@ -354,7 +419,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts * if (!strcmp(free_var->name, decl->func->var->name)) { continue; } - for (k = 0; k < decl->args->count; ++k) { + if (decl->args) for (k = 0; k < decl->args->count; ++k) { decl_arg *free_arg = decl->args->args[k]; if (!strcmp(free_var->name, free_arg->var->name)) { @@ -406,6 +471,9 @@ int PSI_ValidatorValidate(PSI_Validator *V) if (V->defs && !validate_typedefs(V)) { return 0; } + if (V->structs && !validate_structs(V)) { + return 0; + } if (V->decls && !validate_decls(V)) { return 0; }