Print this page
new smatch

@@ -24,11 +24,11 @@
 ALLOCATOR(data_range, "data range");
 __DO_ALLOCATOR(struct data_range, sizeof(struct data_range), __alignof__(struct data_range),
                          "permanent ranges", perm_data_range);
 __DECLARE_ALLOCATOR(struct ptr_list, rl_ptrlist);
 
-static bool is_err_ptr(sval_t sval)
+bool is_err_ptr(sval_t sval)
 {
         if (option_project != PROJ_KERNEL)
                 return false;
         if (!type_is_ptr(sval.type))
                 return false;

@@ -247,10 +247,17 @@
         if (*c != '$')
                 return 0;
         c++;
 
         param = strtoll(c, (char **)&c, 10);
+        /*
+         * FIXME: handle parameter math.  [==$1 + 100]
+         *
+         */
+        if (*c == ' ')
+                return 0;
+
         if (*c == ',' || *c == ']')
                 c++; /* skip the ']' character */
         if (endp)
                 *endp = (char *)c;
 

@@ -340,10 +347,13 @@
         struct range_list *right_orig = right;
         struct range_list *ret_rl = *rl;
         struct symbol *cast_type;
         sval_t min, max;
 
+        if (comparison == UNKNOWN_COMPARISON)
+                return;
+
         cast_type = rl_type(left_orig);
         if (sval_type_max(rl_type(left_orig)).uvalue < sval_type_max(rl_type(right_orig)).uvalue)
                 cast_type = rl_type(right_orig);
         if (sval_type_max(cast_type).uvalue < INT_MAX)
                 cast_type = &int_ctype;

@@ -392,10 +402,14 @@
         struct symbol *type;
         struct expression *arg;
         struct range_list *casted_start, *right_orig;
         int comparison;
 
+        /* For when we have a function that takes a function pointer. */
+        if (!call || call->type != EXPR_CALL)
+                return start_rl;
+
         if (!str_to_comparison_arg_helper(c, call, &comparison, &arg, endp))
                 return start_rl;
 
         if (!get_implied_rl(arg, &right_orig))
                 return start_rl;

@@ -489,10 +503,25 @@
                 return NULL;
 
         return c;
 }
 
+static struct range_list *get_param_return_rl(struct expression *call, const char *call_math)
+{
+        struct expression *arg;
+        int param;
+
+        call_math += 3;
+        param = atoi(call_math);
+
+        arg = get_argument_from_call_expr(call->args, param);
+        if (!arg)
+                return NULL;
+
+        return db_return_vals_no_args(arg);
+}
+
 static void str_to_rl_helper(struct expression *call, struct symbol *type, const char *str, const char **endp, struct range_list **rl)
 {
         struct range_list *rl_tmp = NULL;
         sval_t prev_min, min, max;
         const char *c;

@@ -590,10 +619,16 @@
         str_to_rl_helper(call, type, value, &c, &rl);
         if (*c == '\0')
                 goto cast;
 
         call_math = jump_to_call_math(value);
+        if (call_math && call_math[0] == 'r') {
+                math_rl = get_param_return_rl(call, call_math);
+                if (math_rl)
+                        rl = rl_intersection(rl, math_rl);
+                goto cast;
+        }
         if (call_math && parse_call_math_rl(call, call_math, &math_rl)) {
                 rl = rl_intersection(rl, math_rl);
                 goto cast;
         }
 

@@ -649,11 +684,11 @@
 
 int is_whole_rl(struct range_list *rl)
 {
         struct data_range *drange;
 
-        if (ptr_list_empty(rl))
+        if (ptr_list_empty((struct ptr_list *)rl))
                 return 0;
         drange = first_ptr_list((struct ptr_list *)rl);
         if (sval_is_min(drange->min) && sval_is_max(drange->max))
                 return 1;
         return 0;

@@ -680,11 +715,11 @@
 
 int is_whole_rl_non_zero(struct range_list *rl)
 {
         struct data_range *drange;
 
-        if (ptr_list_empty(rl))
+        if (ptr_list_empty((struct ptr_list *)rl))
                 return 0;
         drange = first_ptr_list((struct ptr_list *)rl);
         if (sval_unsigned(drange->min) &&
             drange->min.value == 1 &&
             sval_is_max(drange->max))

@@ -702,11 +737,11 @@
         struct data_range *drange;
         sval_t ret;
 
         ret.type = &llong_ctype;
         ret.value = LLONG_MIN;
-        if (ptr_list_empty(rl))
+        if (ptr_list_empty((struct ptr_list *)rl))
                 return ret;
         drange = first_ptr_list((struct ptr_list *)rl);
         return drange->min;
 }
 

@@ -715,11 +750,11 @@
         struct data_range *drange;
         sval_t ret;
 
         ret.type = &llong_ctype;
         ret.value = LLONG_MAX;
-        if (ptr_list_empty(rl))
+        if (ptr_list_empty((struct ptr_list *)rl))
                 return ret;
         drange = last_ptr_list((struct ptr_list *)rl);
         return drange->max;
 }
 

@@ -1188,10 +1223,12 @@
 {
         struct range_list *rl_left, *rl_right;
         struct data_range *tmp_left, *tmp_right;
         struct symbol *type;
 
+        if (comparison == UNKNOWN_COMPARISON)
+                return 1;
         if (!get_implied_rl(left, &rl_left))
                 return 1;
         if (!get_implied_rl(right, &rl_right))
                 return 1;
 

@@ -1245,11 +1282,11 @@
 int possibly_true_rl(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
 {
         struct data_range *left_tmp, *right_tmp;
         struct symbol *type;
 
-        if (!left_ranges || !right_ranges)
+        if (!left_ranges || !right_ranges || comparison == UNKNOWN_COMPARISON)
                 return 1;
 
         type = rl_type(left_ranges);
         if (type_positive_bits(type) < type_positive_bits(rl_type(right_ranges)))
                 type = rl_type(right_ranges);

@@ -1271,11 +1308,11 @@
 int possibly_false_rl(struct range_list *left_ranges, int comparison, struct range_list *right_ranges)
 {
         struct data_range *left_tmp, *right_tmp;
         struct symbol *type;
 
-        if (!left_ranges || !right_ranges)
+        if (!left_ranges || !right_ranges || comparison == UNKNOWN_COMPARISON)
                 return 1;
 
         type = rl_type(left_ranges);
         if (type_positive_bits(type) < type_positive_bits(rl_type(right_ranges)))
                 type = rl_type(right_ranges);

@@ -1845,74 +1882,27 @@
                 }
         }
         return ret;
 }
 
-static struct range_list *handle_AND_rl_sval(struct range_list *rl, sval_t sval)
-{
-        struct range_list *known_rl;
-        sval_t zero = { 0 };
-        sval_t min;
-
-        zero.type = sval.type;
-        zero.value = 0;
-
-        if (sm_fls64(rl_max(rl).uvalue) < find_first_zero_bit(sval.uvalue) &&
-            sm_fls64(rl_min(rl).uvalue) < find_first_zero_bit(sval.uvalue))
-                return rl;
-
-        min = sval_lowest_set_bit(sval);
-
-        if (min.value != 0) {
-                sval_t max, mod;
-
-                max = rl_max(rl);
-                mod = sval_binop(max, '%', min);
-                if (mod.value) {
-                        max = sval_binop(max, '-', mod);
-                        max.value++;
-                        if (max.value > 0 && sval_cmp(max, rl_max(rl)) < 0)
-                                rl = remove_range(rl, max, rl_max(rl));
-                }
-        }
-
-        known_rl = alloc_rl(min, sval);
-
-        rl = rl_intersection(rl, known_rl);
-        zero = rl_min(rl);
-        zero.value = 0;
-        add_range(&rl, zero, zero);
-
-        return rl;
-}
-
-static struct range_list *fudge_AND_rl(struct range_list *rl)
-{
-        struct range_list *ret;
-        sval_t min;
-
-        min = sval_lowest_set_bit(rl_min(rl));
-        ret = clone_rl(rl);
-        add_range(&ret, min, rl_min(rl));
-
-        return ret;
-}
-
 static struct range_list *handle_AND_rl(struct range_list *left, struct range_list *right)
 {
-        sval_t sval, zero;
+        struct bit_info *one, *two;
         struct range_list *rl;
+        sval_t min, max, zero;
+        unsigned long long bits;
 
-        if (rl_to_sval(left, &sval))
-                return handle_AND_rl_sval(right, sval);
-        if (rl_to_sval(right, &sval))
-                return handle_AND_rl_sval(left, sval);
+        one = rl_to_binfo(left);
+        two = rl_to_binfo(right);
+        bits = one->possible & two->possible;
 
-        left = fudge_AND_rl(left);
-        right = fudge_AND_rl(right);
+        max = rl_max(left);
+        max.uvalue = bits;
+        min = sval_lowest_set_bit(max);
 
-        rl = rl_intersection(left, right);
+        rl = alloc_rl(min, max);
+
         zero = rl_min(rl);
         zero.value = 0;
         add_range(&rl, zero, zero);
 
         return rl;

@@ -2146,11 +2136,10 @@
                 if (sval_cmp(rl_min(left_orig), rl_max(left_orig)) == 0)
                         right_true = remove_range(right_orig, rl_min(left_orig), rl_min(left_orig));
                 break;
         default:
                 sm_perror(" unhandled comparison %d", op);
-                return;
         }
 
         if (left_true_rl) {
                 *left_true_rl = left_true;
                 *left_false_rl = left_false;