From f7e3fce8ce7a1749a537322a0d0d31d6d668b689 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 16 Mar 2009 10:28:14 +0300 Subject: [PATCH] check_memory: assume parents assigned on all paths when assigned on one. The problem is that when you merge &assigned + NULL you get undefined. if (x) { foo->bar = kmalloc(); x = foo; } <- x is &assigned + NULL which is &undefined. This fix isn't the greatest but smatch doesn't have a way to express what I really want here. Signed-off-by: Dan Carpenter --- check_memory.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/check_memory.c b/check_memory.c index 3acfd260..cc0e6d6d 100644 --- a/check_memory.c +++ b/check_memory.c @@ -36,6 +36,23 @@ static const char *allocation_funcs[] = { NULL, }; +static struct smatch_state *merge_func(const char *name, struct symbol *sym, + struct smatch_state *s1, + struct smatch_state *s2) +{ + if (!strcmp(name, "-")) + return &assigned; + /* this is normal merge */ + if (!s1 || !s2) + return &undefined; + return &merged; +} + +static void assign_parent(struct symbol *sym) +{ + set_state("-", my_id, sym, &assigned); +} + static int parent_is_assigned(struct symbol *sym) { struct smatch_state *state; @@ -112,7 +129,7 @@ static void match_declarations(struct symbol *sym) if (is_allocation(sym->initializer)) { set_state(name, my_id, sym, &malloced); } else { - set_state("-", my_id, sym, &assigned); + assign_parent(sym); } } } @@ -136,15 +153,15 @@ static int handle_double_assign(struct expression *expr) name = get_variable_from_expr(expr->left, &sym); if (name && is_parent(expr->left)) - set_state("-", my_id, sym, &assigned); + assign_parent(sym); name = get_variable_from_expr(expr->right->left, &sym); if (name && is_parent(expr->right->left)) - set_state("-", my_id, sym, &assigned); + assign_parent(sym); name = get_variable_from_expr(expr->right->right, &sym); if (name && is_parent(expr->right->right)) - set_state("-", my_id, sym, &assigned); + assign_parent(sym); return 1; } @@ -172,7 +189,8 @@ static void match_assign(struct expression *expr) right = strip_expr(expr->right); if (left_name && left_sym && is_allocation(right) && !(left_sym->ctype.modifiers & - (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE))) { + (MOD_NONLOCAL | MOD_STATIC | MOD_ADDRESSABLE)) && + !parent_is_assigned(left_sym)) { set_state(left_name, my_id, left_sym, &malloced); goto exit; } @@ -189,9 +207,9 @@ static void match_assign(struct expression *expr) set_state(left_name, my_id, left_sym, &unfree); } if (left_name && is_parent(left)) - set_state("-", my_id, left_sym, &assigned); + assign_parent(left_sym); if (right_name && is_parent(right)) - set_state("-", my_id, right_sym, &assigned); + assign_parent(right_sym); exit: free_string(left_name); free_string(right_name); @@ -265,7 +283,7 @@ static void match_return(struct statement *stmt) name = get_variable_from_expr(stmt->ret_value, &sym); if (sym) - set_state("-", my_id, sym, &assigned); + assign_parent(sym); free_string(name); check_for_allocated(); } @@ -342,7 +360,7 @@ static void match_function_call(struct expression *expr) set_state(name, my_id, sym, &assigned); } } - set_state("-", my_id, sym, &assigned); + assign_parent(sym); } END_FOR_EACH_PTR(tmp); } @@ -355,6 +373,7 @@ static void match_end_func(struct symbol *sym) void register_memory(int id) { my_id = id; + add_merge_hook(my_id, &merge_func); add_hook(&match_function_def, FUNC_DEF_HOOK); add_hook(&match_declarations, DECLARATION_HOOK); add_hook(&match_function_call, FUNCTION_CALL_HOOK); -- 2.11.4.GIT