From 0adcfd7c0fd501c191a688f0e509b16fc73e27ee Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 30 Nov 2016 23:06:56 +0300 Subject: [PATCH] user_data2: math: function calls should be handled by the custom call back When we're doing user data math then function calls are particularly important. Signed-off-by: Dan Carpenter --- check_user_data2.c | 86 +++++++++++++++++++++++++++++++++++++++++++++--------- smatch_math.c | 6 ++++ 2 files changed, 78 insertions(+), 14 deletions(-) diff --git a/check_user_data2.c b/check_user_data2.c index ab98162a..62086282 100644 --- a/check_user_data2.c +++ b/check_user_data2.c @@ -383,8 +383,7 @@ static void match_assign(struct expression *expr) if (handle_struct_assignment(expr)) return; - if (expr->right->type == EXPR_CALL || - !get_user_rl(expr->right, &rl)) + if (!get_user_rl(expr->right, &rl)) goto clear_old_state; rl = cast_rl(get_type(expr->left), rl); @@ -430,6 +429,44 @@ static int get_user_macro_rl(struct expression *expr, struct range_list **rl) return 0; } +struct db_info { + struct range_list *rl; + struct expression *call; +}; +static int returned_rl_callback(void *_info, int argc, char **argv, char **azColName) +{ + struct db_info *db_info = _info; + struct range_list *rl; + + if (argc != 1) + return 0; + + call_results_to_rl(db_info->call, get_type(db_info->call), argv[0], &rl); + db_info->rl = rl_union(db_info->rl, rl); + + return 0; +} + +static int db_returned_user_rl(struct expression *call, struct range_list **rl) +{ + struct db_info db_info = {}; + + /* for function pointers assume everything is used */ + if (call->fn->type != EXPR_SYMBOL) + return 0; + if (is_fake_call(call)) + return 0; + + db_info.call = call; + run_sql(&returned_rl_callback, &db_info, + "select value from return_states where %s and type = %d and parameter = -1 and key = '$';", + get_static_filter(call->fn->symbol), USER_DATA3); + if (!db_info.rl) + return 0; + *rl = db_info.rl; + return 1; +} + static int user_data_flag; static struct range_list *var_user_rl(struct expression *expr) { @@ -451,6 +488,9 @@ static struct range_list *var_user_rl(struct expression *expr) goto found; } + if (expr->type == EXPR_CALL && db_returned_user_rl(expr, &rl)) + goto found; + return NULL; found: user_data_flag = 1; @@ -580,24 +620,15 @@ static void match_syscall_definition(struct symbol *sym) } END_FOR_EACH_PTR(arg); } -static void returns_param_user_data(struct expression *expr, int param, char *key, char *value) +static void set_to_user_data(struct expression *expr, char *key, char *value) { - struct expression *arg; char *name; struct symbol *sym; struct symbol *type; struct range_list *rl = NULL; - while (expr->type == EXPR_ASSIGNMENT) - expr = strip_expr(expr->right); - if (expr->type != EXPR_CALL) - return; - - arg = get_argument_from_call_expr(expr->args, param); - if (!arg) - return; - type = get_member_type_from_key(arg, key); - name = get_variable_from_key(arg, key, &sym); + type = get_member_type_from_key(expr, key); + name = get_variable_from_key(expr, key, &sym); if (!name || !sym) goto free; @@ -606,6 +637,27 @@ static void returns_param_user_data(struct expression *expr, int param, char *ke set_state(my_id, name, sym, alloc_estate_rl(rl)); free: free_string(name); + +} + +static void returns_param_user_data(struct expression *expr, int param, char *key, char *value) +{ + struct expression *arg; + + if (param == -1) { + set_to_user_data(expr->left, key, value); + return; + } + + while (expr->type == EXPR_ASSIGNMENT) + expr = strip_expr(expr->right); + if (expr->type != EXPR_CALL) + return; + + arg = get_argument_from_call_expr(expr->args, param); + if (!arg) + return; + set_to_user_data(arg, key, value); } static int has_empty_state(struct sm_state *sm) @@ -624,6 +676,7 @@ static void param_set_to_user_data(int return_id, char *return_ranges, struct ex { struct sm_state *sm; struct smatch_state *start_state; + struct range_list *rl; int param; const char *param_name; @@ -659,6 +712,11 @@ static void param_set_to_user_data(int return_id, char *return_ranges, struct ex sql_insert_return_states(return_id, return_ranges, USER_DATA3, param, param_name, show_rl(estate_rl(sm->state))); } END_FOR_EACH_SM(sm); + + if (get_user_rl(expr, &rl)) { + sql_insert_return_states(return_id, return_ranges, USER_DATA3, + -1, "$", show_rl(rl)); + } } void check_user_data2(int id) diff --git a/smatch_math.c b/smatch_math.c index f4c4d1bb..1b588943 100644 --- a/smatch_math.c +++ b/smatch_math.c @@ -925,6 +925,12 @@ static struct range_list *handle_call_rl(struct expression *expr, int implied, i if (implied == RL_EXACT || implied == RL_HARD || implied == RL_FUZZY) return NULL; + if (custom_handle_variable) { + rl = custom_handle_variable(expr); + if (rl) + return rl; + } + if (get_implied_return(expr, &rl)) return rl; return db_return_vals(expr); -- 2.11.4.GIT