Print this page
11972 resync smatch
@@ -506,34 +506,36 @@
}
void sql_select_return_states(const char *cols, struct expression *call,
int (*callback)(void*, int, char**, char**), void *info)
{
+ struct expression *fn;
int row_count = 0;
if (is_fake_call(call))
return;
- if (call->fn->type != EXPR_SYMBOL || !call->fn->symbol || is_local_symbol(call->fn)) {
+ fn = strip_expr(call->fn);
+ if (fn->type != EXPR_SYMBOL || !fn->symbol || is_local_symbol(fn)) {
sql_select_return_states_pointer(cols, call, callback, info);
return;
}
- if (inlinable(call->fn)) {
+ if (inlinable(fn)) {
mem_sql(callback, info,
"select %s from return_states where call_id = '%lu' order by return_id, type;",
cols, (unsigned long)call);
return;
}
run_sql(get_row_count, &row_count, "select count(*) from return_states where %s;",
- get_static_filter(call->fn->symbol));
+ get_static_filter(fn->symbol));
if (row_count > 3000)
return;
run_sql(callback, info, "select %s from return_states where %s order by file, return_id, type;",
- cols, get_static_filter(call->fn->symbol));
+ cols, get_static_filter(fn->symbol));
}
#define CALL_IMPLIES 0
#define RETURN_IMPLIES 1
@@ -716,10 +718,37 @@
"select distinct return from return_states where function = '%s';",
fn_name);
return ret_info.return_range_list;
}
+/*
+ * This is used when we have a function that takes a function pointer as a
+ * parameter. "frob(blah, blah, my_function);" We know that the return values
+ * from frob() come from my_funcion() so we want to find the possible returns
+ * of my_function(), but we don't know which arguments are passed to it.
+ *
+ */
+struct range_list *db_return_vals_no_args(struct expression *expr)
+{
+ struct return_info ret_info = {};
+
+ if (!expr || expr->type != EXPR_SYMBOL)
+ return NULL;
+
+ ret_info.static_returns_call = expr;
+ ret_info.return_type = get_type(expr);
+ ret_info.return_type = get_real_base_type(ret_info.return_type);
+ if (!ret_info.return_type)
+ return NULL;
+
+ run_sql(db_return_callback, &ret_info,
+ "select distinct return from return_states where %s;",
+ get_static_filter(expr->symbol));
+
+ return ret_info.return_range_list;
+}
+
static void match_call_marker(struct expression *expr)
{
struct symbol *type;
type = get_type(expr->fn);
@@ -1104,12 +1133,11 @@
get_ptr_names(NULL, sym->ident->name);
if (ptr_list_size((struct ptr_list *)ptr_names) > 20) {
__free_ptr_list((struct ptr_list **)&ptr_names);
__free_ptr_list((struct ptr_list **)&ptr_names_done);
- stree = __pop_fake_cur_stree();
- free_stree(&stree);
+ __free_fake_cur_stree();
return;
}
sql_select_caller_info(&data,
"call_id, type, parameter, key, value",
@@ -1122,10 +1150,11 @@
free_stree(&stree);
__push_fake_cur_stree();
__unnullify_path();
data.prev_func_id = -1;
data.ignore = 0;
+ data.results = 0;
FOR_EACH_PTR(ptr_names, ptr) {
run_sql(caller_info_callback, &data,
"select call_id, type, parameter, key, value"
" from common_caller_info where function = '%s' order by call_id",
@@ -1259,10 +1288,33 @@
info.sym = sym;
sql_select_implies("function, type, parameter, key, value", &info,
call_implies_callbacks);
}
+static char *get_fn_param_str(struct expression *expr)
+{
+ struct expression *tmp;
+ int param;
+ char buf[32];
+
+ tmp = get_assigned_expr(expr);
+ if (tmp)
+ expr = tmp;
+ expr = strip_expr(expr);
+ if (!expr || expr->type != EXPR_CALL)
+ return NULL;
+ expr = strip_expr(expr->fn);
+ if (!expr || expr->type != EXPR_SYMBOL)
+ return NULL;
+ param = get_param_num(expr);
+ if (param < 0)
+ return NULL;
+
+ snprintf(buf, sizeof(buf), "[r $%d]", param);
+ return alloc_sname(buf);
+}
+
static char *get_return_compare_is_param(struct expression *expr)
{
char *var;
char buf[256];
int comparison;
@@ -1304,10 +1356,11 @@
static const char *get_return_ranges_str(struct expression *expr, struct range_list **rl_p)
{
struct range_list *rl;
char *return_ranges;
sval_t sval;
+ char *fn_param_str;
char *compare_str;
char *math_str;
char buf[128];
*rl_p = NULL;
@@ -1319,10 +1372,11 @@
sval = sval_cast(cur_func_return_type(), sval);
*rl_p = alloc_rl(sval, sval);
return sval_to_str_or_err_ptr(sval);
}
+ fn_param_str = get_fn_param_str(expr);
compare_str = expr_equal_to_param(expr, -1);
math_str = get_value_in_terms_of_parameter_math(expr);
if (get_implied_rl(expr, &rl) && !is_whole_rl(rl)) {
rl = cast_rl(cur_func_return_type(), rl);
@@ -1335,10 +1389,14 @@
rl = cast_rl(cur_func_return_type(), rl);
return_ranges = show_rl(rl);
}
*rl_p = rl;
+ if (fn_param_str) {
+ snprintf(buf, sizeof(buf), "%s%s", return_ranges, fn_param_str);
+ return alloc_sname(buf);
+ }
if (compare_str) {
snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
return alloc_sname(buf);
}
if (math_str) {
@@ -1849,12 +1907,10 @@
struct range_list *ret_rl;
const char *return_ranges;
struct sm_state *tmp;
int ret = 0;
int nr_possible, nr_states;
- char *compare_str = NULL;
- char buf[128];
struct state_list *already_handled = NULL;
if (!sm || !sm->merged)
return 0;
@@ -1879,16 +1935,10 @@
overwrite_states_using_pool(sm, tmp);
return_ranges = get_return_ranges_str(expr, &ret_rl);
set_state(RETURN_ID, "return_ranges", NULL, alloc_estate_rl(ret_rl));
- compare_str = get_return_compare_str(expr);
- if (compare_str) {
- snprintf(buf, sizeof(buf), "%s%s", return_ranges, compare_str);
- return_ranges = alloc_sname(buf);
- }
-
return_id++;
FOR_EACH_PTR(returned_state_callbacks, cb) {
cb->callback(return_id, (char *)return_ranges, expr);
} END_FOR_EACH_PTR(cb);
@@ -2012,10 +2062,11 @@
return_id++;
nr_states = get_db_state_count();
if (nr_states >= 10000) {
match_return_info(return_id, (char *)return_ranges, expr);
+ print_limited_param_set(return_id, (char *)return_ranges, expr);
mark_all_params_untracked(return_id, (char *)return_ranges, expr);
return;
}
FOR_EACH_PTR(returned_state_callbacks, cb) {
cb->callback(return_id, (char *)return_ranges, expr);
@@ -2285,29 +2336,42 @@
static char *get_next_string(char **str)
{
static char string[256];
char *start;
char *p = *str;
- int len;
+ int len, i, j;
if (*p == '\0')
return NULL;
start = p;
- while (*p != '\0' && *p != ' ' && *p != '\n')
+ while (*p != '\0' && *p != '\n') {
+ if (*p == '\\' && *(p + 1) == ' ') {
+ p += 2;
+ continue;
+ }
+ if (*p == ' ')
+ break;
p++;
+ }
len = p - start;
- if (len > 256) {
- memcpy(string, start, 255);
- string[255] = '\0';
+ if (len >= sizeof(string)) {
+ memcpy(string, start, sizeof(string));
+ string[sizeof(string) - 1] = '\0';
sm_ierror("return_fix: '%s' too long", string);
**str = '\0';
return NULL;
}
memcpy(string, start, len);
string[len] = '\0';
+ for (i = 0; i < sizeof(string) - 1; i++) {
+ if (string[i] == '\\' && string[i + 1] == ' ') {
+ for (j = i; string[j] != '\0'; j++)
+ string[j] = string[j + 1];
+ }
+ }
if (*p != '\0')
p++;
*str = p;
return string;
}
@@ -2497,18 +2561,18 @@
state_name++;
}
if (strcmp(state_name, param_name) == 0) {
snprintf(buf, sizeof(buf), "%s$", add_star ? "*" : "");
- return buf;
+ return alloc_sname(buf);
}
if (state_name[name_len] == '-' && /* check for '-' from "->" */
strncmp(state_name, param_name, name_len) == 0) {
snprintf(buf, sizeof(buf), "%s$%s",
add_star ? "*" : "", state_name + name_len);
- return buf;
+ return alloc_sname(buf);
}
return NULL;
}
const char *get_param_name_var_sym(const char *name, struct symbol *sym)