Print this page
new smatch
@@ -371,11 +371,11 @@
{
db_info->ret_str = alloc_sname(ret_str),
db_info->ret_state = state;
}
-static bool fake_a_param_assignment(struct expression *expr, const char *return_str)
+static bool fake_a_param_assignment(struct expression *expr, const char *return_str, struct smatch_state *orig)
{
struct expression *arg, *left, *right, *tmp, *fake_assign;
char *p;
int param;
char buf[256];
@@ -435,10 +435,30 @@
return false;
fake_assign = assign_expression(left, '=', right);
__in_fake_parameter_assign++;
__split_expr(fake_assign);
__in_fake_parameter_assign--;
+
+ /*
+ * If the return is "0-65531[$0->nla_len - 4]" the faked expression
+ * is maybe (-4)-65531 but we know it is in the 0-65531 range so both
+ * parts have to be considered. We use _nomod() because it's not really
+ * another modification, it's just a clarification.
+ *
+ */
+ if (estate_rl(orig)) {
+ struct smatch_state *faked;
+ struct range_list *rl;
+
+ faked = get_extra_state(left);
+ if (estate_rl(faked)) {
+ rl = rl_intersection(estate_rl(faked), estate_rl(orig));
+ if (rl)
+ set_extra_expr_nomod(expr, alloc_estate_rl(rl));
+ }
+ }
+
return true;
}
static void set_return_assign_state(struct db_callback_info *db_info)
{
@@ -447,13 +467,14 @@
if (!db_info->ret_state)
return;
state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
+ if (!fake_a_param_assignment(db_info->expr, db_info->ret_str, state))
set_extra_expr_mod(expr, state);
+
db_info->ret_state = NULL;
- fake_a_param_assignment(db_info->expr, db_info->ret_str);
db_info->ret_str = NULL;
}
static void set_other_side_state(struct db_callback_info *db_info)
{
@@ -1090,11 +1111,10 @@
set_state(-1, "unnull_path", NULL, &true_state);
__add_return_comparison(strip_expr(db_info->expr), ret_str);
__add_return_to_param_mapping(db_info->expr, ret_str);
}
-
FOR_EACH_PTR(db_return_states_list, tmp) {
if (tmp->type == type)
tmp->callback(db_info->expr, param, key, value);
} END_FOR_EACH_PTR(tmp);
@@ -1168,16 +1188,18 @@
}
static void match_function_call(struct expression *expr)
{
struct call_back_list *call_backs;
+ struct expression *fn;
- if (expr->fn->type == EXPR_SYMBOL && expr->fn->symbol) {
- call_backs = search_callback(func_hash, (char *)expr->fn->symbol->ident->name);
+ fn = strip_expr(expr->fn);
+ if (fn->type == EXPR_SYMBOL && fn->symbol) {
+ call_backs = search_callback(func_hash, (char *)fn->symbol->ident->name);
if (call_backs)
call_call_backs(call_backs, REGULAR_CALL,
- expr->fn->symbol->ident->name, expr);
+ fn->symbol->ident->name, expr);
}
db_return_states_call(expr);
}
static void match_macro_assign(struct expression *expr)