C++: Demonstrate range analysis MulExpr bugs

Unless these issues can be reproduced in far less contrived code, I
don't think they will cause problems in practice.
This commit is contained in:
Jonas Jensen
2020-08-11 16:28:53 +02:00
parent 1ee96a4b4f
commit 93d8d8eb1d
5 changed files with 100 additions and 1 deletions

View File

@@ -481,6 +481,26 @@
| test.c:461:5:461:9 | total | 0 |
| test.c:461:14:461:14 | r | 143 |
| test.c:464:10:464:14 | total | 0 |
| test.c:469:3:469:3 | x | 0 |
| test.c:469:7:469:7 | y | 0 |
| test.c:470:3:470:4 | xy | 0 |
| test.c:470:8:470:8 | x | 1000000003 |
| test.c:470:12:470:12 | y | 1000000003 |
| test.c:471:10:471:11 | xy | 1000000006000000000 |
| test.c:476:3:476:3 | x | 0 |
| test.c:477:3:477:3 | y | 0 |
| test.c:478:3:478:4 | xy | 0 |
| test.c:478:8:478:8 | x | 274177 |
| test.c:478:12:478:12 | y | 67280421310721 |
| test.c:479:10:479:11 | xy | 18446744073709552000 |
| test.c:483:7:483:8 | ui | 0 |
| test.c:484:43:484:44 | ui | 10 |
| test.c:484:48:484:49 | ui | 10 |
| test.c:485:12:485:17 | result | 100 |
| test.c:487:7:487:8 | ul | 0 |
| test.c:488:28:488:29 | ul | 10 |
| test.c:488:33:488:34 | ul | 10 |
| test.c:489:12:489:17 | result | 0 |
| test.cpp:10:7:10:7 | b | -2147483648 |
| test.cpp:11:5:11:5 | x | -2147483648 |
| test.cpp:13:10:13:10 | x | -2147483648 |

View File

@@ -463,3 +463,30 @@ int test_unsigned_mult02(unsigned b) {
return total;
}
unsigned long mult_rounding() {
unsigned long x, y, xy;
x = y = 1000000003UL; // 1e9 + 3
xy = x * y;
return xy; // BUG: upper bound should be >= 1000000006000000009UL
}
unsigned long mult_overflow() {
unsigned long x, y, xy;
x = 274177UL;
y = 67280421310721UL;
xy = x * y;
return xy; // BUG: lower bound should be <= 18446744073709551617UL
}
unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
if (ui >= 10) {
unsigned long result = (unsigned long)ui * ui;
return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug)
}
if (ul >= 10) {
unsigned long result = ul * ul;
return result; // lower bound is correctly 0 (overflow is possible)
}
return 0;
}

View File

@@ -481,6 +481,26 @@
| test.c:461:5:461:9 | total | 506 |
| test.c:461:14:461:14 | r | 253 |
| test.c:464:10:464:14 | total | 759 |
| test.c:469:3:469:3 | x | 18446744073709552000 |
| test.c:469:7:469:7 | y | 18446744073709552000 |
| test.c:470:3:470:4 | xy | 18446744073709552000 |
| test.c:470:8:470:8 | x | 1000000003 |
| test.c:470:12:470:12 | y | 1000000003 |
| test.c:471:10:471:11 | xy | 1000000006000000000 |
| test.c:476:3:476:3 | x | 18446744073709552000 |
| test.c:477:3:477:3 | y | 18446744073709552000 |
| test.c:478:3:478:4 | xy | 18446744073709552000 |
| test.c:478:8:478:8 | x | 274177 |
| test.c:478:12:478:12 | y | 67280421310721 |
| test.c:479:10:479:11 | xy | 18446744073709552000 |
| test.c:483:7:483:8 | ui | 4294967295 |
| test.c:484:43:484:44 | ui | 4294967295 |
| test.c:484:48:484:49 | ui | 4294967295 |
| test.c:485:12:485:17 | result | 18446744065119617000 |
| test.c:487:7:487:8 | ul | 18446744073709552000 |
| test.c:488:28:488:29 | ul | 18446744073709552000 |
| test.c:488:33:488:34 | ul | 18446744073709552000 |
| test.c:489:12:489:17 | result | 18446744073709552000 |
| test.cpp:10:7:10:7 | b | 2147483647 |
| test.cpp:11:5:11:5 | x | 2147483647 |
| test.cpp:13:10:13:10 | x | 2147483647 |

View File

@@ -391,4 +391,33 @@ void unsigned_mult(unsigned int x, unsigned int y) {
if(x * y < 5) {} // always false
}
}
}
}
void mult_rounding() {
unsigned long x, y, xy;
x = y = 1000000003UL; // 1e9 + 3
xy = 1000000006000000009UL; // x * y, precisely
// Even though the range analysis wrongly considers x*y to be xy - 9, there
// are no PointlessComparison false positives in these tests because alerts
// are suppressed when ulp() < 1, which roughly means that the number is
// larger than 2^53.
if (x * y < xy) {} // always false [NOT DETECTED]
if (x * y > xy) {} // always false [NOT DETECTED]
}
void mult_overflow() {
unsigned long x, y;
// The following two numbers multiply to 2^64 + 1, which is 1 when truncated
// to 64-bit unsigned.
x = 274177UL;
y = 67280421310721UL;
if (x * y == 1) {} // always true [BUG: reported as always false]
// This bug appears to be caused by
// `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of
// 2**64 + 384, making the range analysis think that the multiplication can't
// overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't
// represent that with a QL float or int. We could make `typeUpperBound`
// exclusive instead of inclusive, but there is no exclusive upper bound for
// floats.
}

View File

@@ -41,6 +41,9 @@
| PointlessComparison.c:372:6:372:16 | ... >= ... | Comparison is always true because ... >> ... >= 1. |
| PointlessComparison.c:373:6:373:16 | ... >= ... | Comparison is always false because ... >> ... <= 1. |
| PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. |
| PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. |
| PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. |
| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. |
| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. |
| PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |
| PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |