Print this page
11506 smatch resync

@@ -137,10 +137,20 @@
         cb = alloc_fcall_back(RANGED_CALL, call_back, info);
         cb->range = alloc_range_perm(ll_to_sval(start), ll_to_sval(end));
         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);
 
         cb->type = type;

@@ -244,10 +254,11 @@
         struct smatch_state *estate;
         struct stree *tmp_stree;
         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)
                 return 0;
 

@@ -266,11 +277,13 @@
 
                 same_range_call_backs = get_same_ranged_call_backs(call_backs, tmp->range);
                 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();
                 merge_fake_stree(&final_states, tmp_stree);
                 free_stree(&tmp_stree);

@@ -360,11 +373,11 @@
         db_info->ret_state = state;
 }
 
 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];
         char *str;
 

@@ -400,10 +413,16 @@
         *p = '\0';
 
         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.
          */
         str = expr_to_chunk_sym_vsl(arg, NULL, NULL);

@@ -419,12 +438,13 @@
         __split_expr(fake_assign);
         __in_fake_parameter_assign--;
         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)
                 return;
 

@@ -433,10 +453,24 @@
         db_info->ret_state = NULL;
         fake_a_param_assignment(db_info->expr, db_info->ret_str);
         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;
         long long param;
         struct expression *arg;

@@ -559,28 +593,29 @@
 {
         struct db_callback_info *db_info = _info;
         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;
         int comparison;
 
         if (argc != 6)
                 return 0;
 
         return_id = atoi(argv[0]);
+        ret_str = argv[1];
         type = atoi(argv[2]);
         param = atoi(argv[3]);
         key = argv[4];
         value = argv[5];
 
         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)
                         merge_fake_stree(&db_info->stree, stree);
                 free_stree(&stree);

@@ -601,11 +636,11 @@
         if (is_impossible_data(type, db_info->expr, param, key, value)) {
                 db_info->cull = 1;
                 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));
 
         comparison = db_info->comparison;

@@ -626,17 +661,17 @@
                         param_limit_implications(db_info->expr, param, key, value);
                 filter_by_comparison(&var_rl, negate_comparison(comparison), ret_range);
                 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) {
                 if (tmp->type == type)
                         tmp->callback(db_info->expr, param, key, value);

@@ -685,16 +720,14 @@
         db_info.stree = NULL;
         db_info.prev_return_id = -1;
         __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) {
                 __push_fake_cur_stree();
                 set_path_impossible();

@@ -712,15 +745,14 @@
         db_info.prev_return_id = -1;
         db_info.cull = 0;
         __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) {
                 __push_fake_cur_stree();
                 set_path_impossible();

@@ -804,47 +836,44 @@
 
         fn = expr->fn->symbol_name->name;
 
         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)))
+                if (possibly_true_rl(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;
-                }
         } END_FOR_EACH_PTR(tmp);
 }
 
 static int db_assign_return_states_callback(void *_info, int argc, char **argv, char **azColName)
 {
         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;
 
         if (argc != 6)
                 return 0;
 
         return_id = atoi(argv[0]);
+        ret_str = argv[1];
         type = atoi(argv[2]);
         param = atoi(argv[3]);
         key = argv[4];
         value = argv[5];
 
         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);
                 free_stree(&stree);
                 __push_fake_cur_stree();

@@ -867,21 +896,21 @@
 
         if (type == PARAM_LIMIT)
                 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);
 
         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) {
                 if (tmp->type == type)
                         tmp->callback(db_info->expr, param, key, value);

@@ -915,11 +944,11 @@
                         db_info.prev_return_id,
                         db_info.ret_state ? db_info.ret_state->name : "'<empty>'");
         }
         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);
         free_stree(&stree);
 

@@ -1009,20 +1038,21 @@
 static int db_return_states_callback(void *_info, int argc, char **argv, char **azColName)
 {
         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;
         char buf[64];
 
         if (argc != 6)
                 return 0;
 
         return_id = atoi(argv[0]);
+        ret_str = argv[1];
         type = atoi(argv[2]);
         param = atoi(argv[3]);
         key = argv[4];
         value = argv[5];
 

@@ -1051,17 +1081,17 @@
         }
 
         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);
         }
 
 
         FOR_EACH_PTR(db_return_states_list, tmp) {
                 if (tmp->type == type)