From b69706fe0155f7535d2abdf8ef118daca5daa993 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 14 Jun 2013 09:48:40 +0300 Subject: [PATCH] comparison: handle unmatched comparisons to " orig" states The problem here is this: int returns_less(int x) { int y; if (x < 10) y = x; else y = 10; return y; } On the true branch then we know that "y == x orig". On the false side, we have an unmatched state. For normal variables we take the implied range_list for both sides and get the comparison from that. For the " orig" state we can use the work in smatch_limit.c and call get_orig_estate() using the symbol pointer. Signed-off-by: Dan Carpenter --- smatch_comparison.c | 20 +++++++++++++++++--- smatch_extra.h | 3 ++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/smatch_comparison.c b/smatch_comparison.c index 5c72acc1..40ab4b4c 100644 --- a/smatch_comparison.c +++ b/smatch_comparison.c @@ -159,6 +159,16 @@ static int rl_comparison(struct range_list *left_rl, struct range_list *right_rl return 0; } +static struct range_list *get_orig_rl(struct symbol *sym) +{ + struct smatch_state *state; + + if (!sym || !sym->ident) + return NULL; + state = get_orig_estate(sym->ident->name, sym); + return estate_rl(state); +} + static struct smatch_state *unmatched_comparison(struct sm_state *sm) { struct compare_data *data = sm->state->data; @@ -168,9 +178,13 @@ static struct smatch_state *unmatched_comparison(struct sm_state *sm) if (!data) return &undefined; - if (!get_implied_rl_var_sym(data->var1, data->sym1, &left_rl)) + if (strstr(data->var1, " orig")) + left_rl = get_orig_rl(data->sym1); + else if (!get_implied_rl_var_sym(data->var1, data->sym1, &left_rl)) return &undefined; - if (!get_implied_rl_var_sym(data->var2, data->sym2, &right_rl)) + if (strstr(data->var2, " orig")) + right_rl = get_orig_rl(data->sym2); + else if (!get_implied_rl_var_sym(data->var2, data->sym2, &right_rl)) return &undefined; op = rl_comparison(left_rl, right_rl); @@ -306,7 +320,7 @@ static void save_start_states(struct statement *stmt) continue; snprintf(orig, sizeof(orig), "%s orig", param->ident->name); snprintf(state_name, sizeof(state_name), "%s vs %s", param->ident->name, orig); - state = alloc_compare_state(param->ident->name, param, alloc_sname(orig), NULL, SPECIAL_EQUAL); + state = alloc_compare_state(param->ident->name, param, alloc_sname(orig), param, SPECIAL_EQUAL); set_state(compare_id, state_name, NULL, state); link = alloc_sname(state_name); diff --git a/smatch_extra.h b/smatch_extra.h index 003191cd..a2e11a18 100644 --- a/smatch_extra.h +++ b/smatch_extra.h @@ -157,4 +157,5 @@ struct expression *binop_expression(struct expression *left, int op, struct expr struct expression *array_element_expression(struct expression *array, struct expression *offset); struct expression *symbol_expression(struct symbol *sym); - +/* smatch_param_limit.c */ +struct smatch_state *get_orig_estate(const char *name, struct symbol *sym); -- 2.11.4.GIT