Skip to content

Commit 3a13588

Browse files
committed
C++: Improve bounds from inequalities on integers
1 parent 9af432d commit 3a13588

File tree

5 files changed

+52
-24
lines changed

5 files changed

+52
-24
lines changed

cpp/ql/lib/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,6 +1709,22 @@ predicate nonNanGuardedVariable(Expr guard, VariableAccess v, boolean branch) {
17091709
nanExcludingComparison(guard, branch)
17101710
}
17111711

1712+
/**
1713+
* Adjusts a lower bound to its meaning for integral types.
1714+
*
1715+
* Examples:
1716+
* `>= 3.0` becomes `3.0`
1717+
* ` > 3.0` becomes `4.0`
1718+
* `>= 3.5` becomes `4.0`
1719+
* ` > 3.5` becomes `4.0`
1720+
*/
1721+
bindingset[strictness, lb]
1722+
private float adjustLowerBoundIntegral(RelationStrictness strictness, float lb) {
1723+
if strictness = Nonstrict() and lb.floorFloat() = lb
1724+
then result = lb
1725+
else result = lb.floorFloat() + 1
1726+
}
1727+
17121728
/**
17131729
* If the guard is a comparison of the form `p*v + q <CMP> r`, then this
17141730
* predicate uses the bounds information for `r` to compute a lower bound
@@ -1720,15 +1736,29 @@ private predicate lowerBoundFromGuard(Expr guard, VariableAccess v, float lb, bo
17201736
|
17211737
if nonNanGuardedVariable(guard, v, branch)
17221738
then
1723-
if
1724-
strictness = Nonstrict() or
1725-
not getVariableRangeType(v.getTarget()) instanceof IntegralType
1726-
then lb = childLB
1727-
else lb = childLB + 1
1739+
if getVariableRangeType(v.getTarget()) instanceof IntegralType
1740+
then lb = adjustLowerBoundIntegral(strictness, childLB)
1741+
else lb = childLB
17281742
else lb = varMinVal(v.getTarget())
17291743
)
17301744
}
17311745

1746+
/**
1747+
* Adjusts an upper bound to its meaning for integral types.
1748+
*
1749+
* Examples:
1750+
* `<= 3.0` becomes `3.0`
1751+
* ` < 3.0` becomes `2.0`
1752+
* `<= 3.5` becomes `3.0`
1753+
* ` < 3.5` becomes `3.0`
1754+
*/
1755+
bindingset[strictness, ub]
1756+
private float adjustUpperBoundIntegral(RelationStrictness strictness, float ub) {
1757+
if strictness = Nonstrict() and ub.ceilFloat() = ub
1758+
then result = ub
1759+
else result = ub.ceilFloat() - 1
1760+
}
1761+
17321762
/**
17331763
* If the guard is a comparison of the form `p*v + q <CMP> r`, then this
17341764
* predicate uses the bounds information for `r` to compute a upper bound
@@ -1740,11 +1770,9 @@ private predicate upperBoundFromGuard(Expr guard, VariableAccess v, float ub, bo
17401770
|
17411771
if nonNanGuardedVariable(guard, v, branch)
17421772
then
1743-
if
1744-
strictness = Nonstrict() or
1745-
not getVariableRangeType(v.getTarget()) instanceof IntegralType
1746-
then ub = childUB
1747-
else ub = childUB - 1
1773+
if getVariableRangeType(v.getTarget()) instanceof IntegralType
1774+
then ub = adjustUpperBoundIntegral(strictness, childUB)
1775+
else ub = childUB
17481776
else ub = varMaxVal(v.getTarget())
17491777
)
17501778
}

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -353,19 +353,19 @@
353353
| test.c:341:32:341:34 | odd | 9007199254740991 |
354354
| test.c:343:10:343:16 | shifted | 4503599627370495 |
355355
| test.c:348:27:348:27 | e | 0 |
356-
| test.c:348:40:348:40 | e | 0.5 |
356+
| test.c:348:40:348:40 | e | 0 |
357357
| test.c:349:25:349:25 | e | 0 |
358358
| test.c:349:39:349:39 | e | 0 |
359359
| test.c:350:27:350:27 | e | 0 |
360-
| test.c:350:40:350:40 | e | 0.333333 |
360+
| test.c:350:40:350:40 | e | 0 |
361361
| test.c:351:27:351:27 | e | 0 |
362-
| test.c:351:40:351:40 | e | 0.5 |
362+
| test.c:351:40:351:40 | e | 0 |
363363
| test.c:352:27:352:27 | e | 0 |
364-
| test.c:352:41:352:41 | e | 8.5 |
365-
| test.c:354:10:354:12 | bi1 | 0.5 |
364+
| test.c:352:41:352:41 | e | 8 |
365+
| test.c:354:10:354:12 | bi1 | 0 |
366366
| test.c:354:16:354:18 | bi2 | 0 |
367-
| test.c:354:22:354:24 | bi3 | 0.333333 |
368-
| test.c:354:28:354:30 | bi4 | 0.5 |
367+
| test.c:354:22:354:24 | bi3 | 0 |
368+
| test.c:354:28:354:30 | bi4 | 0 |
369369
| test.c:354:34:354:36 | bi5 | 2 |
370370
| test.c:359:7:359:7 | x | -2147483648 |
371371
| test.c:363:10:363:10 | i | 0 |

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
| test.c:154:10:154:40 | ... ? ... : ... | -1.0 | 1.0 | -1.0 |
2-
| test.c:348:22:348:44 | ... ? ... : ... | 0.5 | 0.5 | 2.0 |
2+
| test.c:348:22:348:44 | ... ? ... : ... | 0.0 | 0.0 | 2.0 |
33
| test.c:349:20:349:43 | ... ? ... : ... | 0.0 | 0.0 | 2.0 |
4-
| test.c:350:22:350:44 | ... ? ... : ... | 0.33333333333333337 | 0.33333333333333337 | 2.0 |
5-
| test.c:351:22:351:44 | ... ? ... : ... | 0.5 | 0.5 | 2.0 |
6-
| test.c:352:22:352:45 | ... ? ... : ... | 2.0 | 8.5 | 2.0 |
4+
| test.c:350:22:350:44 | ... ? ... : ... | 0.0 | 0.0 | 2.0 |
5+
| test.c:351:22:351:44 | ... ? ... : ... | 0.0 | 0.0 | 2.0 |
6+
| test.c:352:22:352:45 | ... ? ... : ... | 2.0 | 8.0 | 2.0 |
77
| test.c:378:8:378:23 | ... ? ... : ... | 0.0 | 0.0 | 10.0 |
88
| test.c:379:8:379:24 | ... ? ... : ... | 0.0 | 10.0 | 0.0 |
99
| test.c:387:10:387:15 | ... ? ... : ... | 0.0 | 0.0 | 5.0 |

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
| test.c:154:10:154:40 | ... ? ... : ... | 2.147483647E9 | 2.147483647E9 | -1.0 |
22
| test.c:348:22:348:44 | ... ? ... : ... | 2.147483647E9 | 2.147483647E9 | 2.0 |
33
| test.c:349:20:349:43 | ... ? ... : ... | 2.147483647E9 | 2.147483647E9 | 2.0 |
4-
| test.c:350:22:350:44 | ... ? ... : ... | 1.4316557643333333E9 | 1.4316557643333333E9 | 2.0 |
4+
| test.c:350:22:350:44 | ... ? ... : ... | 1.431655764E9 | 1.431655764E9 | 2.0 |
55
| test.c:351:22:351:44 | ... ? ... : ... | 2.147483647E9 | 2.147483647E9 | 2.0 |
66
| test.c:352:22:352:45 | ... ? ... : ... | 2.147483647E9 | 2.147483647E9 | 2.0 |
77
| test.c:378:8:378:23 | ... ? ... : ... | 99.0 | 99.0 | 10.0 |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,14 @@
357357
| test.c:349:25:349:25 | e | 4294967295 |
358358
| test.c:349:39:349:39 | e | 2147483647 |
359359
| test.c:350:27:350:27 | e | 4294967295 |
360-
| test.c:350:40:350:40 | e | 1431655764.333333 |
360+
| test.c:350:40:350:40 | e | 1431655764 |
361361
| test.c:351:27:351:27 | e | 4294967295 |
362362
| test.c:351:40:351:40 | e | 2147483647 |
363363
| test.c:352:27:352:27 | e | 4294967295 |
364364
| test.c:352:41:352:41 | e | 2147483647 |
365365
| test.c:354:10:354:12 | bi1 | 2147483647 |
366366
| test.c:354:16:354:18 | bi2 | 2147483647 |
367-
| test.c:354:22:354:24 | bi3 | 1431655764.333333 |
367+
| test.c:354:22:354:24 | bi3 | 1431655764 |
368368
| test.c:354:28:354:30 | bi4 | 2147483647 |
369369
| test.c:354:34:354:36 | bi5 | 2147483647 |
370370
| test.c:359:7:359:7 | x | 2147483647 |

0 commit comments

Comments
 (0)