From 7c1bad39e43e4327927d582b6b58a69e3f2ab7ac Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 18 Dec 2012 11:53:20 +0300 Subject: [PATCH] db: handle unchanged return_states better The situation here is when some paths through the function have implications for the parameter values and some don't. In other words we know that a return value of -5 means something about parameter 1 but it doesn't mean anything about parameter 2. In that situation the original code would say treat that as an whole_range but instead we should be looking at the value that we passed into the function. Signed-off-by: Dan Carpenter --- smatch.h | 2 ++ smatch_extra.c | 20 +++++++++++++++++++ smatch_function_hooks.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/smatch.h b/smatch.h index 09f9b24d..cceced14 100644 --- a/smatch.h +++ b/smatch.h @@ -134,6 +134,8 @@ void add_macro_assign_hook_extra(const char *look_for, func_hook *call_back, void return_implies_state(const char *look_for, long long start, long long end, implication_hook *call_back, void *info); void add_db_return_states_callback(int type, return_implies_hook *callback); +void add_db_return_states_before(void (*fn)(void)); +void add_db_return_states_after(void (*fn)(void)); int get_implied_return(struct expression *expr, struct range_list **rl); typedef void (modification_hook)(struct sm_state *sm); diff --git a/smatch_extra.c b/smatch_extra.c index 060e4380..37f33cd2 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -364,8 +364,16 @@ void __extra_pre_loop_hook_after(struct sm_state *sm, set_extra_mod(sm->name, sm->sym, state); } +static struct state_list *unmatched_slist; static struct smatch_state *unmatched_state(struct sm_state *sm) { + struct smatch_state *state; + + if (unmatched_slist) { + state = get_state_slist(unmatched_slist, SMATCH_EXTRA, sm->name, sm->sym); + if (state) + return state; + } return extra_undefined(estate_type(sm->state)); } @@ -936,6 +944,16 @@ static void struct_member_callback(char *fn, char *global_static, int param, cha sm_msg("info: passes param_value '%s' %d '%s' %s %s", fn, param, printed_name, state->name, global_static); } +static void db_limited_before(void) +{ + unmatched_slist = clone_slist(__get_cur_slist()); +} + +static void db_limited_after(void) +{ + free_slist(&unmatched_slist); +} + static void db_limited_param(struct expression *expr, int param, char *key, char *value) { struct expression *arg; @@ -1195,7 +1213,9 @@ void register_smatch_extra(int id) add_definition_db_callback(set_param_value, PARAM_VALUE); add_db_return_states_callback(RETURN_VALUE, &db_returned_member_info); add_db_return_states_callback(PARAM_VALUE, &db_returned_states_param); + add_db_return_states_before(&db_limited_before); add_db_return_states_callback(LIMITED_VALUE, &db_limited_param); + add_db_return_states_after(&db_limited_after); } void register_smatch_extra_late(int id) diff --git a/smatch_function_hooks.c b/smatch_function_hooks.c index 3faadef6..acb9101a 100644 --- a/smatch_function_hooks.c +++ b/smatch_function_hooks.c @@ -57,6 +57,11 @@ ALLOCATOR(return_implies_callback, "return_implies callbacks"); DECLARE_PTR_LIST(db_implies_list, struct return_implies_callback); static struct db_implies_list *db_return_states_list; +typedef void (void_fn)(void); +DECLARE_PTR_LIST(void_fn_list, void_fn *); +static struct void_fn_list *return_states_before; +static struct void_fn_list *return_states_after; + static struct fcall_back *alloc_fcall_back(int type, void *call_back, void *info) { @@ -133,6 +138,38 @@ void add_db_return_states_callback(int type, return_implies_hook *callback) add_ptr_list(&db_return_states_list, cb); } +void add_db_return_states_before(void_fn *fn) +{ + void_fn **p = malloc(sizeof(void_fn *)); + *p = fn; + add_ptr_list(&return_states_before, p); +} + +void add_db_return_states_after(void_fn *fn) +{ + void_fn **p = malloc(sizeof(void_fn *)); + *p = fn; + add_ptr_list(&return_states_after, p); +} + +static void call_return_states_before_hooks(void) +{ + void_fn **fn; + + FOR_EACH_PTR(return_states_before, fn) { + (*fn)(); + } END_FOR_EACH_PTR(fn); +} + +static void call_return_states_after_hooks(void) +{ + void_fn **fn; + + FOR_EACH_PTR(return_states_after, fn) { + (*fn)(); + } END_FOR_EACH_PTR(fn); +} + static int call_call_backs(struct call_back_list *list, int type, const char *fn, struct expression *expr) { @@ -371,6 +408,8 @@ void compare_db_return_states_callbacks(int comparison, struct expression *expr, db_info.left = left; db_info.callbacks = db_return_states_list; + call_return_states_before_hooks(); + db_info.true_side = 1; __push_fake_cur_slist(); run_sql(db_compare_callback, @@ -392,6 +431,8 @@ void compare_db_return_states_callbacks(int comparison, struct expression *expr, __set_true_false_sm(NULL, sm); } END_FOR_EACH_PTR(sm); + call_return_states_after_hooks(); + free_slist(&true_states); free_slist(&false_states); } @@ -473,6 +514,9 @@ static int db_return_states_assign(struct expression *expr) prev_return_id = -1; db_info.expr = expr; db_info.slist = NULL; + + call_return_states_before_hooks(); + __push_fake_cur_slist(); run_sql(db_assign_return_states_callback, "select return_id, return, type, parameter, key, value from return_states where %s", @@ -485,6 +529,8 @@ static int db_return_states_assign(struct expression *expr) handled = 1; } END_FOR_EACH_PTR(sm); + call_return_states_after_hooks(); + return handled; } @@ -596,6 +642,9 @@ static void db_return_states(struct expression *expr) prev_return_id = -1; db_info.expr = expr; db_info.slist = NULL; + + call_return_states_before_hooks(); + __push_fake_cur_slist(); __unnullify_path(); run_sql(db_return_states_callback, @@ -607,6 +656,8 @@ static void db_return_states(struct expression *expr) FOR_EACH_PTR(db_info.slist, sm) { __set_sm(sm); } END_FOR_EACH_PTR(sm); + + call_return_states_after_hooks(); } static int is_assigned_call(struct expression *expr) -- 2.11.4.GIT