Skip to content

Commit a5c13d3

Browse files
authored
Merge pull request #134 from goblint/interval_no_compute_on_top
Interval domain: Don't compute on top values
2 parents cbf5944 + ef5b7be commit a5c13d3

File tree

4 files changed

+75
-16
lines changed

4 files changed

+75
-16
lines changed

src/cdomains/intDomain.ml

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,15 @@ struct
266266
let ur = if Int64.compare max_int x2 = 0 then y2 else x2 in
267267
norm @@ Some (lr,ur)
268268

269+
(* Returns top if one of a, b is top, otherwise return result *)
270+
let on_top_return_top_bin a b result =
271+
if is_top a || is_top b then top () else result
272+
273+
let on_top_return_top_un a result =
274+
if is_top a then top () else result
275+
269276
let log f i1 i2 =
277+
on_top_return_top_bin i1 i2 @@
270278
match is_bot i1, is_bot i2 with
271279
| true, true -> bot ()
272280
| true, _
@@ -280,6 +288,7 @@ struct
280288
let logand = log (&&)
281289

282290
let log1 f i1 =
291+
on_top_return_top_un i1 @@
283292
if is_bot i1 then
284293
bot ()
285294
else
@@ -290,6 +299,7 @@ struct
290299
let lognot = log1 not
291300

292301
let bit f i1 i2 =
302+
on_top_return_top_bin i1 i2 @@
293303
match is_bot i1, is_bot i2 with
294304
| true, true -> bot ()
295305
| true, _
@@ -315,17 +325,20 @@ struct
315325
let shift_right = bit (fun x y -> Int64.shift_right x (Int64.to_int y))
316326
let shift_left = bit (fun x y -> Int64.shift_left x (Int64.to_int y))
317327

318-
let neg = function None -> None | Some (x,y) -> norm @@ Some (Int64.neg y, Int64.neg x)
328+
let neg x = on_top_return_top_un x @@ match x with None -> None | Some (x,y) -> norm @@ Some (Int64.neg y, Int64.neg x)
319329

320330
let add x y =
331+
on_top_return_top_bin x y @@
321332
match x, y with
322333
| None, None -> None
323334
| None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (short 80 x) (short 80 y)))
324335
| Some (x1,x2), Some (y1,y2) -> norm @@ Some (Int64.add x1 y1, Int64.add x2 y2)
325336

326337
let sub i1 i2 = add i1 (neg i2)
327338

328-
let rem x y = match x, y with
339+
let rem x y =
340+
on_top_return_top_bin x y @@
341+
match x, y with
329342
| None, None -> None
330343
| None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (short 80 x) (short 80 y)))
331344
| Some (xl, xu), Some (yl, yu) ->
@@ -348,16 +361,21 @@ struct
348361
meet (bit Int64.rem x y) range
349362

350363
let mul x y =
351-
match x, y with
352-
| None, None -> bot ()
353-
| None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (short 80 x) (short 80 y)))
354-
| Some (x1,x2), Some (y1,y2) ->
355-
let x1y1 = (Int64.mul x1 y1) in let x1y2 = (Int64.mul x1 y2) in
356-
let x2y1 = (Int64.mul x2 y1) in let x2y2 = (Int64.mul x2 y2) in
357-
norm @@ Some ((min (min x1y1 x1y2) (min x2y1 x2y2)),
358-
(max (max x1y1 x1y2) (max x2y1 x2y2)))
364+
if (is_top x || is_top y) && to_int x <> Some 0L && to_int y <> Some 0L then
365+
(* if one of the argument is zero, the result must be zero, even if the value is outside the range of Interval32 *)
366+
top ()
367+
else
368+
match x, y with
369+
| None, None -> bot ()
370+
| None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (short 80 x) (short 80 y)))
371+
| Some (x1,x2), Some (y1,y2) ->
372+
let x1y1 = (Int64.mul x1 y1) in let x1y2 = (Int64.mul x1 y2) in
373+
let x2y1 = (Int64.mul x2 y1) in let x2y2 = (Int64.mul x2 y2) in
374+
norm @@ Some ((min (min x1y1 x1y2) (min x2y1 x2y2)),
375+
(max (max x1y1 x1y2) (max x2y1 x2y2)))
359376

360377
let rec div x y =
378+
on_top_return_top_bin x y @@
361379
match x, y with
362380
| None, None -> bot ()
363381
| None, _ | _, None -> raise (ArithmeticOnIntegerBot (Printf.sprintf "%s op %s" (short 80 x) (short 80 y)))
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//PARAM: --enable ana.int.interval --disable ana.int.def_exc
2+
#include <assert.h>
3+
4+
int main(){
5+
// 2^33
6+
long long x = 8589934592l;
7+
// 2^31 - 1
8+
long long y = 2147483647;
9+
10+
long long z = x/y;
11+
12+
if(z == 4){
13+
// Should be reachable
14+
assert(1);
15+
}
16+
17+
assert(z > 2); //UNKNOWN
18+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//PARAM: --enable ana.int.interval --enable ana.int.def_exc
2+
#include <assert.h>
3+
4+
int main(){
5+
int top;
6+
// 2^33
7+
long long x = 8589934592l;
8+
// 2^31 - 1
9+
long long y = 2147483647;
10+
11+
if(top) {
12+
x = x - 1;
13+
}
14+
15+
long long z = x/y;
16+
17+
if(z == 4){
18+
// Should be reachable
19+
assert(1);
20+
}
21+
22+
assert(z > 2); //UNKNOWN
23+
}

tests/regression/27-inv_invariants/01-ints.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ int main() {
2121
assert(x == 2 && y == 4);
2222
if (x == 3 && y/x == 2) {
2323
assert(y == 6); // UNKNOWN!
24-
assert(RANGE(y, 6, 8));
24+
assert(RANGE(y, 6, 8)); // UNKNOWN
2525
}
2626
if (y/3 == -2)
27-
assert(RANGE(y, -8, -6));
27+
assert(RANGE(y, -8, -6)); // UNKNOWN
2828
if (y/-3 == -2)
29-
assert(RANGE(y, 6, 8));
29+
assert(RANGE(y, 6, 8)); // UNKNOWN
3030
if (y/x == 2 && x == 3)
3131
assert(x == 3); // TO-DO y == [6,8]; this does not work because CIL transforms this into two if-statements
3232
if (2+(3-x)*4/5 == 6 && 2*y >= x+5)
@@ -113,7 +113,7 @@ int main2() {
113113
if (x == three && y/x == two) {
114114
// y could for example also be 7
115115
assert(y == six); // UNKNOWN!
116-
assert(RANGE(y, 6, 8));
116+
assert(RANGE(y, 6, 8)); // UNKNOWN
117117
}
118118
if (y/x == two && x == three)
119119
assert(x == three); // TO-DO y == six
@@ -124,9 +124,9 @@ int main2() {
124124
assert(x != two); // [two,four] -> [three,four] TO-DO x % two == one
125125

126126
if (y/three == -two)
127-
assert(RANGE(y, -8, -6));
127+
assert(RANGE(y, -8, -6)); // UNKNOWN
128128
if (y/-three == -two)
129-
assert(RANGE(y, 6, 8));
129+
assert(RANGE(y, 6, 8)); // UNKNOWN
130130
if (y/x == two && x == three)
131131
assert(x == 3); // TO-DO y == [6,8]; this does not work because CIL transforms this into two if-statements
132132
if (two+(three-x)*four/five == six && two*y >= x+five)

0 commit comments

Comments
 (0)