Print this page
new smatch

@@ -21,11 +21,11 @@
 #include "smatch.h"
 #include "smatch_slist.h"
 #include "smatch_extra.h"
 #include "smatch_function_hashtable.h"
 
-#define UNKNOWN_SIZE (-1)
+#define UNKNOWN_SIZE -1
 
 static int my_size_id;
 
 static DEFINE_HASHTABLE_INSERT(insert_func, char, int);
 static DEFINE_HASHTABLE_SEARCH(search_func, char, int);

@@ -272,12 +272,11 @@
 
         if (expr->type != EXPR_ASSIGNMENT)
                 return;
         call = strip_expr(expr->right);
 
-        if (!parse_call_math_rl(call, math, &rl))
-                return;
+        call_results_to_rl(call, &int_ctype, math, &rl);
         rl = cast_rl(&int_ctype, rl);
         set_state_expr(my_size_id, expr->left, alloc_estate_rl(rl));
 }
 
 static int get_real_array_size_from_type(struct symbol *type)

@@ -469,10 +468,11 @@
 }
 
 struct range_list *get_array_size_bytes_rl(struct expression *expr)
 {
         struct range_list *ret = NULL;
+        sval_t sval;
         int size;
 
         expr = remove_addr_fluff(expr);
         if (!expr)
                 return NULL;

@@ -526,10 +526,12 @@
         size = get_bytes_from_address(expr);
         if (size)
                 return alloc_int_rl(size);
 
         ret = size_from_db(expr);
+        if (rl_to_sval(ret, &sval) && sval.value == -1)
+                return NULL;
         if (ret)
                 return ret;
 
         return NULL;
 }

@@ -630,10 +632,12 @@
 static void store_alloc(struct expression *expr, struct range_list *rl)
 {
         struct symbol *type;
 
         rl = clone_rl(rl); // FIXME!!!
+        if (!rl)
+                rl = size_to_rl(UNKNOWN_SIZE);
         set_state_expr(my_size_id, expr, alloc_estate_rl(rl));
 
         type = get_type(expr);
         if (!type)
                 return;

@@ -717,11 +721,11 @@
         size = get_argument_from_call_expr(right->args, 1);
         mult = binop_expression(nr, '*', size);
         if (get_implied_rl(mult, &rl))
                 store_alloc(expr->left, rl);
         else
-                store_alloc(expr->left, size_to_rl(-1));
+                store_alloc(expr->left, size_to_rl(UNKNOWN_SIZE));
 }
 
 static void match_page(const char *fn, struct expression *expr, void *_unused)
 {
         sval_t page_size = {

@@ -742,11 +746,11 @@
         size_expr = get_argument_from_call_expr(fn_expr->args, 1);
         if (get_implied_max(size_expr, &size)) {
                 size.value++;
                 store_alloc(expr->left, size_to_rl(size.value));
         } else {
-                store_alloc(expr->left, size_to_rl(-1));
+                store_alloc(expr->left, size_to_rl(UNKNOWN_SIZE));
         }
 
 }
 
 static void match_alloc_pages(const char *fn, struct expression *expr, void *_order_arg)

@@ -816,15 +820,17 @@
         } END_FOR_EACH_PTR(arg);
 }
 
 static void struct_member_callback(struct expression *call, int param, char *printed_name, struct sm_state *sm)
 {
-        if (sm->state == &merged ||
-            strcmp(sm->state->name, "(-1)") == 0 ||
-            strcmp(sm->state->name, "empty") == 0 ||
-            strcmp(sm->state->name, "0") == 0)
+        sval_t sval;
+
+        if (!estate_rl(sm->state) ||
+            (estate_get_single_value(sm->state, &sval) &&
+             (sval.value == -1 || sval.value == 0)))
                 return;
+
         sql_insert_caller_info(call, BUF_SIZE, param, printed_name, sm->state->name);
 }
 
 /*
  * This is slightly (very) weird because half of this stuff is handled in

@@ -832,18 +838,32 @@
  * sizes here.
  *
  */
 static void print_returned_allocations(int return_id, char *return_ranges, struct expression *expr)
 {
-        char buf[16];
-        int size;
+        const char *param_math;
+        struct range_list *rl;
+        char buf[64];
+        sval_t sval;
 
-        size = get_array_size_bytes(expr);
-        if (!size)
+        rl = get_array_size_bytes_rl(expr);
+        param_math = get_allocation_math(expr);
+        if (!rl && !param_math)
                 return;
 
-        snprintf(buf, sizeof(buf), "%d", size);
+        if (!param_math &&
+            rl_to_sval(rl, &sval) &&
+            (sval.value == -1 || sval.value == 0))
+                return;
+
+        if (param_math)
+                snprintf(buf, sizeof(buf), "%s[%s]", show_rl(rl), param_math);
+        else
+                snprintf(buf, sizeof(buf), "%s", show_rl(rl));
+
+        // FIXME: don't store if you can guess the size from the type
+        // FIXME: return if we allocate a parameter $0->bar
         sql_insert_return_states(return_id, return_ranges, BUF_SIZE, -1, "", buf);
 }
 
 static void record_global_size(struct symbol *sym)
 {

@@ -870,10 +890,11 @@
         my_size_id = id;
 
         set_dynamic_states(my_size_id);
 
         add_unmatched_state_hook(my_size_id, &unmatched_size_state);
+        add_merge_hook(my_size_id, &merge_estates);
 
         select_caller_info_hook(set_param_buf_size, BUF_SIZE);
         select_return_states_hook(BUF_SIZE, &db_returns_buf_size);
         add_split_return_callback(print_returned_allocations);
 

@@ -903,17 +924,18 @@
                 add_allocation_function("devm_kzalloc", &match_alloc, 1);
                 add_allocation_function("krealloc", &match_alloc, 1);
                 add_allocation_function("__alloc_bootmem", &match_alloc, 0);
                 add_allocation_function("alloc_bootmem", &match_alloc, 0);
                 add_allocation_function("kmap", &match_page, 0);
+                add_allocation_function("kmap_atomic", &match_page, 0);
                 add_allocation_function("get_zeroed_page", &match_page, 0);
                 add_allocation_function("alloc_page", &match_page, 0);
-                add_allocation_function("page_address", &match_page, 0);
-                add_allocation_function("lowmem_page_address", &match_page, 0);
                 add_allocation_function("alloc_pages", &match_alloc_pages, 1);
                 add_allocation_function("alloc_pages_current", &match_alloc_pages, 1);
                 add_allocation_function("__get_free_pages", &match_alloc_pages, 1);
+                add_allocation_function("dma_alloc_contiguous", &match_alloc, 1);
+                add_allocation_function("dma_alloc_coherent", &match_alloc, 1);
         }
 
         add_allocation_function("strndup", match_strndup, 0);
         if (option_project == PROJ_KERNEL)
                 add_allocation_function("kstrndup", match_strndup, 0);