Print this page
11506 smatch resync
*** 34,48 ****
#include "smatch_slist.h"
#include "smatch_extra.h"
static int my_id;
static int link_id;
static void match_link_modify(struct sm_state *sm, struct expression *mod_expr);
struct string_list *__ignored_macros = NULL;
! static int in_warn_on_macro(void)
{
struct statement *stmt;
char *tmp;
char *macro;
--- 34,49 ----
#include "smatch_slist.h"
#include "smatch_extra.h"
static int my_id;
static int link_id;
+ extern int check_assigned_expr_id;
static void match_link_modify(struct sm_state *sm, struct expression *mod_expr);
struct string_list *__ignored_macros = NULL;
! int in_warn_on_macro(void)
{
struct statement *stmt;
char *tmp;
char *macro;
*** 132,197 ****
return NULL;
return expr_to_var_sym(assigned->unop, new_sym);
}
! char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
{
struct expression *assigned;
char *orig_name = NULL;
char buf[256];
! char *ret = NULL;
! int skip;
! *new_sym = NULL;
!
! if (!sym || !sym->ident)
! return NULL;
!
! ret = get_pointed_at(name, sym, new_sym);
! if (ret)
! return ret;
!
! skip = strlen(sym->ident->name);
! if (name[skip] != '-' || name[skip + 1] != '>')
! return NULL;
! skip += 2;
!
! assigned = get_assigned_expr_name_sym(sym->ident->name, sym);
if (!assigned)
return NULL;
if (assigned->type == EXPR_CALL)
return map_call_to_other_name_sym(name, sym, new_sym);
! if (assigned->type == EXPR_PREOP || assigned->op == '&') {
orig_name = expr_to_var_sym(assigned, new_sym);
if (!orig_name || !*new_sym)
goto free;
! snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + skip);
ret = alloc_string(buf);
free_string(orig_name);
return ret;
}
- if (assigned->type != EXPR_DEREF)
- goto free;
-
orig_name = expr_to_var_sym(assigned, new_sym);
if (!orig_name || !*new_sym)
goto free;
! snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + skip);
ret = alloc_string(buf);
free_string(orig_name);
return ret;
-
free:
free_string(orig_name);
return NULL;
}
void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
char *new_name;
struct symbol *new_sym;
--- 133,259 ----
return NULL;
return expr_to_var_sym(assigned->unop, new_sym);
}
! char *get_other_name_sym_from_chunk(const char *name, const char *chunk, int len, struct symbol *sym, struct symbol **new_sym)
{
struct expression *assigned;
char *orig_name = NULL;
char buf[256];
! char *ret;
! assigned = get_assigned_expr_name_sym(chunk, sym);
if (!assigned)
return NULL;
if (assigned->type == EXPR_CALL)
return map_call_to_other_name_sym(name, sym, new_sym);
! if (assigned->type == EXPR_PREOP && assigned->op == '&') {
orig_name = expr_to_var_sym(assigned, new_sym);
if (!orig_name || !*new_sym)
goto free;
! snprintf(buf, sizeof(buf), "%s.%s", orig_name + 1, name + len);
ret = alloc_string(buf);
free_string(orig_name);
return ret;
}
orig_name = expr_to_var_sym(assigned, new_sym);
if (!orig_name || !*new_sym)
goto free;
! snprintf(buf, sizeof(buf), "%s->%s", orig_name, name + len);
ret = alloc_string(buf);
free_string(orig_name);
return ret;
free:
free_string(orig_name);
return NULL;
}
+ static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
+ {
+ struct expression *tmp;
+ struct sm_state *sm;
+ char buf[256];
+
+ /*
+ * Just prepend the name with a different name/sym and return that.
+ * For example, if we set "foo->bar = bar;" then we clamp "bar->baz",
+ * that also clamps "foo->bar->baz".
+ *
+ */
+
+ FOR_EACH_MY_SM(check_assigned_expr_id, __get_cur_stree(), sm) {
+ tmp = sm->state->data;
+ if (!tmp || tmp->type != EXPR_SYMBOL)
+ continue;
+ if (tmp->symbol == sym)
+ goto found;
+ } END_FOR_EACH_SM(sm);
+
+ return NULL;
+
+ found:
+ snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
+ *new_sym = sm->sym;
+ return alloc_string(buf);
+ }
+
+ char *get_other_name_sym_helper(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
+ {
+ char buf[256];
+ char *ret;
+ int len;
+
+ *new_sym = NULL;
+
+ if (!sym || !sym->ident)
+ return NULL;
+
+ ret = get_pointed_at(name, sym, new_sym);
+ if (ret)
+ return ret;
+
+ ret = map_long_to_short_name_sym(name, sym, new_sym, use_stack);
+ if (ret)
+ return ret;
+
+ len = snprintf(buf, sizeof(buf), "%s", name);
+ if (len >= sizeof(buf) - 2)
+ return NULL;
+
+ while (len >= 1) {
+ if (buf[len] == '>' && buf[len - 1] == '-') {
+ len--;
+ buf[len] = '\0';
+ ret = get_other_name_sym_from_chunk(name, buf, len + 2, sym, new_sym);
+ if (ret)
+ return ret;
+ }
+ len--;
+ }
+
+ ret = get_long_name_sym(name, sym, new_sym);
+ if (ret)
+ return ret;
+
+ return NULL;
+ }
+
+ char *get_other_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym)
+ {
+ return get_other_name_sym_helper(name, sym, new_sym, true);
+ }
+
+ char *get_other_name_sym_nostack(const char *name, struct symbol *sym, struct symbol **new_sym)
+ {
+ return get_other_name_sym_helper(name, sym, new_sym, false);
+ }
+
void set_extra_mod(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
char *new_name;
struct symbol *new_sym;
*** 299,310 ****
set_related(state, estate_related(orig_state));
FOR_EACH_PTR(estate_related(orig_state), rel) {
struct smatch_state *estate;
- if (option_debug_related)
- sm_msg("%s updating related %s to %s", name, rel->name, state->name);
estate = get_state(SMATCH_EXTRA, rel->name, rel->sym);
if (!estate)
continue;
set_extra_nomod_helper(rel->name, rel->sym, expr, clone_estate_cast(estate_type(estate), state));
} END_FOR_EACH_PTR(rel);
--- 361,370 ----
*** 482,491 ****
--- 542,552 ----
static struct sm_state *handle_canonical_while_count_down(struct statement *loop)
{
struct expression *iter_var;
struct expression *condition, *unop;
+ struct symbol *type;
struct sm_state *sm;
struct smatch_state *estate;
int op;
sval_t start, right;
*** 505,514 ****
--- 566,580 ----
if (!sm)
return NULL;
if (sval_cmp(estate_min(sm->state), right) < 0)
return NULL;
start = estate_max(sm->state);
+
+ type = get_type(iter_var);
+ right = sval_cast(type, right);
+ start = sval_cast(type, start);
+
if (sval_cmp(start, right) <= 0)
return NULL;
if (!sval_is_max(start))
start.value--;
*** 538,558 ****
{
struct expression *iter_var;
struct sm_state *sm;
struct smatch_state *estate;
sval_t start, end, max;
iter_var = iter_expr->unop;
sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
if (!sm)
return NULL;
if (!estate_get_single_value(sm->state, &start))
return NULL;
! if (get_implied_max(condition->right, &end))
! end = sval_cast(get_type(iter_var), end);
! else
! end = sval_type_max(get_type(iter_var));
if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
return NULL;
switch (condition->op) {
--- 604,623 ----
{
struct expression *iter_var;
struct sm_state *sm;
struct smatch_state *estate;
sval_t start, end, max;
+ struct symbol *type;
iter_var = iter_expr->unop;
sm = get_sm_state_expr(SMATCH_EXTRA, iter_var);
if (!sm)
return NULL;
if (!estate_get_single_value(sm->state, &start))
return NULL;
! if (!get_implied_value(condition->right, &end))
! return NULL;
if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
return NULL;
switch (condition->op) {
*** 568,584 ****
--- 633,654 ----
default:
return NULL;
}
if (sval_cmp(end, start) < 0)
return NULL;
+ type = get_type(iter_var);
+ start = sval_cast(type, start);
+ end = sval_cast(type, end);
estate = alloc_estate_range(start, end);
if (get_hard_max(condition->right, &max)) {
+ if (!get_macro_name(condition->pos))
estate_set_hard_max(estate);
if (condition->op == '<' ||
condition->op == SPECIAL_UNSIGNED_LT ||
condition->op == SPECIAL_NOTEQUAL)
max.value--;
+ max = sval_cast(type, max);
estate_set_fuzzy_max(estate, max);
}
set_extra_expr_mod(iter_var, estate);
return get_sm_state_expr(SMATCH_EXTRA, iter_var);
}
*** 597,613 ****
return NULL;
if (!estate_get_single_value(sm->state, &start))
return NULL;
if (!get_implied_min(condition->right, &end))
end = sval_type_min(get_type(iter_var));
if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
return NULL;
switch (condition->op) {
case SPECIAL_NOTEQUAL:
case '>':
! if (!sval_is_min(end) && !sval_is_max(end))
end.value++;
break;
case SPECIAL_GTE:
break;
default:
--- 667,684 ----
return NULL;
if (!estate_get_single_value(sm->state, &start))
return NULL;
if (!get_implied_min(condition->right, &end))
end = sval_type_min(get_type(iter_var));
+ end = sval_cast(estate_type(sm->state), end);
if (get_sm_state_expr(SMATCH_EXTRA, condition->left) != sm)
return NULL;
switch (condition->op) {
case SPECIAL_NOTEQUAL:
case '>':
! if (!sval_is_max(end))
end.value++;
break;
case SPECIAL_GTE:
break;
default:
*** 712,721 ****
--- 783,793 ----
sval_type_val(estate_type(sm->state), 1));
} else {
limit = sval_binop(estate_min(sm->state), '-',
sval_type_val(estate_type(sm->state), 1));
}
+ limit = sval_cast(estate_type(sm->state), limit);
if (!estate_has_hard_max(sm->state) && !__has_breaks()) {
if (iter_expr->op == SPECIAL_INCREMENT)
state = alloc_estate_range(estate_min(sm->state), limit);
else
state = alloc_estate_range(limit, estate_max(sm->state));
*** 736,757 ****
--- 808,845 ----
}
set_extra_mod(sm->name, sm->sym, iter_expr, state);
}
+ static bool get_global_rl(const char *name, struct symbol *sym, struct range_list **rl)
+ {
+ struct expression *expr;
+
+ if (!sym || !(sym->ctype.modifiers & MOD_TOPLEVEL) || !sym->ident)
+ return false;
+ if (strcmp(sym->ident->name, name) != 0)
+ return false;
+
+ expr = symbol_expression(sym);
+ return get_implied_rl(expr, rl);
+ }
+
static struct stree *unmatched_stree;
static struct smatch_state *unmatched_state(struct sm_state *sm)
{
struct smatch_state *state;
+ struct range_list *rl;
if (unmatched_stree) {
state = get_state_stree(unmatched_stree, SMATCH_EXTRA, sm->name, sm->sym);
if (state)
return state;
}
if (parent_is_gone_var_sym(sm->name, sm->sym))
return alloc_estate_empty();
+ if (get_global_rl(sm->name, sm->sym, &rl))
+ return alloc_estate_rl(rl);
return alloc_estate_whole(estate_type(sm->state));
}
static void clear_the_pointed_at(struct expression *expr)
{
*** 813,831 ****
else
clear_the_pointed_at(tmp);
} END_FOR_EACH_PTR(arg);
}
! static int values_fit_type(struct expression *left, struct expression *right)
{
struct range_list *rl;
struct symbol *type;
type = get_type(left);
if (!type)
return 0;
get_absolute_rl(right, &rl);
if (type_unsigned(type) && sval_is_negative(rl_min(rl)))
return 0;
if (sval_cmp(sval_type_min(type), rl_min(rl)) > 0)
return 0;
if (sval_cmp(sval_type_max(type), rl_max(rl)) < 0)
--- 901,921 ----
else
clear_the_pointed_at(tmp);
} END_FOR_EACH_PTR(arg);
}
! int values_fit_type(struct expression *left, struct expression *right)
{
struct range_list *rl;
struct symbol *type;
type = get_type(left);
if (!type)
return 0;
get_absolute_rl(right, &rl);
+ if (type == rl_type(rl))
+ return 1;
if (type_unsigned(type) && sval_is_negative(rl_min(rl)))
return 0;
if (sval_cmp(sval_type_min(type), rl_min(rl)) > 0)
return 0;
if (sval_cmp(sval_type_max(type), rl_max(rl)) < 0)
*** 949,959 ****
state = alloc_estate_rl(alloc_whole_rl(left_type));
goto done;
}
! comparison = get_comparison(left, right);
if (comparison) {
comparison = flip_comparison(comparison);
get_implied_rl(left, &orig_rl);
}
--- 1039,1049 ----
state = alloc_estate_rl(alloc_whole_rl(left_type));
goto done;
}
! comparison = get_comparison_no_extra(left, right);
if (comparison) {
comparison = flip_comparison(comparison);
get_implied_rl(left, &orig_rl);
}
*** 978,1027 ****
set_extra_mod(name, sym, left, state);
free:
free_string(right_name);
}
- static int op_remove_assign(int op)
- {
- switch (op) {
- case SPECIAL_ADD_ASSIGN:
- return '+';
- case SPECIAL_SUB_ASSIGN:
- return '-';
- case SPECIAL_MUL_ASSIGN:
- return '*';
- case SPECIAL_DIV_ASSIGN:
- return '/';
- case SPECIAL_MOD_ASSIGN:
- return '%';
- case SPECIAL_AND_ASSIGN:
- return '&';
- case SPECIAL_OR_ASSIGN:
- return '|';
- case SPECIAL_XOR_ASSIGN:
- return '^';
- case SPECIAL_SHL_ASSIGN:
- return SPECIAL_LEFTSHIFT;
- case SPECIAL_SHR_ASSIGN:
- return SPECIAL_RIGHTSHIFT;
- default:
- return op;
- }
- }
-
static void match_assign(struct expression *expr)
{
struct range_list *rl = NULL;
struct expression *left;
struct expression *right;
struct expression *binop_expr;
struct symbol *left_type;
struct symbol *sym;
char *name;
- sval_t left_min, left_max;
- sval_t right_min, right_max;
- sval_t res_min, res_max;
left = strip_expr(expr->left);
right = strip_parens(expr->right);
if (right->type == EXPR_CALL && sym_name_is("__builtin_expect", right->fn))
--- 1068,1086 ----
*** 1042,1090 ****
if (!name)
return;
left_type = get_type(left);
- res_min = sval_type_min(left_type);
- res_max = sval_type_max(left_type);
-
switch (expr->op) {
case SPECIAL_ADD_ASSIGN:
- get_absolute_max(left, &left_max);
- get_absolute_max(right, &right_max);
- if (sval_binop_overflows(left_max, '+', sval_cast(left_type, right_max)))
- break;
- if (get_implied_min(left, &left_min) &&
- !sval_is_negative_min(left_min) &&
- get_implied_min(right, &right_min) &&
- !sval_is_negative_min(right_min)) {
- res_min = sval_binop(left_min, '+', right_min);
- res_min = sval_cast(left_type, res_min);
- }
- if (inside_loop()) /* we are assuming loops don't lead to wrapping */
- break;
- res_max = sval_binop(left_max, '+', right_max);
- res_max = sval_cast(left_type, res_max);
- break;
case SPECIAL_SUB_ASSIGN:
- if (get_implied_max(left, &left_max) &&
- !sval_is_max(left_max) &&
- get_implied_min(right, &right_min) &&
- !sval_is_min(right_min)) {
- res_max = sval_binop(left_max, '-', right_min);
- res_max = sval_cast(left_type, res_max);
- }
- if (inside_loop())
- break;
- if (get_implied_min(left, &left_min) &&
- !sval_is_min(left_min) &&
- get_implied_max(right, &right_max) &&
- !sval_is_max(right_max)) {
- res_min = sval_binop(left_min, '-', right_max);
- res_min = sval_cast(left_type, res_min);
- }
- break;
case SPECIAL_AND_ASSIGN:
case SPECIAL_MOD_ASSIGN:
case SPECIAL_SHL_ASSIGN:
case SPECIAL_SHR_ASSIGN:
case SPECIAL_OR_ASSIGN:
--- 1101,1113 ----
*** 1092,1110 ****
case SPECIAL_MUL_ASSIGN:
case SPECIAL_DIV_ASSIGN:
binop_expr = binop_expression(expr->left,
op_remove_assign(expr->op),
expr->right);
! if (get_absolute_rl(binop_expr, &rl)) {
rl = cast_rl(left_type, rl);
! set_extra_mod(name, sym, left, alloc_estate_rl(rl));
! goto free;
}
- break;
}
- rl = cast_rl(left_type, alloc_rl(res_min, res_max));
set_extra_mod(name, sym, left, alloc_estate_rl(rl));
free:
free_string(name);
}
static struct smatch_state *increment_state(struct smatch_state *state)
--- 1115,1141 ----
case SPECIAL_MUL_ASSIGN:
case SPECIAL_DIV_ASSIGN:
binop_expr = binop_expression(expr->left,
op_remove_assign(expr->op),
expr->right);
! get_absolute_rl(binop_expr, &rl);
rl = cast_rl(left_type, rl);
! if (inside_loop()) {
! if (expr->op == SPECIAL_ADD_ASSIGN)
! add_range(&rl, rl_max(rl), sval_type_max(rl_type(rl)));
!
! if (expr->op == SPECIAL_SUB_ASSIGN &&
! !sval_is_negative(rl_min(rl))) {
! sval_t zero = { .type = rl_type(rl) };
!
! add_range(&rl, rl_min(rl), zero);
}
}
set_extra_mod(name, sym, left, alloc_estate_rl(rl));
+ goto free;
+ }
+ set_extra_mod(name, sym, left, alloc_estate_whole(left_type));
free:
free_string(name);
}
static struct smatch_state *increment_state(struct smatch_state *state)
*** 1232,1242 ****
rl = rl_intersection(estate_rl(state), valid_ptr_rl);
if (rl_equiv(rl, estate_rl(state)))
return;
set_extra_expr_nomod(expr, alloc_estate_rl(rl));
} else {
! set_extra_expr_nomod(expr, alloc_estate_range(valid_ptr_min_sval, valid_ptr_max_sval));
}
}
static void match_dereferences(struct expression *expr)
{
--- 1263,1280 ----
rl = rl_intersection(estate_rl(state), valid_ptr_rl);
if (rl_equiv(rl, estate_rl(state)))
return;
set_extra_expr_nomod(expr, alloc_estate_rl(rl));
} else {
! struct range_list *rl;
!
! if (get_mtag_rl(expr, &rl))
! rl = rl_intersection(rl, valid_ptr_rl);
! else
! rl = clone_rl(valid_ptr_rl);
!
! set_extra_expr_nomod(expr, alloc_estate_rl(rl));
}
}
static void match_dereferences(struct expression *expr)
{
*** 1300,1309 ****
--- 1338,1348 ----
static int handle_postop_inc(struct expression *left, int op, struct expression *right)
{
struct statement *stmt;
struct expression *cond;
struct smatch_state *true_state, *false_state;
+ struct symbol *type;
sval_t start;
sval_t limit;
/*
* If we're decrementing here then that's a canonical while count down
*** 1331,1341 ****
if (!get_implied_value(left->unop, &start))
return 0;
if (!get_implied_value(right, &limit))
return 0;
!
if (sval_cmp(start, limit) > 0)
return 0;
switch (op) {
case '<':
--- 1370,1381 ----
if (!get_implied_value(left->unop, &start))
return 0;
if (!get_implied_value(right, &limit))
return 0;
! type = get_type(left->unop);
! limit = sval_cast(type, limit);
if (sval_cmp(start, limit) > 0)
return 0;
switch (op) {
case '<':
*** 1369,1378 ****
--- 1409,1429 ----
if (state && !estate_rl(state))
return true;
return false;
}
+ static bool in_macro(struct expression *left, struct expression *right)
+ {
+ if (!left || !right)
+ return 0;
+ if (left->pos.line != right->pos.line || left->pos.pos != right->pos.pos)
+ return 0;
+ if (get_macro_name(left->pos))
+ return 1;
+ return 0;
+ }
+
static void handle_comparison(struct symbol *type, struct expression *left, int op, struct expression *right)
{
struct range_list *left_orig;
struct range_list *left_true;
struct range_list *left_false;
*** 1451,1472 ****
switch (op) {
case '<':
case SPECIAL_UNSIGNED_LT:
case SPECIAL_UNSIGNED_LTE:
case SPECIAL_LTE:
! if (get_hard_max(right, &dummy))
estate_set_hard_max(left_true_state);
! if (get_hard_max(left, &dummy))
estate_set_hard_max(right_false_state);
break;
case '>':
case SPECIAL_UNSIGNED_GT:
case SPECIAL_UNSIGNED_GTE:
case SPECIAL_GTE:
! if (get_hard_max(left, &dummy))
estate_set_hard_max(right_true_state);
! if (get_hard_max(right, &dummy))
estate_set_hard_max(left_false_state);
break;
}
switch (op) {
--- 1502,1523 ----
switch (op) {
case '<':
case SPECIAL_UNSIGNED_LT:
case SPECIAL_UNSIGNED_LTE:
case SPECIAL_LTE:
! if (get_implied_value(right, &dummy) && !in_macro(left, right))
estate_set_hard_max(left_true_state);
! if (get_implied_value(left, &dummy) && !in_macro(left, right))
estate_set_hard_max(right_false_state);
break;
case '>':
case SPECIAL_UNSIGNED_GT:
case SPECIAL_UNSIGNED_GTE:
case SPECIAL_GTE:
! if (get_implied_value(left, &dummy) && !in_macro(left, right))
estate_set_hard_max(right_true_state);
! if (get_implied_value(right, &dummy) && !in_macro(left, right))
estate_set_hard_max(left_false_state);
break;
}
switch (op) {
*** 1596,1605 ****
--- 1647,1695 ----
return 1;
}
return 0;
}
+ static int flip_op(int op)
+ {
+ /* We only care about simple math */
+ switch (op) {
+ case '+':
+ return '-';
+ case '-':
+ return '+';
+ case '*':
+ return '/';
+ }
+ return 0;
+ }
+
+ static void move_known_to_rl(struct expression **expr_p, struct range_list **rl_p)
+ {
+ struct expression *expr = *expr_p;
+ struct range_list *rl = *rl_p;
+ sval_t sval;
+
+ if (!is_simple_math(expr))
+ return;
+
+ if (get_implied_value(expr->right, &sval)) {
+ *expr_p = expr->left;
+ *rl_p = rl_binop(rl, flip_op(expr->op), alloc_rl(sval, sval));
+ move_known_to_rl(expr_p, rl_p);
+ return;
+ }
+ if (expr->op == '-')
+ return;
+ if (get_implied_value(expr->left, &sval)) {
+ *expr_p = expr->right;
+ *rl_p = rl_binop(rl, flip_op(expr->op), alloc_rl(sval, sval));
+ move_known_to_rl(expr_p, rl_p);
+ return;
+ }
+ }
+
static void move_known_values(struct expression **left_p, struct expression **right_p)
{
struct expression *left = *left_p;
struct expression *right = *right_p;
sval_t sval, dummy;
*** 1704,1740 ****
static int match_func_comparison(struct expression *expr)
{
struct expression *left = strip_expr(expr->left);
struct expression *right = strip_expr(expr->right);
- sval_t sval;
! /*
! * fixme: think about this harder. We should always be trying to limit
! * the non-call side as well. If we can't determine the limitter does
! * that mean we aren't querying the database and are missing important
! * information?
! */
!
! if (left->type == EXPR_CALL) {
! if (get_implied_value(left, &sval)) {
! handle_comparison(get_type(expr), left, expr->op, right);
! return 1;
! }
function_comparison(left, expr->op, right);
return 1;
}
- if (right->type == EXPR_CALL) {
- if (get_implied_value(right, &sval)) {
- handle_comparison(get_type(expr), left, expr->op, right);
- return 1;
- }
- function_comparison(left, expr->op, right);
- return 1;
- }
-
return 0;
}
/* Handle conditions like "if (foo + bar < foo) {" */
static int handle_integer_overflow_test(struct expression *expr)
--- 1794,1809 ----
static int match_func_comparison(struct expression *expr)
{
struct expression *left = strip_expr(expr->left);
struct expression *right = strip_expr(expr->right);
! if (left->type == EXPR_CALL || right->type == EXPR_CALL) {
function_comparison(left, expr->op, right);
return 1;
}
return 0;
}
/* Handle conditions like "if (foo + bar < foo) {" */
static int handle_integer_overflow_test(struct expression *expr)
*** 1770,1779 ****
--- 1839,1852 ----
get_absolute_min(left->left, &left_min);
get_absolute_min(left->right, &right_min);
min = sval_binop(left_min, '+', right_min);
+ type = get_type(left);
+ min = sval_cast(type, min);
+ max = sval_cast(type, max);
+
set_extra_chunk_true_false(left, NULL, alloc_estate_range(min, max));
return 1;
}
static void match_comparison(struct expression *expr)
*** 1868,1877 ****
--- 1941,1995 ----
}
return ret;
}
+ static bool handle_bit_test(struct expression *expr)
+ {
+ struct range_list *orig_rl, *rl;
+ struct expression *shift, *mask, *var;
+ struct bit_info *bit_info;
+ sval_t sval;
+ sval_t high = { .type = &int_ctype };
+ sval_t low = { .type = &int_ctype };
+
+ shift = strip_expr(expr->right);
+ mask = strip_expr(expr->left);
+ if (shift->type != EXPR_BINOP || shift->op != SPECIAL_LEFTSHIFT) {
+ shift = strip_expr(expr->left);
+ mask = strip_expr(expr->right);
+ if (shift->type != EXPR_BINOP || shift->op != SPECIAL_LEFTSHIFT)
+ return false;
+ }
+ if (!get_implied_value(shift->left, &sval) || sval.value != 1)
+ return false;
+ var = strip_expr(shift->right);
+
+ bit_info = get_bit_info(mask);
+ if (!bit_info)
+ return false;
+ if (!bit_info->possible)
+ return false;
+
+ get_absolute_rl(var, &orig_rl);
+ if (sval_is_negative(rl_min(orig_rl)) ||
+ rl_max(orig_rl).uvalue > type_bits(get_type(shift->left)))
+ return false;
+
+ low.value = ffsll(bit_info->possible);
+ high.value = sm_fls64(bit_info->possible);
+ rl = alloc_rl(low, high);
+ rl = cast_rl(get_type(var), rl);
+ rl = rl_intersection(orig_rl, rl);
+ if (!rl)
+ return false;
+
+ set_extra_expr_true_false(shift->right, alloc_estate_rl(rl), NULL);
+
+ return true;
+ }
+
static void handle_AND_op(struct expression *var, sval_t known)
{
struct range_list *orig_rl;
struct range_list *true_rl = NULL;
struct range_list *false_rl = NULL;
*** 1914,1923 ****
--- 2032,2044 ----
static void handle_AND_condition(struct expression *expr)
{
sval_t known;
+ if (handle_bit_test(expr))
+ return;
+
if (get_implied_value(expr->left, &known))
handle_AND_op(expr->right, known);
else if (get_implied_value(expr->right, &known))
handle_AND_op(expr->left, known);
}
*** 1926,1936 ****
{
struct range_list *orig_rl;
struct range_list *true_rl;
struct range_list *false_rl = NULL;
sval_t right;
! sval_t zero;
if (!get_implied_value(expr->right, &right) || right.value == 0)
return;
get_absolute_rl(expr->left, &orig_rl);
--- 2047,2057 ----
{
struct range_list *orig_rl;
struct range_list *true_rl;
struct range_list *false_rl = NULL;
sval_t right;
! sval_t zero = { 0, };
if (!get_implied_value(expr->right, &right) || right.value == 0)
return;
get_absolute_rl(expr->left, &orig_rl);
*** 1986,2028 ****
}
/* this is actually hooked from smatch_implied.c... it's hacky, yes */
void __extra_match_condition(struct expression *expr)
{
- struct smatch_state *pre_state;
- struct smatch_state *true_state;
- struct smatch_state *false_state;
- struct range_list *pre_rl;
-
expr = strip_expr(expr);
switch (expr->type) {
case EXPR_CALL:
function_comparison(expr, SPECIAL_NOTEQUAL, zero_expr());
return;
case EXPR_PREOP:
case EXPR_SYMBOL:
! case EXPR_DEREF: {
! sval_t zero;
!
! zero = sval_blank(expr);
! zero.value = 0;
!
! pre_state = get_extra_state(expr);
! if (estate_is_empty(pre_state))
return;
- if (pre_state)
- pre_rl = estate_rl(pre_state);
- else
- get_absolute_rl(expr, &pre_rl);
- if (possibly_true_rl(pre_rl, SPECIAL_EQUAL, rl_zero()))
- false_state = alloc_estate_sval(zero);
- else
- false_state = alloc_estate_empty();
- true_state = alloc_estate_rl(remove_range(pre_rl, zero, zero));
- set_extra_expr_true_false(expr, true_state, false_state);
- return;
- }
case EXPR_COMPARE:
match_comparison(expr);
return;
case EXPR_ASSIGNMENT:
__extra_match_condition(expr->left);
--- 2107,2126 ----
}
/* this is actually hooked from smatch_implied.c... it's hacky, yes */
void __extra_match_condition(struct expression *expr)
{
expr = strip_expr(expr);
switch (expr->type) {
case EXPR_CALL:
function_comparison(expr, SPECIAL_NOTEQUAL, zero_expr());
return;
case EXPR_PREOP:
case EXPR_SYMBOL:
! case EXPR_DEREF:
! handle_comparison(get_type(expr), expr, SPECIAL_NOTEQUAL, zero_expr());
return;
case EXPR_COMPARE:
match_comparison(expr);
return;
case EXPR_ASSIGNMENT:
__extra_match_condition(expr->left);
*** 2151,2163 ****
{
*(int *)found = 1;
return 0;
}
! static int filter_unused_kzalloc_info(struct expression *call, int param, char *printed_name, struct sm_state *sm)
{
sval_t sval;
int found = 0;
/* for function pointers assume everything is used */
if (call->fn->type != EXPR_SYMBOL)
return 0;
--- 2249,2297 ----
{
*(int *)found = 1;
return 0;
}
! static int is_kzalloc_info(struct sm_state *sm)
{
sval_t sval;
+
+ /*
+ * kzalloc() information is treated as special because so there is just
+ * a lot of stuff initialized to zero and it makes building the database
+ * take hours and hours.
+ *
+ * In theory, we should just remove this line and not pass any unused
+ * information, but I'm not sure enough that this code works so I want
+ * to hold off on that for now.
+ */
+ if (!estate_get_single_value(sm->state, &sval))
+ return 0;
+ if (sval.value != 0)
+ return 0;
+ return 1;
+ }
+
+ static int is_really_long(struct sm_state *sm)
+ {
+ const char *p;
+ int cnt = 0;
+
+ p = sm->name;
+ while ((p = strstr(p, "->"))) {
+ p += 2;
+ cnt++;
+ }
+
+ if (cnt < 3 ||
+ strlen(sm->name) < 40)
+ return 0;
+ return 1;
+ }
+
+ static int filter_unused_param_value_info(struct expression *call, int param, char *printed_name, struct sm_state *sm)
+ {
int found = 0;
/* for function pointers assume everything is used */
if (call->fn->type != EXPR_SYMBOL)
return 0;
*** 2168,2187 ****
*
*/
if (!call->fn->symbol)
return 0;
! /*
! * kzalloc() information is treated as special because so there is just
! * a lot of stuff initialized to zero and it makes building the database
! * take hours and hours.
! *
! * In theory, we should just remove this line and not pass any unused
! * information, but I'm not sure enough that this code works so I want
! * to hold off on that for now.
! */
! if (!estate_get_single_value(sm->state, &sval) || sval.value != 0)
return 0;
run_sql(¶m_used_callback, &found,
"select * from return_implies where %s and type = %d and parameter = %d and key = '%s';",
get_static_filter(call->fn->symbol), PARAM_USED, param, printed_name);
--- 2302,2312 ----
*
*/
if (!call->fn->symbol)
return 0;
! if (!is_kzalloc_info(sm) && !is_really_long(sm))
return 0;
run_sql(¶m_used_callback, &found,
"select * from return_implies where %s and type = %d and parameter = %d and key = '%s';",
get_static_filter(call->fn->symbol), PARAM_USED, param, printed_name);
*** 2244,2297 ****
}
static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
{
struct range_list *rl;
if (estate_is_whole(sm->state))
return;
! if (filter_unused_kzalloc_info(call, param, printed_name, sm))
return;
rl = estate_rl(sm->state);
rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
if (estate_has_fuzzy_max(sm->state))
sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
sval_to_str(estate_get_fuzzy_max(sm->state)));
}
static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
{
struct symbol *returned_sym;
struct sm_state *sm;
- const char *param_name;
char *compare_str;
! char buf[256];
! returned_sym = expr_to_sym(expr);
! if (!returned_sym)
return;
FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
if (!estate_rl(sm->state))
continue;
if (returned_sym != sm->sym)
continue;
!
! param_name = get_param_name(sm);
! if (!param_name)
continue;
! if (strcmp(param_name, "$") == 0)
continue;
compare_str = name_sym_to_param_comparison(sm->name, sm->sym);
if (!compare_str && estate_is_whole(sm->state))
continue;
! snprintf(buf, sizeof(buf), "%s%s", sm->state->name, compare_str ?: "");
sql_insert_return_states(return_id, return_ranges, PARAM_VALUE,
! -1, param_name, buf);
} END_FOR_EACH_SM(sm);
}
static void db_limited_before(void)
{
unmatched_stree = clone_stree(__get_cur_stree());
--- 2369,2440 ----
}
static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
{
struct range_list *rl;
+ sval_t dummy;
if (estate_is_whole(sm->state))
return;
! if (filter_unused_param_value_info(call, param, printed_name, sm))
return;
rl = estate_rl(sm->state);
rl = intersect_with_real_abs_var_sym(sm->name, sm->sym, rl);
sql_insert_caller_info(call, PARAM_VALUE, param, printed_name, show_rl(rl));
+ if (!estate_get_single_value(sm->state, &dummy)) {
+ if (estate_has_hard_max(sm->state))
+ sql_insert_caller_info(call, HARD_MAX, param, printed_name,
+ sval_to_str(estate_max(sm->state)));
if (estate_has_fuzzy_max(sm->state))
sql_insert_caller_info(call, FUZZY_MAX, param, printed_name,
sval_to_str(estate_get_fuzzy_max(sm->state)));
+ }
}
static void returned_struct_members(int return_id, char *return_ranges, struct expression *expr)
{
struct symbol *returned_sym;
+ char *returned_name;
struct sm_state *sm;
char *compare_str;
! char name_buf[256];
! char val_buf[256];
! int len;
! // FIXME handle *$
!
! if (!is_pointer(expr))
return;
+ returned_name = expr_to_var_sym(expr, &returned_sym);
+ if (!returned_name || !returned_sym)
+ goto free;
+ len = strlen(returned_name);
+
FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
if (!estate_rl(sm->state))
continue;
if (returned_sym != sm->sym)
continue;
! if (strncmp(returned_name, sm->name, len) != 0)
continue;
! if (sm->name[len] != '-')
continue;
+
+ snprintf(name_buf, sizeof(name_buf), "$%s", sm->name + len);
+
compare_str = name_sym_to_param_comparison(sm->name, sm->sym);
if (!compare_str && estate_is_whole(sm->state))
continue;
! snprintf(val_buf, sizeof(val_buf), "%s%s", sm->state->name, compare_str ?: "");
sql_insert_return_states(return_id, return_ranges, PARAM_VALUE,
! -1, name_buf, val_buf);
} END_FOR_EACH_SM(sm);
+
+ free:
+ free_string(returned_name);
}
static void db_limited_before(void)
{
unmatched_stree = clone_stree(__get_cur_stree());
*** 2300,2321 ****
static void db_limited_after(void)
{
free_stree(&unmatched_stree);
}
- static int rl_fits_in_type(struct range_list *rl, struct symbol *type)
- {
- if (type_bits(rl_type(rl)) <= type_bits(type))
- return 1;
- if (sval_cmp(rl_max(rl), sval_type_max(type)) > 0)
- return 0;
- if (sval_is_negative(rl_min(rl)) &&
- sval_cmp(rl_min(rl), sval_type_min(type)) < 0)
- return 0;
- return 1;
- }
-
static int basically_the_same(struct range_list *orig, struct range_list *new)
{
if (rl_equiv(orig, new))
return 1;
--- 2443,2452 ----
*** 2361,2372 ****
struct sm_state *sm;
struct symbol *compare_type, *var_type;
struct range_list *rl;
struct range_list *limit;
struct range_list *new;
! char *tmp_name;
! struct symbol *tmp_sym;
while (expr->type == EXPR_ASSIGNMENT)
expr = strip_expr(expr->right);
if (expr->type != EXPR_CALL)
return;
--- 2492,2503 ----
struct sm_state *sm;
struct symbol *compare_type, *var_type;
struct range_list *rl;
struct range_list *limit;
struct range_list *new;
! char *other_name;
! struct symbol *other_sym;
while (expr->type == EXPR_ASSIGNMENT)
expr = strip_expr(expr->right);
if (expr->type != EXPR_CALL)
return;
*** 2373,2423 ****
arg = get_argument_from_call_expr(expr->args, param);
if (!arg)
return;
name = get_chunk_from_key(arg, key, &sym, &vsl);
if (!name)
return;
if (op != PARAM_LIMIT && !sym)
goto free;
- if (strcmp(key, "$") == 0)
- compare_type = get_arg_type(expr->fn, param);
- else
- compare_type = get_member_type_from_key(arg, key);
-
sm = get_sm_state(SMATCH_EXTRA, name, sym);
if (sm)
rl = estate_rl(sm->state);
else
rl = alloc_whole_rl(compare_type);
if (op == PARAM_LIMIT && !rl_fits_in_type(rl, compare_type))
goto free;
- call_results_to_rl(expr, compare_type, value, &limit);
new = rl_intersection(rl, limit);
var_type = get_member_type_from_key(arg, key);
new = cast_rl(var_type, new);
/* We want to preserve the implications here */
! if (sm && basically_the_same(estate_rl(sm->state), new))
goto free;
! tmp_name = map_long_to_short_name_sym(name, sym, &tmp_sym);
! if (tmp_name && tmp_sym) {
! free_string(name);
! name = tmp_name;
! sym = tmp_sym;
! }
if (op == PARAM_LIMIT)
set_extra_nomod_vsl(name, sym, vsl, NULL, alloc_estate_rl(new));
else
set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
db_param_limit_binops(arg, key, new);
free:
free_string(name);
}
--- 2504,2558 ----
arg = get_argument_from_call_expr(expr->args, param);
if (!arg)
return;
+ if (strcmp(key, "$") == 0)
+ compare_type = get_arg_type(expr->fn, param);
+ else
+ compare_type = get_member_type_from_key(arg, key);
+
+ call_results_to_rl(expr, compare_type, value, &limit);
+ if (strcmp(key, "$") == 0)
+ move_known_to_rl(&arg, &limit);
name = get_chunk_from_key(arg, key, &sym, &vsl);
if (!name)
return;
if (op != PARAM_LIMIT && !sym)
goto free;
sm = get_sm_state(SMATCH_EXTRA, name, sym);
if (sm)
rl = estate_rl(sm->state);
else
rl = alloc_whole_rl(compare_type);
if (op == PARAM_LIMIT && !rl_fits_in_type(rl, compare_type))
goto free;
new = rl_intersection(rl, limit);
var_type = get_member_type_from_key(arg, key);
new = cast_rl(var_type, new);
/* We want to preserve the implications here */
! if (sm && basically_the_same(rl, new))
goto free;
! other_name = get_other_name_sym(name, sym, &other_sym);
if (op == PARAM_LIMIT)
set_extra_nomod_vsl(name, sym, vsl, NULL, alloc_estate_rl(new));
else
set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
+ if (other_name && other_sym) {
+ if (op == PARAM_LIMIT)
+ set_extra_nomod_vsl(other_name, other_sym, vsl, NULL, alloc_estate_rl(new));
+ else
+ set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new));
+ }
+
if (op == PARAM_LIMIT && arg->type == EXPR_BINOP)
db_param_limit_binops(arg, key, new);
free:
free_string(name);
}
*** 2433,2444 ****
}
static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
{
struct expression *arg;
! char *name, *tmp_name;
! struct symbol *sym, *tmp_sym;
struct symbol *param_type, *arg_type;
struct smatch_state *state;
struct range_list *new = NULL;
struct range_list *added = NULL;
--- 2568,2580 ----
}
static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
{
struct expression *arg;
! char *name;
! char *other_name = NULL;
! struct symbol *sym, *other_sym;
struct symbol *param_type, *arg_type;
struct smatch_state *state;
struct range_list *new = NULL;
struct range_list *added = NULL;
*** 2466,2483 ****
if (op == PARAM_SET)
new = added;
else
new = rl_union(new, added);
! tmp_name = map_long_to_short_name_sym_nostack(name, sym, &tmp_sym);
! if (tmp_name && tmp_sym) {
! free_string(name);
! name = tmp_name;
! sym = tmp_sym;
! }
set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
free:
free_string(name);
}
static void db_param_add(struct expression *expr, int param, char *key, char *value)
{
--- 2602,2617 ----
if (op == PARAM_SET)
new = added;
else
new = rl_union(new, added);
! other_name = get_other_name_sym_nostack(name, sym, &other_sym);
set_extra_mod(name, sym, NULL, alloc_estate_rl(new));
+ if (other_name && other_sym)
+ set_extra_mod(other_name, other_sym, NULL, alloc_estate_rl(new));
free:
+ free_string(other_name);
free_string(name);
}
static void db_param_add(struct expression *expr, int param, char *key, char *value)
{
*** 2491,2500 ****
--- 2625,2652 ----
in_param_set = true;
db_param_add_set(expr, param, key, value, PARAM_SET);
in_param_set = false;
}
+ static void match_lost_param(struct expression *call, int param)
+ {
+ struct expression *arg;
+
+ if (is_const_param(call->fn, param))
+ return;
+
+ arg = get_argument_from_call_expr(call->args, param);
+ if (!arg)
+ return;
+
+ arg = strip_expr(arg);
+ if (arg->type == EXPR_PREOP && arg->op == '&')
+ set_extra_expr_mod(arg->unop, alloc_estate_whole(get_type(arg->unop)));
+ else
+ ; /* if pointer then set struct members, maybe?*/
+ }
+
static void db_param_value(struct expression *expr, int param, char *key, char *value)
{
struct expression *call;
char *name;
struct symbol *sym;
*** 2526,2535 ****
--- 2678,2688 ----
{
struct smatch_state *state;
struct range_list *rl = NULL;
struct expression *arg;
struct symbol *type;
+ sval_t dummy;
int i = 0;
FOR_EACH_PTR(expr->args, arg) {
type = get_arg_type(expr->fn, i);
*** 2539,2548 ****
--- 2692,2705 ----
if (!is_whole_rl(rl)) {
rl = intersect_with_real_abs_expr(arg, rl);
sql_insert_caller_info(expr, PARAM_VALUE, i, "$", show_rl(rl));
}
state = get_state_expr(SMATCH_EXTRA, arg);
+ if (!estate_get_single_value(state, &dummy) && estate_has_hard_max(state)) {
+ sql_insert_caller_info(expr, HARD_MAX, i, "$",
+ sval_to_str(estate_max(state)));
+ }
if (estate_has_fuzzy_max(state)) {
sql_insert_caller_info(expr, FUZZY_MAX, i, "$",
sval_to_str(estate_get_fuzzy_max(state)));
}
i++;
*** 2549,2580 ****
} END_FOR_EACH_PTR(arg);
}
static void set_param_value(const char *name, struct symbol *sym, char *key, char *value)
{
struct range_list *rl = NULL;
struct smatch_state *state;
struct symbol *type;
char fullname[256];
sval_t dummy;
! if (strcmp(key, "*$") == 0)
! snprintf(fullname, sizeof(fullname), "*%s", name);
! else if (strncmp(key, "$", 1) == 0)
! snprintf(fullname, 256, "%s%s", name, key + 1);
! else
! return;
! type = get_member_type_from_key(symbol_expression(sym), key);
str_to_rl(type, value, &rl);
state = alloc_estate_rl(rl);
if (estate_get_single_value(state, &dummy))
estate_set_hard_max(state);
set_state(SMATCH_EXTRA, fullname, sym, state);
}
! static void set_param_hard_max(const char *name, struct symbol *sym, char *key, char *value)
{
struct range_list *rl = NULL;
struct smatch_state *state;
struct symbol *type;
char fullname[256];
--- 2706,2741 ----
} END_FOR_EACH_PTR(arg);
}
static void set_param_value(const char *name, struct symbol *sym, char *key, char *value)
{
+ struct expression *expr;
struct range_list *rl = NULL;
struct smatch_state *state;
struct symbol *type;
char fullname[256];
+ char *key_orig = key;
+ bool add_star = false;
sval_t dummy;
! if (key[0] == '*') {
! add_star = true;
! key++;
! }
! snprintf(fullname, 256, "%s%s%s", add_star ? "*" : "", name, key + 1);
!
! expr = symbol_expression(sym);
! type = get_member_type_from_key(expr, key_orig);
str_to_rl(type, value, &rl);
state = alloc_estate_rl(rl);
if (estate_get_single_value(state, &dummy))
estate_set_hard_max(state);
set_state(SMATCH_EXTRA, fullname, sym, state);
}
! static void set_param_fuzzy_max(const char *name, struct symbol *sym, char *key, char *value)
{
struct range_list *rl = NULL;
struct smatch_state *state;
struct symbol *type;
char fullname[256];
*** 2588,2604 ****
return;
state = get_state(SMATCH_EXTRA, fullname, sym);
if (!state)
return;
! type = get_member_type_from_key(symbol_expression(sym), key);
str_to_rl(type, value, &rl);
if (!rl_to_sval(rl, &max))
return;
estate_set_fuzzy_max(state, max);
}
struct sm_state *get_extra_sm_state(struct expression *expr)
{
char *name;
struct symbol *sym;
struct sm_state *ret = NULL;
--- 2749,2783 ----
return;
state = get_state(SMATCH_EXTRA, fullname, sym);
if (!state)
return;
! type = estate_type(state);
str_to_rl(type, value, &rl);
if (!rl_to_sval(rl, &max))
return;
estate_set_fuzzy_max(state, max);
}
+ static void set_param_hard_max(const char *name, struct symbol *sym, char *key, char *value)
+ {
+ struct smatch_state *state;
+ char fullname[256];
+
+ if (strcmp(key, "*$") == 0)
+ snprintf(fullname, sizeof(fullname), "*%s", name);
+ else if (strncmp(key, "$", 1) == 0)
+ snprintf(fullname, 256, "%s%s", name, key + 1);
+ else
+ return;
+
+ state = get_state(SMATCH_EXTRA, fullname, sym);
+ if (!state)
+ return;
+ estate_set_hard_max(state);
+ }
+
struct sm_state *get_extra_sm_state(struct expression *expr)
{
char *name;
struct symbol *sym;
struct sm_state *ret = NULL;
*** 2625,2643 ****
void register_smatch_extra(int id)
{
my_id = id;
add_merge_hook(my_id, &merge_estates);
add_unmatched_state_hook(my_id, &unmatched_state);
select_caller_info_hook(set_param_value, PARAM_VALUE);
! select_caller_info_hook(set_param_hard_max, FUZZY_MAX);
select_return_states_before(&db_limited_before);
select_return_states_hook(PARAM_LIMIT, &db_param_limit);
select_return_states_hook(PARAM_FILTER, &db_param_filter);
select_return_states_hook(PARAM_ADD, &db_param_add);
select_return_states_hook(PARAM_SET, &db_param_set);
select_return_states_hook(PARAM_VALUE, &db_param_value);
select_return_states_after(&db_limited_after);
}
static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
--- 2804,2825 ----
void register_smatch_extra(int id)
{
my_id = id;
+ set_dynamic_states(my_id);
add_merge_hook(my_id, &merge_estates);
add_unmatched_state_hook(my_id, &unmatched_state);
select_caller_info_hook(set_param_value, PARAM_VALUE);
! select_caller_info_hook(set_param_fuzzy_max, FUZZY_MAX);
! select_caller_info_hook(set_param_hard_max, HARD_MAX);
select_return_states_before(&db_limited_before);
select_return_states_hook(PARAM_LIMIT, &db_param_limit);
select_return_states_hook(PARAM_FILTER, &db_param_filter);
select_return_states_hook(PARAM_ADD, &db_param_add);
select_return_states_hook(PARAM_SET, &db_param_set);
+ add_lost_param_hook(&match_lost_param);
select_return_states_hook(PARAM_VALUE, &db_param_value);
select_return_states_after(&db_limited_after);
}
static void match_link_modify(struct sm_state *sm, struct expression *mod_expr)
*** 2661,2670 ****
--- 2843,2853 ----
}
void register_smatch_extra_links(int id)
{
link_id = id;
+ set_dynamic_states(link_id);
}
void register_smatch_extra_late(int id)
{
add_merge_hook(link_id, &merge_link_states);