From 2c9b820309f1fad6a4ef64b569e032e82b749b68 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 30 Mar 2015 14:34:04 +0300 Subject: [PATCH] param_limit: handle struct members PARAM_LIMIT is code like this: int is_ok(struct foo *p) { if (p->bar >= 0 && p->bar < 100) return 1; return 0; } PARAM_FILTER looks like this: void some_func(struct foo *p) { if (p->bar < 0 || p->bar >= 100) p->bar = 0; } In the original code, if it was a parameter "$" then we limited it, but if it was a struct member "$->bar" then we filtered it. This was wrong and it caused some false positives. Also a struct member can be both limited and filtered so the ordering has to be handle the limits first and then the filtering. Signed-off-by: Dan Carpenter --- smatch.h | 4 +-- smatch_param_filter.c | 25 ----------------- smatch_param_limit.c | 74 +++++++++++++++++++++++++-------------------------- 3 files changed, 39 insertions(+), 64 deletions(-) diff --git a/smatch.h b/smatch.h index b310b4bf..5fce2a02 100644 --- a/smatch.h +++ b/smatch.h @@ -577,7 +577,8 @@ enum info_type { * it a number below 100-999,9000-9999 ranges. */ PARAM_CLEARED = 101, - PARAM_FILTER = 102, + PARAM_LIMIT = 103, + PARAM_FILTER = 104, PARAM_VALUE = 1001, BUF_SIZE = 1002, @@ -589,7 +590,6 @@ enum info_type { LOCK_HELD = 1008, LOCK_RELEASED = 1009, ABSOLUTE_LIMITS = 1010, - PARAM_LIMIT = 1011, PARAM_ADD = 1012, PARAM_FREED = 1013, DATA_SOURCE = 1014, diff --git a/smatch_param_filter.c b/smatch_param_filter.c index 16f62837..44df43ec 100644 --- a/smatch_param_filter.c +++ b/smatch_param_filter.c @@ -152,29 +152,6 @@ static void print_one_mod_param(int return_id, char *return_ranges, param_name, show_rl(estate_rl(sm->state))); } -static void print_one_extra_param(int return_id, char *return_ranges, - int param, struct sm_state *sm, struct string_list **totally_filtered) -{ - struct smatch_state *old; - const char *param_name; - - if (estate_is_whole(sm->state)) - return; - old = get_state_stree(start_states, SMATCH_EXTRA, sm->name, sm->sym); - if (old && estates_equiv(old, sm->state)) - return; - - param_name = get_param_name(sm); - if (!param_name) - return; - - if (strcmp(sm->state->name, "") == 0) - insert_string(totally_filtered, (char *)sm->name); - - sql_insert_return_states(return_id, return_ranges, PARAM_FILTER, param, - param_name, sm->state->name); -} - static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr) { struct sm_state *tmp; @@ -197,8 +174,6 @@ static void print_return_value_param(int return_id, char *return_ranges, struct sm = get_sm_state(my_id, tmp->name, tmp->sym); if (sm) print_one_mod_param(return_id, return_ranges, param, sm, &totally_filtered); - else - print_one_extra_param(return_id, return_ranges, param, tmp, &totally_filtered); } END_FOR_EACH_SM(tmp); free_ptr_list((struct ptr_list **)&totally_filtered); diff --git a/smatch_param_limit.c b/smatch_param_limit.c index c51c0971..f6ca9517 100644 --- a/smatch_param_limit.c +++ b/smatch_param_limit.c @@ -54,17 +54,7 @@ static struct stree_stack *saved_stack; static void save_start_states(struct statement *stmt) { - struct smatch_state *state; - struct symbol *tmp; - - FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, tmp) { - if (!tmp->ident) - continue; - state = get_state(SMATCH_EXTRA, tmp->ident->name, tmp); - if (!state) - state = alloc_estate_whole(get_real_base_type(tmp)); - set_state_stree(&start_states, SMATCH_EXTRA, tmp->ident->name, tmp, state); - } END_FOR_EACH_PTR(tmp); + start_states = get_all_states_stree(SMATCH_EXTRA); } static void free_start_states(void) @@ -96,35 +86,49 @@ struct smatch_state *get_orig_estate(const char *name, struct symbol *sym) return alloc_estate_rl(alloc_whole_rl(get_real_base_type(sym))); } +struct smatch_state *get_orig_estate_type(const char *name, struct symbol *sym, struct symbol *type) +{ + struct smatch_state *state; + + state = get_state(my_id, name, sym); + if (state) + return state; + + state = get_state(SMATCH_EXTRA, name, sym); + if (state) + return state; + return alloc_estate_rl(alloc_whole_rl(type)); +} + static void print_return_value_param(int return_id, char *return_ranges, struct expression *expr) { - struct smatch_state *start_state, *state; - struct symbol *tmp; + struct smatch_state *state, *old; + struct sm_state *tmp; + const char *param_name; int param; - param = -1; - FOR_EACH_PTR(cur_func_sym->ctype.base_type->arguments, tmp) { - param++; - if (!tmp->ident) + FOR_EACH_MY_SM(SMATCH_EXTRA, __get_cur_stree(), tmp) { + param = get_param_num_from_sym(tmp->sym); + if (param < 0) continue; - state = get_state(my_id, tmp->ident->name, tmp); - if (state) - goto print; - state = get_state(SMATCH_EXTRA, tmp->ident->name, tmp); - if (state) - goto print; - continue; -print: - if (estate_is_whole(state)) + + param_name = get_param_name(tmp); + if (!param_name) continue; - start_state = get_state_stree(start_states, SMATCH_EXTRA, tmp->ident->name, tmp); - if (estates_equiv(state, start_state)) + state = get_state(my_id, tmp->name, tmp->sym); + if (!state) + state = tmp->state; + + if (estate_is_whole(state)) + continue; + old = get_state_stree(start_states, SMATCH_EXTRA, tmp->name, tmp->sym); + if (old && estates_equiv(old, state)) continue; -// sm_msg("return_range %s limited '%s' from %s to %s", return_ranges, tmp->ident->name, start_state->name, state->name); - sql_insert_return_states(return_id, return_ranges, - PARAM_LIMIT, param, "$", state->name); - } END_FOR_EACH_PTR(tmp); + + sql_insert_return_states(return_id, return_ranges, PARAM_LIMIT, + param, param_name, state->name); + } END_FOR_EACH_SM(tmp); } static void extra_mod_hook(const char *name, struct symbol *sym, struct smatch_state *state) @@ -136,11 +140,7 @@ static void extra_mod_hook(const char *name, struct symbol *sym, struct smatch_s if (param < 0) return; - /* we only save on-stack params */ - if (!sym->ident || strcmp(name, sym->ident->name) != 0) - return; - - orig_vals = get_orig_estate(name, sym); + orig_vals = get_orig_estate_type(name, sym, estate_type(state)); set_state(my_id, name, sym, orig_vals); } -- 2.11.4.GIT