Skip to content

Commit 93d8d8e

Browse files
committed
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.
1 parent 1ee96a4 commit 93d8d8e

File tree

5 files changed

+100
-1
lines changed

5 files changed

+100
-1
lines changed

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/lowerBound.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,26 @@
481481
| test.c:461:5:461:9 | total | 0 |
482482
| test.c:461:14:461:14 | r | 143 |
483483
| test.c:464:10:464:14 | total | 0 |
484+
| test.c:469:3:469:3 | x | 0 |
485+
| test.c:469:7:469:7 | y | 0 |
486+
| test.c:470:3:470:4 | xy | 0 |
487+
| test.c:470:8:470:8 | x | 1000000003 |
488+
| test.c:470:12:470:12 | y | 1000000003 |
489+
| test.c:471:10:471:11 | xy | 1000000006000000000 |
490+
| test.c:476:3:476:3 | x | 0 |
491+
| test.c:477:3:477:3 | y | 0 |
492+
| test.c:478:3:478:4 | xy | 0 |
493+
| test.c:478:8:478:8 | x | 274177 |
494+
| test.c:478:12:478:12 | y | 67280421310721 |
495+
| test.c:479:10:479:11 | xy | 18446744073709552000 |
496+
| test.c:483:7:483:8 | ui | 0 |
497+
| test.c:484:43:484:44 | ui | 10 |
498+
| test.c:484:48:484:49 | ui | 10 |
499+
| test.c:485:12:485:17 | result | 100 |
500+
| test.c:487:7:487:8 | ul | 0 |
501+
| test.c:488:28:488:29 | ul | 10 |
502+
| test.c:488:33:488:34 | ul | 10 |
503+
| test.c:489:12:489:17 | result | 0 |
484504
| test.cpp:10:7:10:7 | b | -2147483648 |
485505
| test.cpp:11:5:11:5 | x | -2147483648 |
486506
| test.cpp:13:10:13:10 | x | -2147483648 |

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,3 +463,30 @@ int test_unsigned_mult02(unsigned b) {
463463

464464
return total;
465465
}
466+
467+
unsigned long mult_rounding() {
468+
unsigned long x, y, xy;
469+
x = y = 1000000003UL; // 1e9 + 3
470+
xy = x * y;
471+
return xy; // BUG: upper bound should be >= 1000000006000000009UL
472+
}
473+
474+
unsigned long mult_overflow() {
475+
unsigned long x, y, xy;
476+
x = 274177UL;
477+
y = 67280421310721UL;
478+
xy = x * y;
479+
return xy; // BUG: lower bound should be <= 18446744073709551617UL
480+
}
481+
482+
unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
483+
if (ui >= 10) {
484+
unsigned long result = (unsigned long)ui * ui;
485+
return result; // BUG: upper bound should be >= 18446744065119617025 (possibly a pretty-printing bug)
486+
}
487+
if (ul >= 10) {
488+
unsigned long result = ul * ul;
489+
return result; // lower bound is correctly 0 (overflow is possible)
490+
}
491+
return 0;
492+
}

cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/upperBound.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,26 @@
481481
| test.c:461:5:461:9 | total | 506 |
482482
| test.c:461:14:461:14 | r | 253 |
483483
| test.c:464:10:464:14 | total | 759 |
484+
| test.c:469:3:469:3 | x | 18446744073709552000 |
485+
| test.c:469:7:469:7 | y | 18446744073709552000 |
486+
| test.c:470:3:470:4 | xy | 18446744073709552000 |
487+
| test.c:470:8:470:8 | x | 1000000003 |
488+
| test.c:470:12:470:12 | y | 1000000003 |
489+
| test.c:471:10:471:11 | xy | 1000000006000000000 |
490+
| test.c:476:3:476:3 | x | 18446744073709552000 |
491+
| test.c:477:3:477:3 | y | 18446744073709552000 |
492+
| test.c:478:3:478:4 | xy | 18446744073709552000 |
493+
| test.c:478:8:478:8 | x | 274177 |
494+
| test.c:478:12:478:12 | y | 67280421310721 |
495+
| test.c:479:10:479:11 | xy | 18446744073709552000 |
496+
| test.c:483:7:483:8 | ui | 4294967295 |
497+
| test.c:484:43:484:44 | ui | 4294967295 |
498+
| test.c:484:48:484:49 | ui | 4294967295 |
499+
| test.c:485:12:485:17 | result | 18446744065119617000 |
500+
| test.c:487:7:487:8 | ul | 18446744073709552000 |
501+
| test.c:488:28:488:29 | ul | 18446744073709552000 |
502+
| test.c:488:33:488:34 | ul | 18446744073709552000 |
503+
| test.c:489:12:489:17 | result | 18446744073709552000 |
484504
| test.cpp:10:7:10:7 | b | 2147483647 |
485505
| test.cpp:11:5:11:5 | x | 2147483647 |
486506
| test.cpp:13:10:13:10 | x | 2147483647 |

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,4 +391,33 @@ void unsigned_mult(unsigned int x, unsigned int y) {
391391
if(x * y < 5) {} // always false
392392
}
393393
}
394-
}
394+
}
395+
396+
void mult_rounding() {
397+
unsigned long x, y, xy;
398+
x = y = 1000000003UL; // 1e9 + 3
399+
xy = 1000000006000000009UL; // x * y, precisely
400+
// Even though the range analysis wrongly considers x*y to be xy - 9, there
401+
// are no PointlessComparison false positives in these tests because alerts
402+
// are suppressed when ulp() < 1, which roughly means that the number is
403+
// larger than 2^53.
404+
if (x * y < xy) {} // always false [NOT DETECTED]
405+
if (x * y > xy) {} // always false [NOT DETECTED]
406+
}
407+
408+
void mult_overflow() {
409+
unsigned long x, y;
410+
// The following two numbers multiply to 2^64 + 1, which is 1 when truncated
411+
// to 64-bit unsigned.
412+
x = 274177UL;
413+
y = 67280421310721UL;
414+
if (x * y == 1) {} // always true [BUG: reported as always false]
415+
416+
// This bug appears to be caused by
417+
// `RangeAnalysisUtils::typeUpperBound(unsigned long)` having a result of
418+
// 2**64 + 384, making the range analysis think that the multiplication can't
419+
// overflow. The correct `typeUpperBound` would be 2**64 - 1, but we can't
420+
// represent that with a QL float or int. We could make `typeUpperBound`
421+
// exclusive instead of inclusive, but there is no exclusive upper bound for
422+
// floats.
423+
}

cpp/ql/test/query-tests/Likely Bugs/Arithmetic/PointlessComparison/PointlessComparison.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
| PointlessComparison.c:372:6:372:16 | ... >= ... | Comparison is always true because ... >> ... >= 1. |
4242
| PointlessComparison.c:373:6:373:16 | ... >= ... | Comparison is always false because ... >> ... <= 1. |
4343
| PointlessComparison.c:383:6:383:17 | ... >= ... | Comparison is always false because ... & ... <= 2. |
44+
| PointlessComparison.c:388:10:388:21 | ... > ... | Comparison is always false because ... * ... <= 408. |
45+
| PointlessComparison.c:391:12:391:20 | ... < ... | Comparison is always false because ... * ... >= 6. |
46+
| PointlessComparison.c:414:7:414:16 | ... == ... | Comparison is always false because ... * ... >= 18446744073709552000. |
4447
| PointlessComparison.cpp:36:6:36:33 | ... >= ... | Comparison is always false because ... >> ... <= 9223372036854776000. |
4548
| PointlessComparison.cpp:41:6:41:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |
4649
| PointlessComparison.cpp:42:6:42:29 | ... >= ... | Comparison is always false because ... >> ... <= 140737488355327.5. |

0 commit comments

Comments
 (0)