Print this page
11506 smatch resync
*** 639,649 ****
new_state = alloc_link_state(links);
set_state(link_id, var, sym, new_state);
}
! static void match_inc(struct sm_state *sm)
{
struct string_list *links;
struct smatch_state *state, *new;
struct compare_data *data;
char *tmp;
--- 639,649 ----
new_state = alloc_link_state(links);
set_state(link_id, var, sym, new_state);
}
! static void match_inc(struct sm_state *sm, bool preserve)
{
struct string_list *links;
struct smatch_state *state, *new;
struct compare_data *data;
char *tmp;
*** 671,680 ****
--- 671,682 ----
case SPECIAL_EQUAL:
case SPECIAL_GTE:
case SPECIAL_UNSIGNED_GTE:
case '>':
case SPECIAL_UNSIGNED_GT:
+ if (preserve)
+ break;
new = alloc_compare_state(
data->left, data->left_var, data->left_vsl,
flip ? '<' : '>',
data->right, data->right_var, data->right_vsl);
set_state(compare_id, tmp, NULL, new);
*** 691,701 ****
set_state(compare_id, tmp, NULL, &undefined);
}
} END_FOR_EACH_PTR(tmp);
}
! static void match_dec(struct sm_state *sm)
{
struct string_list *links;
struct smatch_state *state;
char *tmp;
--- 693,703 ----
set_state(compare_id, tmp, NULL, &undefined);
}
} END_FOR_EACH_PTR(tmp);
}
! static void match_dec(struct sm_state *sm, bool preserve)
{
struct string_list *links;
struct smatch_state *state;
char *tmp;
*** 711,720 ****
--- 713,725 ----
case '<':
case SPECIAL_UNSIGNED_LT: {
struct compare_data *data = state->data;
struct smatch_state *new;
+ if (preserve)
+ break;
+
new = alloc_compare_state(
data->left, data->left_var, data->left_vsl,
'<',
data->right, data->right_var, data->right_vsl);
set_state(compare_id, tmp, NULL, new);
*** 724,747 ****
set_state(compare_id, tmp, NULL, &undefined);
}
} END_FOR_EACH_PTR(tmp);
}
static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr)
{
/*
* if (foo > bar) then ++foo is also > bar.
*/
if (!mod_expr)
return;
if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP)
return;
if (mod_expr->op == SPECIAL_INCREMENT)
! match_inc(sm);
else if (mod_expr->op == SPECIAL_DECREMENT)
! match_dec(sm);
}
static int is_self_assign(struct expression *expr)
{
if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
--- 729,790 ----
set_state(compare_id, tmp, NULL, &undefined);
}
} END_FOR_EACH_PTR(tmp);
}
+ static void reset_sm(struct sm_state *sm)
+ {
+ struct string_list *links;
+ char *tmp;
+
+ links = sm->state->data;
+
+ FOR_EACH_PTR(links, tmp) {
+ set_state(compare_id, tmp, NULL, &undefined);
+ } END_FOR_EACH_PTR(tmp);
+ set_state(link_id, sm->name, sm->sym, &undefined);
+ }
+
+ static bool match_add_sub_assign(struct sm_state *sm, struct expression *expr)
+ {
+ struct range_list *rl;
+ sval_t zero = { .type = &int_ctype };
+
+ if (!expr || expr->type != EXPR_ASSIGNMENT)
+ return false;
+ if (expr->op != SPECIAL_ADD_ASSIGN && expr->op != SPECIAL_SUB_ASSIGN)
+ return false;
+
+ get_absolute_rl(expr->right, &rl);
+ if (sval_is_negative(rl_min(rl))) {
+ reset_sm(sm);
+ return false;
+ }
+
+ if (expr->op == SPECIAL_ADD_ASSIGN)
+ match_inc(sm, rl_has_sval(rl, zero));
+ else
+ match_dec(sm, rl_has_sval(rl, zero));
+ return true;
+ }
+
static void match_inc_dec(struct sm_state *sm, struct expression *mod_expr)
{
/*
* if (foo > bar) then ++foo is also > bar.
*/
if (!mod_expr)
return;
+ if (match_add_sub_assign(sm, mod_expr))
+ return;
if (mod_expr->type != EXPR_PREOP && mod_expr->type != EXPR_POSTOP)
return;
if (mod_expr->op == SPECIAL_INCREMENT)
! match_inc(sm, false);
else if (mod_expr->op == SPECIAL_DECREMENT)
! match_dec(sm, false);
}
static int is_self_assign(struct expression *expr)
{
if (!expr || expr->type != EXPR_ASSIGNMENT || expr->op != '=')
*** 749,776 ****
return expr_equiv(expr->left, expr->right);
}
static void match_modify(struct sm_state *sm, struct expression *mod_expr)
{
- struct string_list *links;
- char *tmp;
-
if (mod_expr && is_self_assign(mod_expr))
return;
/* handled by match_inc_dec() */
if (mod_expr &&
((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) &&
(mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT)))
return;
! links = sm->state->data;
!
! FOR_EACH_PTR(links, tmp) {
! set_state(compare_id, tmp, NULL, &undefined);
! } END_FOR_EACH_PTR(tmp);
! set_state(link_id, sm->name, sm->sym, &undefined);
}
static void match_preop(struct expression *expr)
{
struct expression *parent;
--- 792,814 ----
return expr_equiv(expr->left, expr->right);
}
static void match_modify(struct sm_state *sm, struct expression *mod_expr)
{
if (mod_expr && is_self_assign(mod_expr))
return;
/* handled by match_inc_dec() */
if (mod_expr &&
((mod_expr->type == EXPR_PREOP || mod_expr->type == EXPR_POSTOP) &&
(mod_expr->op == SPECIAL_INCREMENT || mod_expr->op == SPECIAL_DECREMENT)))
return;
+ if (mod_expr && mod_expr->type == EXPR_ASSIGNMENT &&
+ (mod_expr->op == SPECIAL_ADD_ASSIGN || mod_expr->op == SPECIAL_SUB_ASSIGN))
+ return;
! reset_sm(sm);
}
static void match_preop(struct expression *expr)
{
struct expression *parent;
*** 1602,1612 ****
ret = flip_comparison(ret);
return ret;
}
! int get_comparison(struct expression *a, struct expression *b)
{
char *one = NULL;
char *two = NULL;
int ret = 0;
--- 1640,1650 ----
ret = flip_comparison(ret);
return ret;
}
! static int get_comparison_helper(struct expression *a, struct expression *b, bool use_extra)
{
char *one = NULL;
char *two = NULL;
int ret = 0;
*** 1651,1665 ****
free:
free_string(one);
free_string(two);
! if (!ret)
return comparison_from_extra(a, b);
return ret;
}
int possible_comparison(struct expression *a, int comparison, struct expression *b)
{
char *one = NULL;
char *two = NULL;
int ret = 0;
--- 1689,1713 ----
free:
free_string(one);
free_string(two);
! if (!ret && use_extra)
return comparison_from_extra(a, b);
return ret;
}
+ int get_comparison(struct expression *a, struct expression *b)
+ {
+ return get_comparison_helper(a, b, true);
+ }
+
+ int get_comparison_no_extra(struct expression *a, struct expression *b)
+ {
+ return get_comparison_helper(a, b, false);
+ }
+
int possible_comparison(struct expression *a, int comparison, struct expression *b)
{
char *one = NULL;
char *two = NULL;
int ret = 0;
*** 2325,2335 ****
char *p;
if (!parse_comparison(&value, op))
return 0;
! snprintf(buf, sizeof(buf), value);
p = buf;
if (*p++ != '$')
return 0;
--- 2373,2383 ----
char *p;
if (!parse_comparison(&value, op))
return 0;
! snprintf(buf, sizeof(buf), "%s", value);
p = buf;
if (*p++ != '$')
return 0;
*** 2493,2502 ****
--- 2541,2551 ----
}
void register_comparison(int id)
{
compare_id = id;
+ set_dynamic_states(compare_id);
add_hook(&save_start_states, AFTER_DEF_HOOK);
add_unmatched_state_hook(compare_id, unmatched_comparison);
add_pre_merge_hook(compare_id, &pre_merge_hook);
add_merge_hook(compare_id, &merge_compare_states);
add_hook(&free_data, AFTER_FUNC_HOOK);
*** 2513,2522 ****
--- 2562,2573 ----
}
void register_comparison_links(int id)
{
link_id = id;
+ db_ignore_states(link_id);
+ set_dynamic_states(link_id);
add_merge_hook(link_id, &merge_links);
add_modification_hook(link_id, &match_modify);
add_modification_hook_late(link_id, match_inc_dec);
add_member_info_callback(link_id, struct_member_callback);
*** 2529,2538 ****
--- 2580,2590 ----
}
void register_comparison_inc_dec_links(int id)
{
inc_dec_link_id = id;
+ set_dynamic_states(inc_dec_link_id);
set_up_link_functions(inc_dec_id, inc_dec_link_id);
}
static void filter_by_sm(struct sm_state *sm, int op,
struct state_list **true_stack,