From 179b79a987ed0f464f47f724032aff6c90bc50c0 Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 8 Mar 2014 02:52:39 +0200 Subject: [PATCH] some func ptr arg type checking --- tools/cvt_data.c | 17 ++++++++++++++++- tools/protoparse.h | 14 ++++++++++---- tools/translate.c | 16 +++++++++++++++- winelib.mak | 2 +- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/tools/cvt_data.c b/tools/cvt_data.c index 2c5bbbf..237abef 100644 --- a/tools/cvt_data.c +++ b/tools/cvt_data.c @@ -247,7 +247,8 @@ static const struct parsed_proto *check_var(FILE *fhdr, const char *sym, const char *varname) { const struct parsed_proto *pp, *pp_sym; - char fp_sym[256], fp_var[256]; + char fp_sym[256], fp_var[256], *p; + int i; pp = proto_parse(fhdr, varname, 1); if (pp == NULL) { @@ -277,6 +278,20 @@ static const struct parsed_proto *check_var(FILE *fhdr, } check_sym: + // fptrs must use 32bit args, callsite might have no information and + // lack a cast to smaller types, which results in incorrectly masked + // args passed (callee may assume masked args, it does on ARM) + for (i = 0; i < pp->argc; i++) { + if (pp->arg[i].type.is_ptr) + continue; + p = pp->arg[i].type.name; + if (strstr(p, "int8") || strstr(p, "int16") + || strstr(p, "char") || strstr(p, "short")) + { + awarn("reference to %s with arg%d '%s'\n", pp->name, i + 1, p); + } + } + sprint_pp_short(pp, g_comment, sizeof(g_comment)); if (sym != NULL) { diff --git a/tools/protoparse.h b/tools/protoparse.h index 0ae46f6..27752cf 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -41,7 +41,8 @@ struct parsed_proto { unsigned int is_noreturn:1; unsigned int is_unresolved:1; unsigned int is_userstack:1; - unsigned int is_arg:1; // decl in func arg + unsigned int is_oslib:1; // OS/system library func + unsigned int is_arg:1; // declared in some func arg unsigned int has_structarg:1; unsigned int has_retreg:1; }; @@ -52,7 +53,7 @@ static int hdrfline = 0; static void pp_copy_arg(struct parsed_proto_arg *d, const struct parsed_proto_arg *s); -static int b_pp_c_handler(char *proto, const char *fname); +static int b_pp_c_handler(char *proto, const char *fname, int is_oslib); static int do_protostrs(FILE *fhdr, const char *fname) { @@ -61,6 +62,7 @@ static int do_protostrs(FILE *fhdr, const char *fname) char protostr[256]; char path[256]; char fname_inc[256]; + int is_oslib; FILE *finc; int line = 0; int ret; @@ -69,6 +71,9 @@ static int do_protostrs(FILE *fhdr, const char *fname) hdrfn_saved = hdrfn; hdrfn = fname; + is_oslib = strstr(fname, "stdc.hlist") + || strstr(fname, "win32.hlist"); + while (fgets(protostr, sizeof(protostr), fhdr)) { line++; @@ -110,7 +115,7 @@ static int do_protostrs(FILE *fhdr, const char *fname) hdrfline = line; - ret = b_pp_c_handler(protostr, hdrfn); + ret = b_pp_c_handler(protostr, hdrfn, is_oslib); if (ret < 0) break; } @@ -653,7 +658,7 @@ static struct parsed_proto *pp_cache; static int pp_cache_size; static int pp_cache_alloc; -static int b_pp_c_handler(char *proto, const char *fname) +static int b_pp_c_handler(char *proto, const char *fname, int is_oslib) { int ret; @@ -671,6 +676,7 @@ static int b_pp_c_handler(char *proto, const char *fname) if (ret < 0) return -1; + pp_cache[pp_cache_size].is_oslib = is_oslib; pp_cache_size++; return 0; } diff --git a/tools/translate.c b/tools/translate.c index ff65fda..c697f32 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -473,7 +473,7 @@ static int guess_lmod_from_c_type(enum opr_lenmod *lmod, static const char *dword_types[] = { "int", "_DWORD", "UINT_PTR", "DWORD", "WPARAM", "LPARAM", "UINT", "__int32", - "LONG", "HIMC", + "LONG", "HIMC", "BOOL", }; static const char *word_types[] = { "uint16_t", "int16_t", "_WORD", "WORD", @@ -1561,7 +1561,9 @@ static void stack_frame_access(struct parsed_op *po, static void check_func_pp(struct parsed_op *po, const struct parsed_proto *pp, const char *pfx) { + enum opr_lenmod tmp_lmod; char buf[256]; + int ret, i; if (pp->argc_reg != 0) { if (/*!g_allow_regfunc &&*/ !pp->is_fastcall) { @@ -1572,6 +1574,18 @@ static void check_func_pp(struct parsed_op *po, ferr(po, "%s: %d reg arg(s) with %d stack arg(s)\n", pfx, pp->argc_reg, pp->argc_stack); } + + // fptrs must use 32bit args, callsite might have no information and + // lack a cast to smaller types, which results in incorrectly masked + // args passed (callee may assume masked args, it does on ARM) + if (!pp->is_oslib) { + for (i = 0; i < pp->argc; i++) { + ret = guess_lmod_from_c_type(&tmp_lmod, &pp->arg[i].type); + if (ret && tmp_lmod != OPLM_DWORD) + ferr(po, "reference to %s with arg%d '%s'\n", pp->name, + i + 1, pp->arg[i].type.name); + } + } } static const char *check_label_read_ref(struct parsed_op *po, diff --git a/winelib.mak b/winelib.mak index 77da421..a0558d3 100644 --- a/winelib.mak +++ b/winelib.mak @@ -10,7 +10,7 @@ LDFLAGS += -ggdb ifdef ARM CFLAGS += -mcpu=cortex-a8 -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon -CFLAGS += -Wno-unused +CFLAGS += -Wno-unused -fsigned-char WGCC_FLAGS += -marm -b$(patsubst %-,%,$(CROSS_COMPILE)) # wine defines wchar_t correctly, doesn't use -fshort-wchar, we can't too WGCC_FLAGS += -fno-short-wchar -- 2.39.2