Skip to content

Commit a4cb774

Browse files
lcarteyjbj
authored andcommitted
C++: Support dereferenced variables in simple range analysis
- Support inference of guards on reference variables - Support type bounds for reference variables - Support reference variables when widening - Support reference variables when determining arithmetic assignment
1 parent 027f22d commit a4cb774

File tree

2 files changed

+23
-9
lines changed

2 files changed

+23
-9
lines changed

cpp/ql/src/semmle/code/cpp/rangeanalysis/RangeAnalysisUtils.qll

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,8 @@ private predicate linearAccessImpl(Expr expr, VariableAccess v, float p, float q
191191
// Base case
192192
expr = v and p = 1.0 and q = 0.0
193193
or
194+
expr.(ReferenceDereferenceExpr).getExpr() = v and p = 1.0 and q = 0.0
195+
or
194196
// a+(p*v+b) == p*v + (a+b)
195197
exists(AddExpr addExpr, float a, float b |
196198
addExpr.getLeftOperand().isConstant() and
@@ -349,21 +351,33 @@ private predicate typeBounds(ArithmeticType t, float lb, float ub) {
349351
t instanceof FloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
350352
}
351353

354+
private Type stripReference(Type t) {
355+
if t instanceof ReferenceType then
356+
result = t.(ReferenceType).getBaseType()
357+
else
358+
result = t
359+
}
360+
361+
/** Gets the type used by range analysis for the given `StackVariable`. */
362+
Type getVariableRangeType(StackVariable v) {
363+
result = stripReference(v.getUnspecifiedType())
364+
}
365+
352366
/**
353367
* Gets the lower bound for the unspecified type `t`.
354368
*
355369
* For example, if `t` is a signed 32-bit type then the result is
356370
* `-2^31`.
357371
*/
358-
float typeLowerBound(ArithmeticType t) { typeBounds(t, result, _) }
372+
float typeLowerBound(Type t) { typeBounds(stripReference(t), result, _) }
359373

360374
/**
361375
* Gets the upper bound for the unspecified type `t`.
362376
*
363377
* For example, if `t` is a signed 32-bit type then the result is
364378
* `2^31 - 1`.
365379
*/
366-
float typeUpperBound(ArithmeticType t) { typeBounds(t, _, result) }
380+
float typeUpperBound(Type t) { typeBounds(stripReference(t), _, result) }
367381

368382
/**
369383
* Gets the minimum value that this expression could represent, based on

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

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ private predicate isRecursiveDef(RangeSsaDefinition def, StackVariable v) {
485485
* This predicate finds all the definitions in the first set.
486486
*/
487487
private predicate assignmentDef(RangeSsaDefinition def, StackVariable v, Expr expr) {
488-
v.getUnspecifiedType() instanceof ArithmeticType and
488+
getVariableRangeType(v) instanceof ArithmeticType and
489489
(
490490
def = v.getInitializer().getExpr() and def = expr
491491
or
@@ -1329,7 +1329,7 @@ private float getDefLowerBounds(RangeSsaDefinition def, StackVariable v) {
13291329
// recursion from exploding.
13301330
result =
13311331
max(float widenLB |
1332-
widenLB = wideningLowerBounds(v.getUnspecifiedType()) and
1332+
widenLB = wideningLowerBounds(getVariableRangeType(v)) and
13331333
not widenLB > truncatedLB
13341334
|
13351335
widenLB
@@ -1359,7 +1359,7 @@ private float getDefUpperBounds(RangeSsaDefinition def, StackVariable v) {
13591359
// from exploding.
13601360
result =
13611361
min(float widenUB |
1362-
widenUB = wideningUpperBounds(v.getUnspecifiedType()) and
1362+
widenUB = wideningUpperBounds(getVariableRangeType(v)) and
13631363
not widenUB < truncatedUB
13641364
|
13651365
widenUB
@@ -1391,9 +1391,9 @@ private predicate unanalyzableDefBounds(RangeSsaDefinition def, StackVariable v,
13911391
*/
13921392
bindingset[guard, v, branch]
13931393
predicate nonNanGuardedVariable(ComparisonOperation guard, VariableAccess v, boolean branch) {
1394-
v.getUnspecifiedType() instanceof IntegralType
1394+
getVariableRangeType(v.getTarget()) instanceof IntegralType
13951395
or
1396-
v.getUnspecifiedType() instanceof FloatingPointType and v instanceof NonNanVariableAccess
1396+
getVariableRangeType(v.getTarget()) instanceof FloatingPointType and v instanceof NonNanVariableAccess
13971397
or
13981398
// The reason the following case is here is to ensure that when we say
13991399
// `if (x > 5) { ...then... } else { ...else... }`
@@ -1418,7 +1418,7 @@ private predicate lowerBoundFromGuard(
14181418
then
14191419
if
14201420
strictness = Nonstrict() or
1421-
not v.getUnspecifiedType() instanceof IntegralType
1421+
not getVariableRangeType(v.getTarget()) instanceof IntegralType
14221422
then lb = childLB
14231423
else lb = childLB + 1
14241424
else lb = varMinVal(v.getTarget())
@@ -1440,7 +1440,7 @@ private predicate upperBoundFromGuard(
14401440
then
14411441
if
14421442
strictness = Nonstrict() or
1443-
not v.getUnspecifiedType() instanceof IntegralType
1443+
not getVariableRangeType(v.getTarget()) instanceof IntegralType
14441444
then ub = childUB
14451445
else ub = childUB - 1
14461446
else ub = varMaxVal(v.getTarget())

0 commit comments

Comments
 (0)