#include "test_util.h" struct List { struct List* next; }; int test1(struct List* p) { int count = 0; for (; p; p = p->next) { count = count+1; range(count); // $ range="==Phi: p | Store: count+1" } range(count); return count; } int test2(struct List* p) { int count = 0; for (; p; p = p->next) { count = (count+1) % 10; range(count); // $ range=<=9 range=>=-9 } range(count); // $ range=>=-9 range=<=9 return count; } int test3(struct List* p) { int count = 0; for (; p; p = p->next) { range(count++); // $ range=>=-9 range=<=9 count = count % 10; range(count); // $ range=<=9 range=>=-9 } range(count); // $ range=>=-9 range=<=9 return count; } int test4() { int i = 0; int total = 0; for (i = 0; i < 2; i = i+1) { range(i); // $ range=<=1 range=>=0 range(total); total += i; range(total); // $ range="<=Phi: i+1" MISSING: range=>=0 range=>=i+0 } range(total); // $ MISSING: range=>=0 range(i); // $ range===2 range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0 return total + i; } int test5() { int i = 0; int total = 0; for (i = 0; i < 2; i++) { range(i); // $ range=<=1 range=>=0 range(total); // $ MISSING: range=>=0 total += i; range(total); // $ range="<=Phi: i+1" MISSING: range=>=0 range=>=i+0 } range(total); // $ MISSING: range=>=0 range(i); // $ range===2 range(total + i); // $ range="<=Phi: i+2" MISSING: range===i+2 range=>=2 range=>=i+0 return total + i; } int test6() { int i = 0; int total = 0; for (i = 0; i+2 < 4; i = i+1) { range(i); // $ range=<=1 range=>=0 range(total); // $ MISSING: range=>=0 total += i; range(total); // $ range="<=Phi: i+1" MISSING: range=>=0 range=>=i+0 } return total + i; } int test7(int i) { if (i < 4) { if (i < 5) { range(i); // $ range=<=3 return i; } range(i); // $ range=<=3 range=>=5 } range(i); return 1; } int test8(int x, int y) { if (-1000 < y && y < 10) { range(y); // $ range=<=9 range=>=-999 if (x < y-2) { range(x); // $ range=<=6 range="<=InitializeParameter: y | Store: y-3" range(y); // $ range=<=9 range=>=-999 range=">=InitializeParameter: x | Store: x+3" return x; } range(x); // $ range=>=-1001 range=">=InitializeParameter: y | Store: y-2" range(y); // $ range=<=9 range="<=InitializeParameter: x | Store: x+2" range=>=-999 } range(x); range(y); return y; } int test9(int x, int y) { if (y == 0) { if (x < 4) { range(x); // $ range=<=3 return 0; } range(x); // $ range=>=4 } else { if (x < 4) { range(x); // $ range=<=3 return 1; } range(x); // $ range=>=4 } range(x); // $ MISSING: range=>=4 return x; } int test10(int x, int y) { if (y > 7) { range(y); // $ range=>=8 if (x < y) { range(x); // $ range="<=InitializeParameter: y-1" range(y); // $ range=>=8 range=">=InitializeParameter: x | Store: x+1" return 0; } range(x); // $ range=>=8 range=">=InitializeParameter: y+0" range(y); // $ range="<=InitializeParameter: x | Store: x+0" range=>=8 return x; } range(y); // $ range=<=7 return 1; } int test11(char *p) { char c; c = *p; range(*p); if (c != '\0') { *p++ = '\0'; range(p); // $ range="==InitializeParameter: p+1" range(*p); } if (c == ':') { range(c); // $ range===58 c = *p; range(*p); if (c != '\0') { range(c); *p++ = '\0'; range(p); // $ range="<=InitializeParameter: p+2" range="==Phi: c+1" range=">=InitializeParameter: p+1" } if (c != ',') { return 1; } } return 0; } typedef unsigned long long size_type; size_type test12_helper() { static size_type n = 0; return n++; // $ overflow=+ } int test12() { size_type Start = 0; while (Start <= test12_helper()-1) { range(Start); // $ MISSING:range=>=0 const size_type Length = test12_helper(); Start += Length + 1; // $ overflow=+ range(Start); // $ MISSING:range=>=1 MISSING:range=>=Start+1 MISSING:range=">=call to test12_helper+1" } range(Start); // $ MISSING:range=>=0 return 1; } // Tests for overflow conditions. int test13(char c, int i) { unsigned char uc = c; range(uc); unsigned int x = 0; unsigned int y = x-1; // $ overflow=- range(y); // $ range===-1 overflow=- int z = i+1; // $ overflow=+ range(z); // $ range="==InitializeParameter: i+1" range(c + i + uc + x + y + z); // $ overflow=+- overflow=+ overflow=- MISSING: range=>=1 range((double)(c + i + uc + x + y + z)); // $ overflow=+ overflow=+- overflow=- MISSING: range=>=1 return (double)(c + i + uc + x + y + z); // $ overflow=+- overflow=+ overflow=- } // Regression test for ODASA-6013. int test14(int x) { int x0 = (int)(char)x; range(x0); int x1 = (int)(unsigned char)x; range(x1); int x2 = (int)(unsigned short)x; range(x2); int x3 = (int)(unsigned int)x; range(x3); char c0 = x; range(c0); unsigned short s0 = x; range(s0); range(x0 + x1 + x2 + x3 + c0 + s0); // $ overflow=+ overflow=+- return x0 + x1 + x2 + x3 + c0 + s0; // $ overflow=+ overflow=+- } long long test15(long long x) { return (x > 0 && (range(x), x == (int)x)) ? // $ range=>=1 (range(x), x) : // $ range=>=1 (range(x), -1); } // Tests for unary operators. int test_unary(int a) { int total = 0; if (3 <= a && a <= 11) { range(a); // $ range=<=11 range=>=3 int b = +a; range(b); // $ range=<=11 range=>=3 int c = -a; range(c); // $ range=<=-3 range=>=-11 range(b+c); // $ range=<=8 range=>=-8 total += b+c; range(total); // $ range=<=8 range=>=-8 } if (0 <= a && a <= 11) { range(a); // $ range=<=11 range=>=0 int b = +a; range(b); // $ range=<=11 range=>=0 int c = -a; range(c); // $ range=<=0 range=>=-11 range(b+c); // $ range=<=11 range=>=-11 MISSING:range=">=- ...+0" total += b+c; range(total); // $ range="<=Phi: 0+11" range=<=19 range=">=Phi: 0-11" range=>=-19 } if (-7 <= a && a <= 11) { range(a); // $ range=<=11 range=>=-7 int b = +a; range(b); // $ range=<=11 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=-11 range(b+c); // $ range=<=18 range=>=-18 total += b+c; range(total); // $ range="<=Phi: - ...+18" range=">=Phi: - ...-18" range="<=Phi: 0+29" range=<=37 range=">=Phi: 0-29" range=>=-37 } if (-7 <= a && a <= 1) { range(a); // $ range=<=1 range=>=-7 int b = +a; range(b); // $ range=<=1 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=-1 range(b+c); // $ range=<=8 range=>=-8 total += b+c; range(total); // $ range="<=Phi: - ...+8" range="<=Phi: - ...+26" range=">=Phi: - ...-8" range=">=Phi: - ...-26" range="<=Phi: 0+37" range=<=45 range=">=Phi: 0-37" range=>=-45 } if (-7 <= a && a <= 0) { range(a); // $ range=<=0 range=>=-7 int b = +a; range(b); // $ range=<=0 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=0 range(b+c); // $ range=>=-7 range=<=7 MISSING:range="<=- ...+0" total += b+c; range(total); // $ range="<=Phi: - ...+7" range="<=Phi: - ...+15" range="<=Phi: - ...+33" range=">=Phi: - ...-7" range=">=Phi: - ...-15" range=">=Phi: - ...-33" range="<=Phi: 0+44" range=<=52 Unexpected result: range=">=Phi: 0-44" range=>=-52 } if (-7 <= a && a <= -2) { range(a); // $ range=<=-2 range=>=-7 int b = +a; range(b); // $ range=<=-2 range=>=-7 int c = -a; range(c); // $ range=<=7 range=>=2 range(b+c); // $ range=<=5 range=>=-5 total += b+c; range(total); // $ range="<=Phi: - ...+5" range="<=Phi: - ...+12" range="<=Phi: - ...+20" range="<=Phi: - ...+38" range=">=Phi: - ...-5" range=">=Phi: - ...-12" range=">=Phi: - ...-20" range=">=Phi: - ...-38" range="<=Phi: 0+49" range=<=57 range=">=Phi: 0-49" range=>=-57 } range(total); // $ range="<=Phi: - ...+5" range="<=Phi: - ...+12" range="<=Phi: - ...+20" range="<=Phi: - ...+38" range=">=Phi: - ...-5" range=">=Phi: - ...-12" range=">=Phi: - ...-20" range=">=Phi: - ...-38" range="<=Phi: 0+49" range=<=57 range=">=Phi: 0-49" range=>=-57 return total; } // Tests for multiplication. int test_mult01(int a, int b) { int total = 0; if (3 <= a && a <= 11 && 5 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=5 int r = a*b; // 15 .. 253 range(r); // $ range=<=253 range=>=15 total += r; range(total); // $ range=<=253 range=>=15 } if (3 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 range(r); // $ range=<=253 range=>=0 total += r; range(total); // $ range="<=Phi: 3+253" range=<=506 range=>=0 range=">=Phi: 3+0" } if (3 <= a && a <= 11 && -13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=-13 int r = a*b; // $ overflow=+- -143 .. 253 range(r); total += r; // $ overflow=+- range(total); // $ MISSING: range=">=... * ...+0" } if (3 <= a && a <= 11 && -13 <= b && b <= 0) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=0 range=>=-13 int r = a*b; // -143 .. 0 range(r); // $ range=<=0 range=>=-143 total += r; range(total); // $ range=">=Phi: 3-143" } if (3 <= a && a <= 11 && -13 <= b && b <= -7) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // -143 .. -21 range(r); // $ range=<=-21 range=>=-143 total += r; range(total); // $ range=">=Phi: 3-143" range=">=Phi: 3-286" } range(total); // $ range=">=Phi: 3-143" range=">=Phi: 3-286" return total; } // Tests for multiplication. int test_mult02(int a, int b) { int total = 0; if (0 <= a && a <= 11 && 5 <= b && b <= 23) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=23 range=>=5 int r = a*b; // 0 .. 253 range(r); // $ range=<=253 range=>=0 total += r; range(total); // $ range=>=0 range=<=253 } if (0 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 range(r); // $ range=<=253 range=>=0 total += r; range(total); // $ range=>=0 range=">=Phi: 0+0" range="<=Phi: 0+253" range=<=506 } if (0 <= a && a <= 11 && -13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=23 range=>=-13 int r = a*b; // $ overflow=+- -143 .. 253 range(r); total += r; // $ overflow=+- range(total); // $ MISSING: range=">=... * ...+0" } if (0 <= a && a <= 11 && -13 <= b && b <= 0) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=0 range=>=-13 int r = a*b; // -143 .. 0 range(r); // $ range=<=0 range=>=-143 total += r; range(total); // $ range=">=Phi: 0-143" } if (0 <= a && a <= 11 && -13 <= b && b <= -7) { range(a); // $ range=<=11 range=>=0 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // -143 .. 0 range(r); // $ range=<=0 range=>=-143 total += r; range(total); // $ range=">=Phi: 0-143" range=">=Phi: 0-286" } range(total); // $range=">=Phi: 0-143" range=">=Phi: 0-286" return total; } // Tests for multiplication. int test_mult03(int a, int b) { int total = 0; if (-17 <= a && a <= 11 && 5 <= b && b <= 23) { range(a); // $ range=<=11 range=>=-17 range(b); // $ range=<=23 range=>=5 int r = a*b; // $ overflow=+- -391 .. 253 range(r); total += r; range(total); } if (-17 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=-17 range(b); // $ range=<=23 range=>=0 int r = a*b; // $ overflow=+- -391 .. 253 range(r); total += r; // $ overflow=+- range(total); } if (-17 <= a && a <= 11 && -13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=-17 range(b); // $ range=<=23 range=>=-13 int r = a*b; // $ overflow=+- -391 .. 25 range(r); total += r; // $ overflow=+- range(total); } if (-17 <= a && a <= 11 && -13 <= b && b <= 0) { range(a); // $ range=<=11 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // $ overflow=+- -143 .. 221 range(r); total += r; // $ overflow=+- range(total); } if (-17 <= a && a <= 11 && -13 <= b && b <= -7) { range(a); // $ range=<=11 range=>=-17 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // $ overflow=+- -143 .. 221 range(r); total += r; // $ overflow=+- range(total); } range(total); return total; } // Tests for multiplication. int test_mult04(int a, int b) { int total = 0; if (-17 <= a && a <= 0 && 5 <= b && b <= 23) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=23 range=>=5 int r = a*b; // -391 .. 0 total += r; range(total); // $ range=<=0 range=>=-391 } if (-17 <= a && a <= 0 && 0 <= b && b <= 23) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=23 range=>=0 int r = a*b; // -391 .. 0 range(r); // $ range=<=0 range=>=-391 total += r; range(total); // $ range="<=Phi: - ...+0" range=<=0 range=">=Phi: - ...-391" range=>=-782 } if (-17 <= a && a <= 0 && -13 <= b && b <= 23) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=23 range=>=-13 int r = a*b; // $ overflow=+- -391 .. 221 range(r); total += r; // $ overflow=+- range(total); // $ MISSING: range="<=... * ...+0" } if (-17 <= a && a <= 0 && -13 <= b && b <= 0) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // 0 .. 221 range(r); // $ range=<=221 range=>=0 total += r; range(total); // $ range="<=Phi: - ...+221" } if (-17 <= a && a <= 0 && -13 <= b && b <= -7) { range(a); // $ range=<=0 range=>=-17 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // 0 .. 221 range(r); // $ range=<=221 range=>=0 total += r; range(total); // $ range="<=Phi: - ...+221" range="<=Phi: - ...+442" } range(total); // $ range="<=Phi: - ...+221" range="<=Phi: - ...+442" return total; } // Tests for multiplication. int test_mult05(int a, int b) { int total = 0; if (-17 <= a && a <= -2 && 5 <= b && b <= 23) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=23 range=>=5 int r = a*b; // -391 .. -10 range(r); // $ range=<=-10 range=>=-391 total += r; range(total); // $ range=<=-10 range=>=-391 } if (-17 <= a && a <= -2 && 0 <= b && b <= 23) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=23 range=>=0 int r = a*b; // -391 .. 0 range(r); // $ range=<=0 range=>=-391 total += r; range(total); // $ range="<=Phi: - ...+0" range=<=0 range=">=Phi: - ...-391" range=>=-782 } if (-17 <= a && a <= -2 && -13 <= b && b <= 23) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=23 range=>=-13 int r = a*b; // $ overflow=+- -391 .. 221 range(r); total += r; // $ overflow=+- range(total); // $ MISSING: range="<=... * ...+0" } if (-17 <= a && a <= -2 && -13 <= b && b <= 0) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=0 range=>=-13 int r = a*b; // 0 .. 221 range(r); // $ range=<=221 range=>=0 total += r; range(total); // $ range="<=Phi: - ...+221" } if (-17 <= a && a <= -2 && -13 <= b && b <= -7) { range(a); // $ range=<=-2 range=>=-17 range(b); // $ range=<=-7 range=>=-13 int r = a*b; // 14 .. 221 range(r); // $ range=<=221 range=>=14 total += r; range(total); // $ range="<=Phi: - ...+221" range="<=Phi: - ...+442" } range(total); // $ range="<=Phi: - ...+221" range="<=Phi: - ...+442" return total; } int test16(int x) { int d, i = 0; if (x < 0) { range(x); // $ range=<=-1 return -1; } while (i < 3) { range(i); // $ range=<=2 range=>=0 i++; range(i); // $ range=<=3 range=>=1 range="==Phi: i | Store: ... = ...+1" } range(d); d = i; range(d); // $ range===3 if (x < 0) { // Comparison is always false. range(x); // $ range=<=-1 range=>=0 if (d > -x) { // Unreachable code. range(d); // $ range===3 range(x); // $ range=<=-1 range=>=0 return 1; } range(d); // $ range=<=0 range=>=3 // Unreachable code range(x); // $ range=<=-1 range=>=0 } range(x); // $ range=>=0 return 0; } // Test ternary expression upper bounds. unsigned int test_ternary01(unsigned int x) { unsigned int y1, y2, y3, y4, y5, y6, y7, y8; y1 = x < 100 ? (range(x), x) : // $ range=<=99 (range(x), 10); // $ range=>=100 range(y1); // $ range=<=99 y2 = x >= 100 ? (range(x), 10) : // $ range=>=100 (range(x), x); // $ range=<=99 range(y2); // $ range=<=99 y3 = 0; y4 = 0; y5 = 0; y6 = 0; y7 = 0; y8 = 0; if (x < 300) { range(x); // $ range=<=299 y3 = x ?: (range(x), 5); range(y3); // $ range=<=299 y4 = x ?: (range(x), 500); range(y4); // $ range=<=500 y5 = (x+1) ?: (range(x), 500); // $ overflow=- range===-1 range(y5); // $ range=<=500 y6 = ((unsigned char)(x+1)) ?: (range(x), 5); // $ range=<=299 range(y6); // y6 < 256 y7 = ((unsigned char)(x+1)) ?: (range(x), 500); // $ range=<=299 range(y7); // y7 <= 500 y8 = ((unsigned short)(x+1)) ?: (range(x), 500); // $ range=<=299 range(y8); // y8 <= 300 } range(y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8); // $ overflow=+ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8; // $ overflow=+ } // Test ternary expression lower bounds. unsigned int test_ternary02(unsigned int x) { unsigned int y1, y2, y3, y4, y5; y1 = x > 100 ? (range(x), x) : // $ range=>=101 (range(x), 110); // $ range=<=100 range(y1); // $ range=>=101 y2 = x <= 100 ? (range(x), 110) : // $ range=<=100 (range(x), x); // $ range=>=101 range(y2); // $ range=>=101 y3 = 1000; y4 = 1000; y5 = 1000; if (x >= 300) { range(x); // $ range=>=300 y3 = (x-300) ?: (range(x), 5); // $ range===300 range(y3); // $ range=>=0 y4 = (x-200) ?: (range(x), 5); // $ range=<=200 range=>=300 range(y4); // $ SPURIOUS: range=>=5 MISSING: range=>=100 y5 = ((unsigned char)(x-200)) ?: (range(x), 5); // $ range=>=300 range(y5); // y6 >= 0 } range(y1 + y2 + y3 + y4 + y5); // $ overflow=+ MISSING: range=">=call to range+207" range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" return y1 + y2 + y3 + y4 + y5; // $ overflow=+ } // Test the comma expression. unsigned int test_comma01(unsigned int x) { unsigned int y = x < 100 ? (range(x), x) : // $ range=<=99 (range(x), 100); // $ range=>=100 unsigned int y1; unsigned int y2; y1 = (++y, y); range(y1); // $ range=<=101 range="==Phi: ... ? ... : ... | Store: ... ? ... : ...+1" y2 = (y++, range(y), // $ range=<=102 range="==Store: ++ ... | Store: ... = ...+1" range="==Phi: ... ? ... : ... | Store: ... ? ... : ...+2" y += 3, range(y), // $ range=<=105 range="==Store: ++ ... | Store: ... = ...+4" range="==Store: ... +++3" range="==Phi: ... ? ... : ... | Store: ... ? ... : ...+5" y); range(y2); // $ range=<=105 range="==Store: ++ ... | Store: ... = ...+4" range="==Store: ... +++3" Unexpected result: range="==Phi: ... ? ... : ... | Store: ... ? ... : ...+5" range(y1 + y2); // $ range=<=206 range="<=Phi: ... ? ... : ... | Store: ... ? ... : ...+106" MISSING: range=">=++ ...:... = ...+5" range=">=... +++4" range=">=... += ...:... = ...+1" range=">=... ? ... : ...+6" return y1 + y2; } void test17() { int i, j; i = 10; range(i); // $ range===10 i = 10; i += 10; range(i); // $ range===20 i = 40; i -= 10; range(i); // $ range===30 i = j = 40; range(i); // $ range===40 i = (j += 10); range(i); // $ range===50 i = 20 + (j -= 10); range(i); // $ range="==Store: ... += ... | Store: ... = ...+10" range===60 range="==Store: ... -= ...+20" } // Tests for unsigned multiplication. int test_unsigned_mult01(unsigned int a, unsigned b) { int total = 0; if (3 <= a && a <= 11 && 5 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=5 int r = a*b; // 15 .. 253 range(r); // $ range=>=15 range=<=253 total += r; range(total); // $ range=>=15 range=<=253 } if (3 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 range(r);// $ range=>=0 range=<=253 total += r; range(total); // $ range=">=Phi: (unsigned int)...+0" range=>=0 range=<=506 range="<=Phi: (unsigned int)...+253" } if (3 <= a && a <= 11 && 13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=13 int r = a*b; // 39 .. 253 range(r); // $ range=>=39 range=<=253 total += r; range(total); // $ range=>=39 range=<=759 range="<=Phi: (unsigned int)...+253" range="<=Phi: (unsigned int)...+506" range=">=Phi: (unsigned int)...+39" } range(total); // $ range=>=0 range=<=759 range=">=Phi: (unsigned int)...+0" range="<=Phi: (unsigned int)...+506" range="<=Phi: (unsigned int)...+253" return total; } int test_unsigned_mult02(unsigned b) { int total = 0; if (5 <= b && b <= 23) { range(b); // $ range=<=23 range=>=5 int r = 11*b; // 55 .. 253 range(r); // $ range=>=55 range=<=253 total += r; range(total); // $ range=>=55 range=<=253 } if (0 <= b && b <= 23) { range(b); // $ range=<=23 range=>=0 int r = 11*b; // 0 .. 253 range(r); // $ range=>=0 range=<=253 total += r; range(total); // $ range=">=Phi: (unsigned int)...+0" range=>=0 range="<=Phi: (unsigned int)...+253" range=<=506 } if (13 <= b && b <= 23) { range(b); // $ range=<=23 range=>=13 int r = 11*b; // 143 .. 253 range(r); // $ range=>=143 range=<=253 total += r; range(total); // $ range="<=Phi: (unsigned int)...+253" range="<=Phi: (unsigned int)...+506" range=">=Phi: (unsigned int)...+143" range=>=143 range=<=759 } range(total); // $ range=>=0 range=<=759 range=">=Phi: (unsigned int)...+0" range="<=Phi: (unsigned int)...+506" range="<=Phi: (unsigned int)...+253" return total; } unsigned long mult_rounding() { unsigned long x, y, xy; x = y = 1000000003UL; // 1e9 + 3 range(y); // $ range===1000000003 range(x); // $ range===1000000003 xy = x * y; range(xy); // $ range===1000000006000000000 return xy; // BUG: upper bound should be >= 1000000006000000009UL } unsigned long mult_overflow() { unsigned long x, y, xy; x = 274177UL; range(x); // $ range===274177 y = 67280421310721UL; range(y); xy = x * y; // $ overflow=+- range(xy); return xy; // BUG: upper bound should be >= 18446744073709551617UL } unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) { if (ui >= 10) { range(ui); // $ range=>=10 range((unsigned long)ui); // $ range=>=10 unsigned long result = (unsigned long)ui * ui; // $ overflow=+ range(result); // $ MISSING: range=>=100 return result; // BUG: upper bound should be >= 18446744065119617025 } if (ul >= 10) { range(ul); // $ range=>=10 unsigned long result = ul * ul; // $ overflow=+ range(result); // $ MISSING: range=>=100 return result; // BUG: lower bound should be 0 (overflow is possible) } return 0; } unsigned long mul_assign(unsigned int ui) { if (ui <= 10 && ui >= 2) { range(ui); // $ range=<=10 range=>=2 ui *= ui + 0; range(ui); // $ range=<=100 range=>=4 return ui; // 4 .. 100 } unsigned int uiconst = 10; range(uiconst); // $ range===10 uiconst *= 4; range(uiconst); // $ range===40 unsigned long ulconst = 10; range(ulconst); // $ range===10 ulconst *= 4; range(ulconst); // $ range===40 range(uiconst + ulconst); // $ range===80 return uiconst + ulconst; // 40 .. 40 for both } int mul_by_constant(int i, int j) { if (i >= -1 && i <= 2) { range(i); // $ range=<=2 range=>=-1 i = 5 * i; range(i); // $ range=<=10 range=>=-5 i = i * -3; // $ overflow=+- range(i); // -30 .. 15 i *= 7; // $ overflow=+- range(i); // -210 .. 105 i *= -11; // $ overflow=+- range(i); // -1155 .. 2310 } if (i == -1) { range(i); // $ range===-1 range((int)0xffFFffFF); // $ range===-1 i = i * (int)0xffFFffFF; // fully converted literal is -1 range(i); // $ range===1 } i = i * -1; // $ overflow=+- range( i); // -2^31 .. 2^31-1 signed char sc = 1; range(sc); // $ range===1 i = (*&sc *= 2); range(sc); // $ range===2 range(i); // $ range===2 return 0; } int notequal_type_endpoint(unsigned n) { range(n); // 0 .. if (n > 0) { range(n); // $ range=>=1 } if (n != 0) { range(n); // 1 .. } else { range(n); // 0 .. 0 } if (!n) { range(n); // 0 .. 0 } else { range(n); // 1 .. } while (n != 0) { n--; // 1 .. } range(n); // $ range="<=InitializeParameter: n+0" // 0 .. 0 } void notequal_refinement(short n) { if (n < 0) { range(n); // $ range=<=-1 return; } if (n == 0) { range(n); // 0 .. 0 } else { range(n); // $ range=>=1 } if (n) { range(n); // $ range=>=1 } else { range(n); // 0 .. 0 } while (n != 0) { range(n); // $ MISSING:range=<=n+0 n--; // 1 .. } range(n); // $ MISSING:range=<=n+0 // 0 .. 0 } void notequal_variations(short n, float f) { if (n != 0) { if (n >= 0) { range(n); // $ range=>=1 } } if (n >= 5) { if (2 * n - 10 == 0) { // $ overflow=+ range(n); // $ range=>=5 MISSING: range===5 return; } range(n); // $ range=>=5 MISSING: range=>=6 } if (n != -32768 && n != -32767) { range(n); // -32766 .. } if (n >= 0) { n ? (range(n), n) // $ range=>=1 : (range(n), n); // $ MISSING: range===0 !n ? (range(n), n) // $ MISSING: range===0 : (range(n), n); // $ range=>=1 } } void two_bounds_from_one_test(short ss, unsigned short us) { // These tests demonstrate how the range analysis is often able to deduce // both an upper bound and a lower bound even when there is only one // inequality in the source. For example `signedInt < 4U` establishes that // `signedInt >= 0` since if `signedInt` were negative then it would be // greater than 4 in the unsigned comparison. if (ss < sizeof(int)) { // Lower bound added in `linearBoundFromGuard` range(ss); // 0 .. 3 } if (ss < 0x8001) { // Lower bound removed in `getDefLowerBounds` range(ss); // $ overflow=+ range=<=32768 MISSING: range=>=-32768 } if ((short)us >= 0) { range(us); // 0 .. 32767 } if ((short)us >= -1) { range(us); // 0 .. 65535 } if (ss >= sizeof(int)) { // test is true for negative numbers range(ss); // -32768 .. 32767 } if (ss + 1 < sizeof(int)) { // $ overflow=+ range(ss); // -1 .. 2 } } void widen_recursive_expr() { int s; for (s = 0; s < 10; s++) { range(s); // $ range=<=9 range=>=0 int result = s + s; range(result); // $ range=<=18 Unexpected result: range="<=Phi: s+9" range=>=0 Unexpected result: range=">=Phi: s+0" } } void guard_bound_out_of_range(void) { int i = 0; if (i < 0) { range(i); // unreachable [BUG: is -max .. +max] } unsigned int u = 0; if (u < 0) { range(u); // unreachable [BUG: is 0 .. +max] } } void test_mod(int s) { int s2 = s % 5; range(s2); // $ range=>=-4 range=<=4 } void test_mod_neg(int s) { int s2 = s % -5; range(s2); // $ range=>=-4 range=<=4 } void test_mod_ternary(int s, bool b) { int s2 = s % (b ? 5 : 500); range(s2); // $ range=>=-499 range=<=499 } void test_mod_ternary2(int s, bool b1, bool b2) { int s2 = s % (b1 ? (b2 ? 5 : -5000) : -500000); range(s2); // $ range=>=-499999 range=<=499999 } void exit(int); void guard_with_exit(int x, int y) { if (x) { if (y != 0) { exit(0); } } range(y); // .. // This test ensures that we correctly identify // that the upper bound for y is max_int when calling `range(y)`. } void test(int x) { if (x >= 10) { range(x); // $ range=>=10 return; } // The basic below has two predecessors. label: range(x); // $ range=<=9 goto label; } void test_overflow() { const int x = 2147483647; // 2^31-1 range(x); // $ range===2147483647 const int y = 256; range(y); // $ range===256 if ((x + y) <= 512) { // $ overflow=+ range(x); // $ range===2147483647 range(y); // $ range===256 range(x + y); // $ range=<=2147483903 overflow=+ } } void test_negate_unsigned(unsigned u) { if(10 < u && u < 20) { range(-u); // $ overflow=- } } void test_negate_signed(int s) { if(10 < s && s < 20) { range(-s); // $ range=<=-11 range=>=-19 } } // By setting the guard after the use in another guard we // don't get the useful information void test_guard_after_use(int pos, int size, int offset) { if (pos + offset >= size) { // $ overflow=+- return; } if (offset != 1) { return; } range(pos + 1); // $ overflow=+ range="==InitializeParameter: pos+1" MISSING: range="<=InitializeParameter: size-1" } int cond(); // This is basically what we get when we have a loop that calls // realloc in some iterations void alloc_in_loop(int origLen) { if (origLen <= 10) { return; } int len = origLen; int index = 0; while (cond()) { if (index == len) { if (len >= 1000) { return; } len = len * 2; // $ overflow=- } // We want that index < len range(index); // $ MISSING: range="<=InitializeParameter: len-1" index++; } } // This came from a case where it handled the leftovers before an unrolled loop void mask_at_start(int len) { if (len < 0) { return; } int leftOver = len & 63; for (int i = 0; i < leftOver; i++) { range(i); // $ range=<=62 range=>=0 range="<=Store: ... & ... | Store: leftOver-1" range="<=InitializeParameter: len-1" } // Do something with leftOver for (int index = leftOver; index < len; index+=64) { range(index); // $ range="<=InitializeParameter: len-64" range=">=Store: ... & ... | Store: leftOver+0" range(index + 63); // $ range="<=InitializeParameter: len-1" range="==Phi: index+63" range=">=Store: ... & ... | Store: leftOver+63" } } // Same as above but with modulo void mod_at_start(int len) { if (len < 0) { return; } int leftOver = len % 64; for (int i = 0; i < leftOver; i++) { range(i); // $ range=<=62 range=>=0 range="<=Store: ... % ... | Store: leftOver-1" range="<=InitializeParameter: len-1" } // Do something with leftOver for (int index = leftOver; index < len; index+=64) { range(index); // $ range="<=InitializeParameter: len-64" range=">=Store: ... % ... | Store: leftOver+0" range(index + 63); // $ range="<=InitializeParameter: len-1" range="==Phi: index+63" range=">=Store: ... % ... | Store: leftOver+63" } }