#include <stdlib.h>
#include "parse.h"
#include "smatch.h"
#include "smatch_slist.h"
#include "smatch_extra.h"
static int my_used_id;
static void delete(struct sm_state *sm, struct expression *mod_expr)
{
set_state(my_used_id, sm->name, sm->sym, &undefined);
}
static void array_check(struct expression *expr)
{
struct expression *array_expr;
int array_size;
struct expression *offset;
struct range_list *rl;
expr = strip_expr(expr);
if (!is_array(expr))
return;
array_expr = get_array_base(expr);
array_size = get_array_size(array_expr);
if (!array_size || array_size == 1)
return;
offset = get_array_offset(expr);
get_absolute_rl(offset, &rl);
if (rl_max(rl).uvalue < array_size)
return;
if (buf_comparison_index_ok(expr))
return;
if (getting_address(expr))
return;
if (is_capped(offset))
return;
set_state_expr(my_used_id, offset, alloc_state_num(array_size));
}
static void match_condition(struct expression *expr)
{
int left;
sval_t sval;
struct state_list *slist;
struct sm_state *tmp;
int boundary;
if (!expr || expr->type != EXPR_COMPARE)
return;
if (get_macro_name(expr->pos))
return;
if (get_implied_value(expr->left, &sval))
left = 1;
else if (get_implied_value(expr->right, &sval))
left = 0;
else
return;
if (left)
slist = get_possible_states_expr(my_used_id, expr->right);
else
slist = get_possible_states_expr(my_used_id, expr->left);
if (!slist)
return;
FOR_EACH_PTR(slist, tmp) {
if (tmp->state == &merged || tmp->state == &undefined)
continue;
boundary = PTR_INT(tmp->state->data);
boundary -= sval.value;
if (boundary < 1 && boundary > -1) {
char *name;
name = expr_to_var(left ? expr->right : expr->left);
sm_error("testing array offset '%s' after use.", name);
return;
}
} END_FOR_EACH_PTR(tmp);
}
void check_testing_index_after_use(int id)
{
my_used_id = id;
set_dynamic_states(my_used_id);
add_hook(&array_check, OP_HOOK);
add_hook(&match_condition, CONDITION_HOOK);
add_modification_hook(my_used_id, &delete);
}