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)