--- old/usr/src/tools/smatch/src/smatch_function_hooks.c	Mon Aug  5 08:38:31 2019
+++ new/usr/src/tools/smatch/src/smatch_function_hooks.c	Mon Aug  5 08:38:31 2019
@@ -139,6 +139,16 @@
 	add_callback(func_hash, look_for, cb);
 }
 
+void return_implies_state_sval(const char *look_for, sval_t start, sval_t end,
+			 implication_hook *call_back, void *info)
+{
+	struct fcall_back *cb;
+
+	cb = alloc_fcall_back(RANGED_CALL, call_back, info);
+	cb->range = alloc_range_perm(start, end);
+	add_callback(func_hash, look_for, cb);
+}
+
 void select_return_states_hook(int type, return_implies_hook *callback)
 {
 	struct return_implies_callback *cb = __alloc_return_implies_callback(0);
@@ -246,6 +256,7 @@
 	struct stree *final_states = NULL;
 	struct range_list *handled_ranges = NULL;
 	struct call_back_list *same_range_call_backs = NULL;
+	struct range_list *rl;
 	int handled = 0;
 
 	if (!call_backs)
@@ -268,7 +279,9 @@
 		call_ranged_call_backs(same_range_call_backs, fn, expr->right, expr);
 		__free_ptr_list((struct ptr_list **)&same_range_call_backs);
 
-		estate = alloc_estate_range(tmp->range->min, tmp->range->max);
+		rl = alloc_rl(tmp->range->min, tmp->range->max);
+		rl = cast_rl(get_type(expr->left), rl);
+		estate = alloc_estate_rl(rl);
 		set_extra_mod(var_name, sym, expr->left, estate);
 
 		tmp_stree = __pop_fake_cur_stree();
@@ -362,7 +375,7 @@
 
 static bool fake_a_param_assignment(struct expression *expr, const char *return_str)
 {
-	struct expression *arg, *left, *right, *fake_assign;
+	struct expression *arg, *left, *right, *tmp, *fake_assign;
 	char *p;
 	int param;
 	char buf[256];
@@ -402,6 +415,12 @@
 	arg = get_argument_from_call_expr(right->args, param);
 	if (!arg)
 		return false;
+
+	/* There should be a get_other_name() function which returns an expr */
+	tmp = get_assigned_expr(arg);
+	if (tmp)
+		arg = tmp;
+
 	/*
 	 * This is a sanity check to prevent side effects from evaluating stuff
 	 * twice.
@@ -421,8 +440,9 @@
 	return true;
 }
 
-static void set_return_state(struct expression *expr, struct db_callback_info *db_info)
+static void set_return_assign_state(struct db_callback_info *db_info)
 {
+	struct expression *expr = db_info->expr->left;
 	struct smatch_state *state;
 
 	if (!db_info->ret_state)
@@ -435,6 +455,20 @@
 	db_info->ret_str = NULL;
 }
 
+static void set_other_side_state(struct db_callback_info *db_info)
+{
+	struct expression *expr = db_info->var_expr;
+	struct smatch_state *state;
+
+	if (!db_info->ret_state)
+		return;
+
+	state = alloc_estate_rl(cast_rl(get_type(expr), clone_rl(estate_rl(db_info->ret_state))));
+	set_extra_expr_nomod(expr, state);
+	db_info->ret_state = NULL;
+	db_info->ret_str = NULL;
+}
+
 static void handle_ret_equals_param(char *ret_string, struct range_list *rl, struct expression *call)
 {
 	char *str;
@@ -561,7 +595,7 @@
 	struct range_list *var_rl = db_info->rl;
 	struct range_list *ret_range;
 	int type, param;
-	char *key, *value;
+	char *ret_str, *key, *value;
 	struct return_implies_callback *tmp;
 	struct stree *stree;
 	int return_id;
@@ -571,6 +605,7 @@
 		return 0;
 
 	return_id = atoi(argv[0]);
+	ret_str = argv[1];
 	type = atoi(argv[2]);
 	param = atoi(argv[3]);
 	key = argv[4];
@@ -578,7 +613,7 @@
 
 	db_info->has_states = 1;
 	if (db_info->prev_return_id != -1 && type == INTERNAL) {
-		set_return_state(db_info->var_expr, db_info);
+		set_other_side_state(db_info);
 		stree = __pop_fake_cur_stree();
 
 		if (!db_info->cull)
@@ -603,7 +638,7 @@
 		return 0;
 	}
 
-	call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
+	call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
 	ret_range = cast_rl(get_type(db_info->expr), ret_range);
 	if (!ret_range)
 		ret_range = alloc_whole_rl(get_type(db_info->expr));
@@ -628,13 +663,13 @@
 		filter_by_comparison(&ret_range, flip_comparison(negate_comparison(comparison)), var_rl);
 	}
 
-	handle_ret_equals_param(argv[1], ret_range, db_info->expr);
+	handle_ret_equals_param(ret_str, ret_range, db_info->expr);
 
 	if (type == INTERNAL) {
 		set_state(-1, "unnull_path", NULL, &true_state);
-		__add_return_comparison(strip_expr(db_info->expr), argv[1]);
-		__add_return_to_param_mapping(db_info->expr, argv[1]);
-		store_return_state(db_info, argv[1], alloc_estate_rl(clone_rl(var_rl)));
+		__add_return_comparison(strip_expr(db_info->expr), ret_str);
+		__add_return_to_param_mapping(db_info->expr, ret_str);
+		store_return_state(db_info, ret_str, alloc_estate_rl(clone_rl(var_rl)));
 	}
 
 	FOR_EACH_PTR(db_info->callbacks, tmp) {
@@ -687,12 +722,10 @@
 	__push_fake_cur_stree();
 	sql_select_return_states("return_id, return, type, parameter, key, value",
 				 call_expr, db_compare_callback, &db_info);
-	set_return_state(db_info.var_expr, &db_info);
+	set_other_side_state(&db_info);
 	stree = __pop_fake_cur_stree();
-	if (!db_info.cull) {
-		set_return_state(db_info.var_expr, &db_info);
+	if (!db_info.cull)
 		merge_fake_stree(&db_info.stree, stree);
-	}
 	free_stree(&stree);
 	true_states = db_info.stree;
 	if (!true_states && db_info.has_states) {
@@ -714,11 +747,10 @@
 	__push_fake_cur_stree();
 	sql_select_return_states("return_id, return, type, parameter, key, value", call_expr,
 			db_compare_callback, &db_info);
+	set_other_side_state(&db_info);
 	stree = __pop_fake_cur_stree();
-	if (!db_info.cull) {
-		set_return_state(db_info.var_expr, &db_info);
+	if (!db_info.cull)
 		merge_fake_stree(&db_info.stree, stree);
-	}
 	free_stree(&stree);
 	false_states = db_info.stree;
 	if (!false_states && db_info.has_states) {
@@ -806,18 +838,14 @@
 
 	call_backs = search_callback(func_hash, fn);
 	FOR_EACH_PTR(call_backs, tmp) {
-		struct range_list *range_rl = NULL;
+		struct range_list *range_rl;
 
 		if (tmp->type != RANGED_CALL)
 			continue;
-		add_range(&range_rl, tmp->range->min, tmp->range->max);
+		range_rl = alloc_rl(tmp->range->min, tmp->range->max);
 		range_rl = cast_rl(estate_type(db_info->ret_state), range_rl);
-		if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state))) {
-			if (!possibly_true_rl(rl_invert(range_rl), SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
-				(tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
-			else
-				db_info->handled = -1;
-		}
+		if (possibly_true_rl(range_rl, SPECIAL_EQUAL, estate_rl(db_info->ret_state)))
+			(tmp->u.ranged)(fn, expr, db_info->expr, tmp->info);
 	} END_FOR_EACH_PTR(tmp);
 }
 
@@ -826,7 +854,7 @@
 	struct db_callback_info *db_info = _info;
 	struct range_list *ret_range;
 	int type, param;
-	char *key, *value;
+	char *ret_str, *key, *value;
 	struct return_implies_callback *tmp;
 	struct stree *stree;
 	int return_id;
@@ -835,6 +863,7 @@
 		return 0;
 
 	return_id = atoi(argv[0]);
+	ret_str = argv[1];
 	type = atoi(argv[2]);
 	param = atoi(argv[3]);
 	key = argv[4];
@@ -842,7 +871,7 @@
 
 	if (db_info->prev_return_id != -1 && type == INTERNAL) {
 		call_ranged_return_hooks(db_info);
-		set_return_state(db_info->expr->left, db_info);
+		set_return_assign_state(db_info);
 		stree = __pop_fake_cur_stree();
 		if (!db_info->cull)
 			merge_fake_stree(&db_info->stree, stree);
@@ -869,7 +898,7 @@
 		param_limit_implications(db_info->expr, param, key, value);
 
 	db_info->handled = 1;
-	call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), argv[1], &ret_range);
+	call_results_to_rl(db_info->expr->right, get_type(strip_expr(db_info->expr->right)), ret_str, &ret_range);
 	if (!ret_range)
 		ret_range = alloc_whole_rl(get_type(strip_expr(db_info->expr->right)));
 	ret_range = cast_rl(get_type(db_info->expr->right), ret_range);
@@ -876,10 +905,10 @@
 
 	if (type == INTERNAL) {
 		set_state(-1, "unnull_path", NULL, &true_state);
-		__add_return_comparison(strip_expr(db_info->expr->right), argv[1]);
-		__add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), argv[1]);
-		__add_return_to_param_mapping(db_info->expr, argv[1]);
-		store_return_state(db_info, argv[1], alloc_estate_rl(ret_range));
+		__add_return_comparison(strip_expr(db_info->expr->right), ret_str);
+		__add_comparison_info(db_info->expr->left, strip_expr(db_info->expr->right), ret_str);
+		__add_return_to_param_mapping(db_info->expr, ret_str);
+		store_return_state(db_info, ret_str, alloc_estate_rl(ret_range));
 	}
 
 	FOR_EACH_PTR(db_return_states_list, tmp) {
@@ -917,7 +946,7 @@
 	}
 	if (db_info.handled)
 		call_ranged_return_hooks(&db_info);
-	set_return_state(db_info.expr->left, &db_info);
+	set_return_assign_state(&db_info);
 	stree = __pop_fake_cur_stree();
 	if (!db_info.cull)
 		merge_fake_stree(&db_info.stree, stree);
@@ -1011,7 +1040,7 @@
 	struct db_callback_info *db_info = _info;
 	struct range_list *ret_range;
 	int type, param;
-	char *key, *value;
+	char *ret_str, *key, *value;
 	struct return_implies_callback *tmp;
 	struct stree *stree;
 	int return_id;
@@ -1021,6 +1050,7 @@
 		return 0;
 
 	return_id = atoi(argv[0]);
+	ret_str = argv[1];
 	type = atoi(argv[2]);
 	param = atoi(argv[3]);
 	key = argv[4];
@@ -1053,13 +1083,13 @@
 	if (type == PARAM_LIMIT)
 		param_limit_implications(db_info->expr, param, key, value);
 
-	call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), argv[1], &ret_range);
+	call_results_to_rl(db_info->expr, get_type(strip_expr(db_info->expr)), ret_str, &ret_range);
 	ret_range = cast_rl(get_type(db_info->expr), ret_range);
 
 	if (type == INTERNAL) {
 		set_state(-1, "unnull_path", NULL, &true_state);
-		__add_return_comparison(strip_expr(db_info->expr), argv[1]);
-		__add_return_to_param_mapping(db_info->expr, argv[1]);
+		__add_return_comparison(strip_expr(db_info->expr), ret_str);
+		__add_return_to_param_mapping(db_info->expr, ret_str);
 	}
 
 
