Skip to content

Commit

Permalink
dereferences_param: re-write simpler
Browse files Browse the repository at this point in the history
This takes advantage of the add_dereference_hook() now so a lot of code
can be deleted.

Signed-off-by: Dan Carpenter <[email protected]>
  • Loading branch information
Dan Carpenter committed May 8, 2023
1 parent f53e8d2 commit 4ce3816
Showing 1 changed file with 20 additions and 145 deletions.
165 changes: 20 additions & 145 deletions check_dereferences_param.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,140 +28,6 @@
static int my_id;

STATE(derefed);
STATE(ignore);
STATE(param);

static void pre_merge_hook(struct sm_state *cur, struct sm_state *other)
{
if (cur->state == &derefed || other->state != &derefed)
return;
if (is_impossible_path())
set_state(my_id, cur->name, cur->sym, &derefed);
}

static void set_ignore(struct sm_state *sm, struct expression *mod_expr)
{
if (sm->state == &derefed)
return;
set_state(my_id, sm->name, sm->sym, &ignore);
}

static void match_function_def(struct symbol *sym)
{
struct symbol *arg;
int i;

i = -1;
FOR_EACH_PTR(sym->ctype.base_type->arguments, arg) {
i++;
if (!arg->ident)
continue;
set_state(my_id, arg->ident->name, arg, &param);
} END_FOR_EACH_PTR(arg);
}

static int is_ignored_param(struct expression *expr)
{
struct sm_state *sm;

if (param_was_set(expr))
return 1;

sm = get_sm_state_expr(my_id, expr);
if (sm && slist_has_state(sm->possible, &ignore))
return 1;
return 0;
}

static void check_deref(struct expression *expr)
{
struct expression *tmp;

if (is_impossible_path())
return;

tmp = get_assigned_expr(expr);
if (tmp)
expr = tmp;

if (expr->type == EXPR_PREOP &&
expr->op == '&') {
expr = strip_expr(expr->unop);
if (expr->type != EXPR_DEREF)
return;
expr = strip_expr(expr->deref);
if (expr->type != EXPR_PREOP ||
expr->op != '*')
return;
expr = strip_expr(expr->unop);
}

expr = strip_expr(expr);
if (!expr)
return;

if (expr->type == EXPR_PREOP && expr->op == '&')
return;

if (get_param_num(expr) < 0)
return;

if (is_ignored_param(expr))
return;

if (param_was_set(expr))
return;

/*
* At this point we really only care about potential NULL dereferences.
* Potentially in the future we will care about everything.
*/
if (implied_not_equal(expr, 0))
return;

set_state_expr(my_id, expr, &derefed);
}

static void match_dereference(struct expression *expr)
{
if (expr->type != EXPR_PREOP)
return;
check_deref(expr->unop);
}

static void find_inner_dereferences(struct expression *expr)
{
while (expr->type == EXPR_PREOP) {
if (expr->op == '*')
check_deref(expr->unop);
expr = strip_expr(expr->unop);
}
}

static void set_param_dereferenced(struct expression *call, struct expression *arg, char *key, char *unused)
{
struct symbol *sym;
char *name;

check_deref(arg);

name = get_variable_from_key(arg, key, &sym);
if (!name || !sym)
goto free;
if (name[0] == '&')
goto free;
if (is_ignored_param(symbol_expression(sym)))
goto free;
if (get_param_num_from_sym(sym) < 0)
goto free;
if (param_was_set_var_sym(name, sym))
goto free;

set_state(my_id, name, sym, &derefed);
find_inner_dereferences(arg);
free:
free_string(name);
}

static void process_states(void)
{
Expand All @@ -182,24 +48,33 @@ static void process_states(void)
} END_FOR_EACH_SM(tmp);
}

static void match_pointer_as_array(struct expression *expr)
static void deref_hook(struct expression *expr)
{
if (!is_array(expr))
char *param_name = NULL;
struct symbol *sym, *param_sym;
char *name;

name = expr_to_var_sym(expr, &sym);
if (!name)
return;
check_deref(get_array_base(expr));

param_name = get_param_var_sym_var_sym(name, sym, NULL, &param_sym);
if (!param_name || !param_sym)
goto free;
if (get_param_num_from_sym(param_sym) < 0)
goto free;
if (param_was_set_var_sym(param_name, param_sym))
goto free;

set_state(my_id, param_name, param_sym, &derefed);
free:
free_string(name);
}

void check_dereferences_param(int id)
{
my_id = id;

add_hook(&match_function_def, FUNC_DEF_HOOK);

add_hook(&match_dereference, DEREF_HOOK);
add_hook(&match_pointer_as_array, OP_HOOK);
select_return_implies_hook(DEREFERENCE, &set_param_dereferenced);
add_modification_hook(my_id, &set_ignore);
add_pre_merge_hook(my_id, &pre_merge_hook);

add_dereference_hook(deref_hook);
all_return_states_hook(&process_states);
}

0 comments on commit 4ce3816

Please sign in to comment.