Skip to content

Commit e4db3b1

Browse files
authored
Merge pull request #20584 from paldepind/cpp/range-analysis-fix
C++: Range analysis guard improvement
2 parents c9e6d42 + 3a13588 commit e4db3b1

File tree

7 files changed

+5141
-4976
lines changed

7 files changed

+5141
-4976
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
}

0 commit comments

Comments
 (0)