Print this page
12724 update smatch to 0.6.1-rc1-il-5

@@ -70,10 +70,12 @@
 #define implied_debug 0
 #define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
 
 bool debug_implied(void)
 {
+        if (option_debug)
+                return true;
         return implied_debug;
 }
 
 /*
  * tmp_range_list():

@@ -89,10 +91,17 @@
         my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
         add_ptr_list(&my_list, my_range);
         return my_list;
 }
 
+static const char *show_comparison(int op)
+{
+        if (op == PARAM_LIMIT)
+                return "<lim>";
+        return show_special(op);
+}
+
 static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
 {
         if (!implied_debug && !option_debug)
                 return;
 

@@ -113,10 +122,22 @@
                         sm->merged ? "[merged]" : "[leaf]",
                         get_stree_id(sm->pool));
         }
 }
 
+void split_comparison_helper(struct range_list *left_orig, int op, struct range_list *right_orig,
+                struct range_list **left_true_rl, struct range_list **left_false_rl)
+{
+        if (op == PARAM_LIMIT) {
+                *left_true_rl = rl_intersection(left_orig, right_orig);
+                *left_false_rl = rl_filter(left_orig, right_orig);
+                return;
+        }
+
+        split_comparison_rl(left_orig, op, right_orig, left_true_rl, left_false_rl, NULL, NULL);
+}
+
 static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl)
 {
         struct range_list *orig_rl;
         struct range_list *true_rl, *false_rl;
         struct stree *true_stree, *false_stree;

@@ -129,11 +150,11 @@
                 return 0;
         if (!estate_rl(sm->state))
                 return 0;
 
         orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
-        split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL);
+        split_comparison_helper(orig_rl, comparison, rl, &true_rl, &false_rl);
 
         true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
         false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
         if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
             !true_rl || !false_rl ||

@@ -152,11 +173,11 @@
                 return 0;
         }
 
         if (implied_debug)
                 sm_msg("fake_history: %s vs %s.  %s %s %s. --> T: %s F: %s",
-                       sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
+                       sm->name, show_rl(rl), sm->state->name, show_comparison(comparison), show_rl(rl),
                        show_rl(true_rl), show_rl(false_rl));
 
         true_sm = clone_sm(sm);
         false_sm = clone_sm(sm);
 

@@ -231,10 +252,36 @@
         } END_FOR_EACH_PTR(tmp);
 
         return ret;
 }
 
+static bool possibly_true_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
+{
+        if (comparison == PARAM_LIMIT) {
+                struct range_list *intersect;
+
+                intersect = rl_intersection(var_rl, rl);
+                if (intersect)
+                        return true;
+                return false;
+        }
+        return possibly_true_rl(var_rl, comparison, rl);
+}
+
+static bool possibly_false_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
+{
+        if (comparison == PARAM_LIMIT) {
+                struct range_list *intersect;
+
+                intersect = rl_intersection(var_rl, rl);
+                if (!rl_equiv(var_rl, intersect))
+                        return true;
+                return false;
+        }
+        return possibly_false_rl(var_rl, comparison, rl);
+}
+
 /*
  * If 'foo' == 99 add it that pool to the true pools.  If it's false, add it to
  * the false pools.  If we're not sure, then we don't add it to either.
  */
 static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,

@@ -250,12 +297,12 @@
         if (!sm->pool)
                 return;
 
         var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
 
-        istrue = !possibly_false_rl(var_rl, comparison, rl);
-        isfalse = !possibly_true_rl(var_rl, comparison, rl);
+        istrue = !possibly_false_helper(var_rl, comparison, rl);
+        isfalse = !possibly_true_helper(var_rl, comparison, rl);
 
         print_debug_tf(sm, istrue, isfalse);
 
         /* give up if we have borrowed implications (smatch_equiv.c) */
         if (sm->sym != gate_sm->sym ||

@@ -313,11 +360,11 @@
         gettimeofday(&now, NULL);
         timersub(&now, start_time, &diff);
         if (diff.tv_sec >= 1) {
                 if (implied_debug) {
                         sm_msg("debug: %s: implications taking too long.  (%s %s %s)",
-                               __func__, sm->state->name, show_special(comparison), show_rl(rl));
+                               __func__, sm->state->name, show_comparison(comparison), show_rl(rl));
                 }
                 if (mixed)
                         *mixed = 1;
         }
 

@@ -591,11 +638,11 @@
         int sec;
 
         gettimeofday(&time_before, NULL);
 
         DIMPLIED("checking implications: (%s (%s) %s %s)\n",
-                 sm->name, sm->state->name, show_special(comparison), show_rl(rl));
+                 sm->name, sm->state->name, show_comparison(comparison), show_rl(rl));
 
         if (!is_merged(sm)) {
                 DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
                 return;
         }

@@ -750,11 +797,11 @@
 
         name = expr_to_var_sym(expr, &sym);
         if (!name || !sym)
                 goto free;
         sm = get_sm_state(SMATCH_EXTRA, name, sym);
-        if (!sm)
+        if (!sm || !sm->merged)
                 goto free;
 
         separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
         delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
         delete_gate_sm_equiv(implied_false, sm->name, sm->sym);

@@ -771,14 +818,14 @@
 
 static int handled_by_comparison_hook(struct expression *expr,
                                    struct stree **implied_true,
                                    struct stree **implied_false)
 {
+        struct sm_state *sm, *true_sm, *false_sm;
         struct state_list *true_stack = NULL;
         struct state_list *false_stack = NULL;
         struct stree *pre_stree;
-        struct sm_state *sm;
 
         sm = comparison_implication_hook(expr, &true_stack, &false_stack);
         if (!sm)
                 return 0;
 

@@ -785,10 +832,17 @@
         pre_stree = clone_stree(__get_cur_stree());
 
         *implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
         *implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
 
+        true_sm = get_sm_state_stree(*implied_true, sm->owner, sm->name, sm->sym);
+        false_sm = get_sm_state_stree(*implied_false, sm->owner, sm->name, sm->sym);
+        if (true_sm && strcmp(true_sm->state->name, "unknown") == 0)
+                delete_state_stree(implied_true, sm->owner, sm->name, sm->sym);
+        if (false_sm && strcmp(false_sm->state->name, "unknown") == 0)
+                delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
+
         free_stree(&pre_stree);
         free_slist(&true_stack);
         free_slist(&false_stack);
 
         return 1;

@@ -951,25 +1005,29 @@
         extra_saved_implied_true = NULL;
         extra_saved_implied_false = NULL;
         set_implied_states(NULL);
 }
 
-void param_limit_implications(struct expression *expr, int param, char *key, char *value)
+void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied)
 {
-        struct expression *arg;
+        struct expression *orig_expr, *arg;
         struct symbol *compare_type;
         char *name;
         struct symbol *sym;
         struct sm_state *sm;
         struct sm_state *tmp;
         struct stree *implied_true = NULL;
         struct stree *implied_false = NULL;
         struct range_list *orig, *limit;
+        char *left_name = NULL;
+        struct symbol *left_sym = NULL;
+        int mixed = 0;
 
         if (time_parsing_function() > 40)
                 return;
 
+        orig_expr = expr;
         while (expr->type == EXPR_ASSIGNMENT)
                 expr = strip_expr(expr->right);
         if (expr->type != EXPR_CALL)
                 return;
 

@@ -997,13 +1055,29 @@
         orig = estate_rl(sm->state);
         orig = cast_rl(compare_type, orig);
 
         call_results_to_rl(expr, compare_type, value, &limit);
 
-        separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL);
+        separate_and_filter(sm, PARAM_LIMIT, limit, __get_cur_stree(), &implied_true, &implied_false, &mixed);
 
+        if (orig_expr->type == EXPR_ASSIGNMENT)
+                left_name = expr_to_var_sym(orig_expr->left, &left_sym);
+
         FOR_EACH_SM(implied_true, tmp) {
+                /*
+                 * What we're trying to do here is preserve the sm state so that
+                 * smatch extra doesn't create a new sm state when it parses the
+                 * PARAM_LIMIT.
+                 */
+                if (!mixed && tmp->sym == sym &&
+                    strcmp(tmp->name, name) == 0 &&
+                    (!left_name || strcmp(left_name, name) != 0)) {
+                        overwrite_sm_state_stree(implied, tmp);
+                        continue;
+                }
+
+                // TODO why can't this just be __set_sm()?
                 __set_sm_fake_stree(tmp);
         } END_FOR_EACH_SM(tmp);
 
         free_stree(&implied_true);
         free_stree(&implied_false);