Skip to content

Commit d962fc4

Browse files
committed
C++: Improve predicate upperBound in SimpleRangeAnalysis
If an expression has an immediate guardPhi node, this is used as a strict upper bound
1 parent c110508 commit d962fc4

File tree

5 files changed

+39
-11
lines changed

5 files changed

+39
-11
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The `SimpleRangeAnalysis` library includes information from the
3+
immediate guard for determining the upper bound of a stack
4+
variable for improved accuracy.

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,19 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
9595

9696
/**
9797
* If this definition is a phi node corresponding to a guard,
98-
* then return the variable and the guard.
98+
* then return the variable access and the guard.
9999
*/
100-
predicate isGuardPhi(VariableAccess v, Expr guard, boolean branch) {
101-
guard_defn(v, guard, this, branch)
100+
predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
101+
guard_defn(va, guard, this, branch)
102+
}
103+
104+
/**
105+
* If this definition is a phi node corresponding to a guard,
106+
* then return the variable guarded, the variable access and the guard.
107+
*/
108+
predicate isGuardPhi(StackVariable v, VariableAccess va, Expr guard, boolean branch) {
109+
guard_defn(va, guard, this, branch) and
110+
va.getTarget() = v
102111
}
103112

104113
/** Gets the primary location of this definition. */

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

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,6 +1530,22 @@ private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, Vari
15301530
)
15311531
}
15321532

1533+
/**
1534+
* Gets the upper bound of the expression, if the expression is guarded.
1535+
* An upper bound can only be found, if a guard phi node can be found, and the
1536+
* expression has only one immediate predecessor.
1537+
*/
1538+
private float getGuardedUpperBound(VariableAccess guardedAccess) {
1539+
exists(
1540+
RangeSsaDefinition def, StackVariable v, VariableAccess guardVa, Expr guard, boolean branch
1541+
|
1542+
def.isGuardPhi(v, guardVa, guard, branch) and
1543+
exists(unique(BasicBlock b | b = def.(BasicBlock).getAPredecessor())) and
1544+
guardedAccess = def.getAUse(v) and
1545+
result = max(float ub | upperBoundFromGuard(guard, guardVa, ub, branch))
1546+
)
1547+
}
1548+
15331549
cached
15341550
private module SimpleRangeAnalysisCached {
15351551
/**
@@ -1565,9 +1581,9 @@ private module SimpleRangeAnalysisCached {
15651581
*/
15661582
cached
15671583
float upperBound(Expr expr) {
1568-
// Combine the upper bounds returned by getTruncatedUpperBounds into a
1569-
// single maximum value.
1570-
result = max(float ub | ub = getTruncatedUpperBounds(expr) | ub)
1584+
// Combine the upper bounds returned by getTruncatedUpperBounds and
1585+
// getGuardedUpperBound into a single maximum value
1586+
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
15711587
}
15721588

15731589
/**

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,9 +584,9 @@
584584
| test.c:639:9:639:10 | ss | 2 |
585585
| test.c:645:8:645:8 | s | 2147483647 |
586586
| test.c:645:15:645:15 | s | 127 |
587-
| test.c:645:23:645:23 | s | 15 |
588-
| test.c:646:18:646:18 | s | 15 |
589-
| test.c:646:22:646:22 | s | 15 |
587+
| test.c:645:23:645:23 | s | 9 |
588+
| test.c:646:18:646:18 | s | 9 |
589+
| test.c:646:22:646:22 | s | 9 |
590590
| test.c:647:9:647:14 | result | 127 |
591591
| test.c:653:7:653:7 | i | 0 |
592592
| test.c:654:9:654:9 | i | 2147483647 |
@@ -650,7 +650,7 @@
650650
| test.cpp:97:10:97:10 | i | 65535 |
651651
| test.cpp:97:22:97:22 | i | 32767 |
652652
| test.cpp:98:5:98:5 | i | 2147483647 |
653-
| test.cpp:98:9:98:9 | i | 32767 |
653+
| test.cpp:98:9:98:9 | i | 12345 |
654654
| test.cpp:99:5:99:5 | i | 32767 |
655655
| test.cpp:106:7:106:7 | n | 32767 |
656656
| test.cpp:109:7:109:7 | n | 32767 |

cpp/ql/test/query-tests/Critical/OverflowStatic/OverflowStatic.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,3 @@
1414
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
1515
| test.cpp:26:27:26:27 | 4 | Potential buffer-overflow: 'buffer2' has size 3 not 4. |
1616
| test.cpp:40:22:40:27 | amount | Potential buffer-overflow: 'buffer' has size 100 not 101. |
17-
| test.cpp:55:13:55:21 | access to array | Potential buffer-overflow: counter 'i' <= 9 but 'buffer' has 5 elements. |

0 commit comments

Comments
 (0)