From 08078e8b2231c5760b5a0f17ad1476e9517ccbd2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Sep 2018 17:53:09 +0300 Subject: [PATCH] extra/type: fix type of return PARAM_ADD/SET Imagine we have a function "void frob(char *p);" and it sets *p to an unknown signed char value. Then we have a caller "frob(&u8_variabl);". Before we would take -128-127 from the DB and try to put it into a u8, but -128 is less than a u8 so it would get confused and set the result to 0-127. Signed-off-by: Dan Carpenter --- smatch.h | 1 + smatch_extra.c | 10 ++++++---- smatch_type.c | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/smatch.h b/smatch.h index 497c9141..c9d54460 100644 --- a/smatch.h +++ b/smatch.h @@ -397,6 +397,7 @@ const char *global_static(); struct symbol *cur_func_return_type(void); struct symbol *get_arg_type(struct expression *fn, int arg); struct symbol *get_member_type_from_key(struct expression *expr, const char *key); +struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key); int is_struct(struct expression *expr); char *type_to_str(struct symbol *type); diff --git a/smatch_extra.c b/smatch_extra.c index 1b5463f7..aa8182fc 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -2428,7 +2428,7 @@ static void db_param_add_set(struct expression *expr, int param, char *key, char struct expression *arg; char *name, *tmp_name; struct symbol *sym, *tmp_sym; - struct symbol *type; + struct symbol *param_type, *arg_type; struct smatch_state *state; struct range_list *new = NULL; struct range_list *added = NULL; @@ -2441,7 +2441,9 @@ static void db_param_add_set(struct expression *expr, int param, char *key, char arg = get_argument_from_call_expr(expr->args, param); if (!arg) return; - type = get_member_type_from_key(arg, key); + + arg_type = get_arg_type_from_key(expr->fn, param, arg, key); + param_type = get_member_type_from_key(arg, key); name = get_variable_from_key(arg, key, &sym); if (!name || !sym) goto free; @@ -2450,8 +2452,8 @@ static void db_param_add_set(struct expression *expr, int param, char *key, char if (state) new = estate_rl(state); - call_results_to_rl(expr, type, value, &added); - + call_results_to_rl(expr, arg_type, value, &added); + added = cast_rl(param_type, added); if (op == PARAM_SET) new = added; else diff --git a/smatch_type.c b/smatch_type.c index f59c912c..23763b9f 100644 --- a/smatch_type.c +++ b/smatch_type.c @@ -658,6 +658,23 @@ struct symbol *get_member_type_from_key(struct expression *expr, const char *key return get_real_base_type(sym); } +struct symbol *get_arg_type_from_key(struct expression *fn, int param, struct expression *arg, const char *key) +{ + struct symbol *type; + + if (!key) + return NULL; + if (strcmp(key, "$") == 0) + return get_arg_type(fn, param); + if (strcmp(key, "*$") == 0) { + type = get_arg_type(fn, param); + if (!type || type->type != SYM_PTR) + return NULL; + return get_real_base_type(type); + } + return get_member_type_from_key(arg, key); +} + int is_struct(struct expression *expr) { struct symbol *type; -- 2.11.4.GIT