Print this page
11972 resync 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;