--- old/usr/src/tools/smatch/src/smatch_buf_size.c	Mon Nov 18 13:19:08 2019
+++ new/usr/src/tools/smatch/src/smatch_buf_size.c	Mon Nov 18 13:19:08 2019
@@ -23,7 +23,7 @@
 #include "smatch_extra.h"
 #include "smatch_function_hashtable.h"
 
-#define UNKNOWN_SIZE (-1)
+#define UNKNOWN_SIZE -1
 
 static int my_size_id;
 
@@ -274,8 +274,7 @@
 		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));
 }
@@ -471,6 +470,7 @@
 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);
@@ -528,6 +528,8 @@
 		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;
 
@@ -632,6 +634,8 @@
 	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);
@@ -719,7 +723,7 @@
 	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)
@@ -744,7 +748,7 @@
 		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));
 	}
 
 }
@@ -818,11 +822,13 @@
 
 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);
 }
 
@@ -834,14 +840,28 @@
  */
 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);
 }
 
@@ -872,6 +892,7 @@
 	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);
@@ -905,13 +926,14 @@
 		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);
