Print this page
new smatch
*** 97,112 ****
void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
}
static bool in_param_set;
void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
remove_from_equiv(name, sym);
call_extra_mod_hooks(name, sym, expr, state);
! if ((__in_fake_assign || in_param_set) &&
estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
return;
set_state(SMATCH_EXTRA, name, sym, state);
}
--- 97,186 ----
void call_extra_nomod_hooks(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
call_extra_hooks(extra_nomod_hooks, name, sym, expr, state);
}
+ static void set_union_info(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
+ {
+ struct symbol *type, *tmp, *inner_type, *inner, *new_type;
+ struct expression *deref, *member_expr;
+ struct smatch_state *new;
+ int offset, inner_offset;
+ static bool in_recurse;
+ char *member_name;
+
+ if (__in_fake_assign)
+ return;
+
+ if (in_recurse)
+ return;
+ in_recurse = true;
+
+ if (!expr || expr->type != EXPR_DEREF || !expr->member)
+ goto done;
+ offset = get_member_offset_from_deref(expr);
+ if (offset < 0)
+ goto done;
+
+ deref = strip_expr(expr->deref);
+ type = get_type(deref);
+ if (type_is_ptr(type))
+ type = get_real_base_type(type);
+ if (!type || type->type != SYM_STRUCT)
+ goto done;
+
+ FOR_EACH_PTR(type->symbol_list, tmp) {
+ inner_type = get_real_base_type(tmp);
+ if (!inner_type || inner_type->type != SYM_UNION)
+ continue;
+
+ inner = first_ptr_list((struct ptr_list *)inner_type->symbol_list);
+ if (!inner || !inner->ident)
+ continue;
+
+ inner_offset = get_member_offset(type, inner->ident->name);
+ if (inner_offset < offset)
+ continue;
+ if (inner_offset > offset)
+ goto done;
+
+ FOR_EACH_PTR(inner_type->symbol_list, inner) {
+ struct symbol *tmp_type;
+
+ if (!inner->ident || inner->ident == expr->member)
+ continue;
+ tmp_type = get_real_base_type(inner);
+ if (tmp_type && tmp_type->type == SYM_STRUCT)
+ continue;
+ member_expr = deref;
+ if (tmp->ident)
+ member_expr = member_expression(member_expr, '.', tmp->ident);
+ member_expr = member_expression(member_expr, expr->op, inner->ident);
+ member_name = expr_to_var(member_expr);
+ if (!member_name)
+ continue;
+ new_type = get_real_base_type(inner);
+ new = alloc_estate_rl(cast_rl(new_type, estate_rl(state)));
+ set_extra_mod_helper(member_name, sym, member_expr, new);
+ free_string(member_name);
+ } END_FOR_EACH_PTR(inner);
+ } END_FOR_EACH_PTR(tmp);
+
+ done:
+ in_recurse = false;
+ }
+
static bool in_param_set;
void set_extra_mod_helper(const char *name, struct symbol *sym, struct expression *expr, struct smatch_state *state)
{
+ if (!expr)
+ expr = gen_expression_from_name_sym(name, sym);
remove_from_equiv(name, sym);
+ set_union_info(name, sym, expr, state);
call_extra_mod_hooks(name, sym, expr, state);
! update_mtag_data(expr, state);
! if (in_param_set &&
estate_is_unknown(state) && !get_state(SMATCH_EXTRA, name, sym))
return;
set_state(SMATCH_EXTRA, name, sym, state);
}
*** 170,180 ****
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];
--- 244,254 ----
free:
free_string(orig_name);
return NULL;
}
! static char *get_long_name_sym(const char *name, struct symbol *sym, struct symbol **new_sym, bool use_stack)
{
struct expression *tmp;
struct sm_state *sm;
char buf[256];
*** 194,203 ****
--- 268,279 ----
} END_FOR_EACH_SM(sm);
return NULL;
found:
+ if (!use_stack && name[tmp->symbol->ident->len] != '-')
+ return NULL;
snprintf(buf, sizeof(buf), "%s%s", sm->name, name + tmp->symbol->ident->len);
*new_sym = sm->sym;
return alloc_string(buf);
}
*** 222,232 ****
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)
--- 298,308 ----
len = snprintf(buf, sizeof(buf), "%s", name);
if (len >= sizeof(buf) - 2)
return NULL;
! while (use_stack && 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)
*** 233,243 ****
return ret;
}
len--;
}
! ret = get_long_name_sym(name, sym, new_sym);
if (ret)
return ret;
return NULL;
}
--- 309,319 ----
return ret;
}
len--;
}
! ret = get_long_name_sym(name, sym, new_sym, use_stack);
if (ret)
return ret;
return NULL;
}
*** 256,268 ****
{
char *new_name;
struct symbol *new_sym;
set_extra_mod_helper(name, sym, expr, state);
! new_name = get_other_name_sym(name, sym, &new_sym);
if (new_name && new_sym)
! set_extra_mod_helper(new_name, new_sym, expr, state);
free_string(new_name);
}
static struct expression *chunk_get_array_base(struct expression *expr)
{
--- 332,344 ----
{
char *new_name;
struct symbol *new_sym;
set_extra_mod_helper(name, sym, expr, state);
! new_name = get_other_name_sym_nostack(name, sym, &new_sym);
if (new_name && new_sym)
! set_extra_mod_helper(new_name, new_sym, NULL, state);
free_string(new_name);
}
static struct expression *chunk_get_array_base(struct expression *expr)
{
*** 1229,1252 ****
static void asm_expr(struct statement *stmt)
{
struct expression *expr;
struct symbol *type;
- int state = 0;
FOR_EACH_PTR(stmt->asm_outputs, expr) {
! switch (state) {
! case 0: /* identifier */
! case 1: /* constraint */
! state++;
continue;
- case 2: /* expression */
- state = 0;
- type = get_type(strip_expr(expr));
- set_extra_expr_mod(expr, alloc_estate_whole(type));
- continue;
}
} END_FOR_EACH_PTR(expr);
}
static void check_dereference(struct expression *expr)
{
--- 1305,1322 ----
static void asm_expr(struct statement *stmt)
{
struct expression *expr;
struct symbol *type;
FOR_EACH_PTR(stmt->asm_outputs, expr) {
! if (expr->type != EXPR_ASM_OPERAND) {
! sm_perror("unexpected asm param type %d", expr->type);
continue;
}
+ type = get_type(strip_expr(expr->expr));
+ set_extra_expr_mod(expr->expr, alloc_estate_whole(type));
} END_FOR_EACH_PTR(expr);
}
static void check_dereference(struct expression *expr)
{
*** 1278,1287 ****
--- 1348,1359 ----
static void match_dereferences(struct expression *expr)
{
if (expr->type != EXPR_PREOP)
return;
+ if (getting_address(expr))
+ return;
/* it's saying that foo[1] = bar dereferences foo[1] */
if (is_array(expr))
return;
check_dereference(expr->unop);
}
*** 2201,2211 ****
buf[sizeof(buf) - 1] = '\0';
start = &buf[0];
while (*start == '*') {
start++;
! state = get_state(SMATCH_EXTRA, start, sym);
if (!state)
continue;
if (!estate_rl(state))
return 1;
if (estate_min(state).value == 0 &&
--- 2273,2283 ----
buf[sizeof(buf) - 1] = '\0';
start = &buf[0];
while (*start == '*') {
start++;
! state = __get_state(SMATCH_EXTRA, start, sym);
if (!state)
continue;
if (!estate_rl(state))
return 1;
if (estate_min(state).value == 0 &&
*** 2371,2386 ****
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)));
--- 2443,2460 ----
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) || !estate_rl(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);
+ if (!rl)
+ return;
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)));
*** 2567,2577 ****
db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
}
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;
--- 2641,2651 ----
db_param_limit_filter(expr, param, key, value, PARAM_FILTER);
}
static void db_param_add_set(struct expression *expr, int param, char *key, char *value, enum info_type op)
{
! struct expression *arg, *gen_expr;
char *name;
char *other_name = NULL;
struct symbol *sym, *other_sym;
struct symbol *param_type, *arg_type;
struct smatch_state *state;
*** 2587,2599 ****
--- 2661,2676 ----
if (!arg)
return;
arg_type = get_arg_type_from_key(expr->fn, param, arg, key);
param_type = get_member_type_from_key(arg, key);
+ if (param_type && param_type->type == SYM_STRUCT)
+ return;
name = get_variable_from_key(arg, key, &sym);
if (!name || !sym)
goto free;
+ gen_expr = gen_expression_from_key(arg, key);
state = get_state(SMATCH_EXTRA, name, sym);
if (state)
new = estate_rl(state);
*** 2603,2615 ****
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);
}
--- 2680,2692 ----
new = added;
else
new = rl_union(new, added);
other_name = get_other_name_sym_nostack(name, sym, &other_sym);
! set_extra_mod(name, sym, gen_expr, alloc_estate_rl(new));
if (other_name && other_sym)
! set_extra_mod(other_name, other_sym, gen_expr, alloc_estate_rl(new));
free:
free_string(other_name);
free_string(name);
}