From fc63475542736ba7667835dbea3532c0e9ec1567 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 16 Sep 2013 13:08:46 +0300 Subject: [PATCH] db, extra, user_data: handle: *x = 1; return x;" Say you have code like: int *frob(void) { *x = 42; return x; } It's good to know to record that *x is 42. But the real reason for this is because of memdup_user() which does: void *memdup_user(void *src, size_t size) { ... copy_from_user(dest, src, size); return dest; } In the old code, there was no way to record that the data it was returning was user data. Signed-off-by: Dan Carpenter --- check_user_data.c | 5 +++++ smatch_db.c | 17 +++++++++++++---- smatch_extra.c | 11 +++++++---- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/check_user_data.c b/check_user_data.c index 9d590f5a..b627ab4e 100644 --- a/check_user_data.c +++ b/check_user_data.c @@ -530,6 +530,11 @@ static void db_return_states_userdata(struct expression *expr, int param, char * char *name; struct symbol *sym; + if (expr->type == EXPR_ASSIGNMENT && param == -1 && strcmp(key, "*$$") == 0) { + tag_as_user_data(expr->left); + return; + } + name = return_state_to_var_sym(expr, param, key, &sym); if (!name || !sym) goto free; diff --git a/smatch_db.c b/smatch_db.c index 7ca344b1..0216e56e 100644 --- a/smatch_db.c +++ b/smatch_db.c @@ -932,9 +932,6 @@ static void print_returned_struct_members(int return_id, char *return_ranges, st type = get_type(expr); if (!type || type->type != SYM_PTR) return; - type = get_real_base_type(type); - if (!type || type->type != SYM_STRUCT) - return; name = expr_to_var(expr); if (!name) return; @@ -946,10 +943,16 @@ static void print_returned_struct_members(int return_id, char *return_ranges, st FOR_EACH_PTR(returned_member_callbacks, cb) { my_slist = get_all_states(cb->owner); FOR_EACH_PTR(my_slist, sm) { + if (sm->name[0] == '*' && strcmp(sm->name + 1, name) == 0) { + strcpy(member_name, "*$$"); + cb->callback(return_id, return_ranges, member_name, sm->state); + continue; + } if (strncmp(sm->name, name, len) != 0) continue; if (strncmp(sm->name + len, "->", 2) != 0) continue; + strcpy(member_name, "$$"); strncpy(member_name + 2, sm->name + len, sizeof(member_name) - 2); cb->callback(return_id, return_ranges, member_name, sm->state); } END_FOR_EACH_PTR(sm); @@ -1096,14 +1099,20 @@ char *return_state_to_var_sym(struct expression *expr, int param, char *key, str *sym = NULL; if (param == -1) { + const char *star = ""; + if (expr->type != EXPR_ASSIGNMENT) return NULL; name = expr_to_var_sym(expr->left, sym); if (!name) return NULL; + if (key[0] == '*') { + star = "*"; + key++; + } if (strncmp(key, "$$", 2) != 0) return name; - snprintf(member_name, sizeof(member_name), "%s%s", name, key + 2); + snprintf(member_name, sizeof(member_name), "%s%s%s", star, name, key + 2); free_string(name); return alloc_string(member_name); } diff --git a/smatch_extra.c b/smatch_extra.c index 8ae8abd3..46f4cd90 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -1318,21 +1318,19 @@ static void db_returned_member_info(struct expression *expr, int param, char *ke struct symbol *type; struct symbol *sym; char *name; - char member_name[256]; struct range_list *rl; if (expr->type != EXPR_ASSIGNMENT) return; - name = expr_to_var_sym(expr->left, &sym); + name = return_state_to_var_sym(expr, param, key, &sym); if (!name || !sym) goto free; - snprintf(member_name, sizeof(member_name), "%s%s", name, key + 2); type = get_member_type_from_key(expr->left, key); if (!type) return; call_results_to_rl(expr->right, type, value, &rl); - set_extra_mod(member_name, sym, alloc_estate_rl(rl)); + set_extra_mod(name, sym, alloc_estate_rl(rl)); free: free_string(name); @@ -1343,6 +1341,11 @@ static void returned_member_callback(int return_id, char *return_ranges, char *p if (estate_is_whole(state)) return; + /* these are handled in smatch_param_filter/set/limit.c */ + if (printed_name[0] != '*' && + !strchr(printed_name, '.') && !strchr(printed_name, '-')) + return; + sql_insert_return_states(return_id, return_ranges, RETURN_VALUE, -1, printed_name, state->name); } -- 2.11.4.GIT