Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a328565

Browse files
committed
C++: Prevent an expression to stepping to itself.
1 parent b9c9f65 commit a328565

1 file changed

Lines changed: 35 additions & 11 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,13 +1326,8 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
13261326
localFlow(instructionNode(e1), instructionNode(e2))
13271327
}
13281328

1329-
/**
1330-
* Holds if data can flow from `e1` to `e2` in zero or more
1331-
* local (intra-procedural) steps.
1332-
*/
1333-
pragma[inline]
1334-
predicate localExprFlow(Expr e1, Expr e2) { localExprFlowStep*(e1, e2) }
1335-
1329+
cached
1330+
private module ExprFlowCached {
13361331
/**
13371332
* Holds if `n1.asExpr()` doesn't have a result and `n1` flows to `n2` in a single
13381333
* dataflow step.
@@ -1352,14 +1347,43 @@ private predicate localStepsToExpr(Node n1, Node n2, Expr e2) {
13521347
e2 = n2.asExpr()
13531348
}
13541349

1355-
/** Holds if data can flow from `e1` to `e2` in one local (intra-procedural) step. */
1356-
cached
1357-
predicate localExprFlowStep(Expr e1, Expr e2) {
1358-
exists(Node mid, Node n1, Node n2 |
1350+
/**
1351+
* Holds if `n1.asExpr() = e1` and `n2.asExpr() = e2` and `n2` is the first node
1352+
* reacahble from `n1` such that `n2.asExpr()` exists.
1353+
*/
1354+
private predicate localExprFlowSingleExprStep(Node n1, Expr e1, Node n2, Expr e2) {
1355+
exists(Node mid |
13591356
localFlowStep(n1, mid) and
13601357
localStepsToExpr(mid, n2, e2) and
13611358
e1 = n1.asExpr()
13621359
)
1360+
}
1361+
1362+
/**
1363+
* Holds if `n1.asExpr() = e1` and `e1 != e2` and `n2` is the first reachable node from
1364+
* `n1` such that `n2.asExpr() = e2`.
1365+
*/
1366+
private predicate localExprFlowStepImpl(Node n1, Expr e1, Node n2, Expr e2) {
1367+
exists(Node n, Expr e | localExprFlowSingleExprStep(n1, e1, n, e) |
1368+
// If `n.asExpr()` and `n1.asExpr()` both resolve to the same node (which can
1369+
// happen if `n2` is the node attached to a conversion of `e1`), then we recursively
1370+
// perform another expression step.
1371+
if e1 = e
1372+
then localExprFlowStepImpl(n, e, n2, e2)
1373+
else (
1374+
// If we manage to step to a different expression we're done.
1375+
e2 = e and
1376+
n2 = n
1377+
)
1378+
)
1379+
}
1380+
1381+
/** Holds if data can flow from `e1` to `e2` in one local (intra-procedural) step. */
1382+
cached
1383+
predicate localExprFlowStep(Expr e1, Expr e2) { localExprFlowStepImpl(_, e1, _, e2) }
1384+
}
1385+
1386+
import ExprFlowCached
13631387
}
13641388

13651389
cached

0 commit comments

Comments
 (0)