Skip to content

Commit bc8ca1a

Browse files
committed
Dataflow: Introduce NodeRegions for use in isUnreachableInCall.
1 parent 486eaad commit bc8ca1a

File tree

12 files changed

+142
-31
lines changed

12 files changed

+142
-31
lines changed

cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,15 @@ class DataFlowCall extends Expr instanceof Call {
264264
Function getEnclosingCallable() { result = this.getEnclosingFunction() }
265265
}
266266

267-
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
267+
class NodeRegion instanceof Unit {
268+
string toString() { result = "NodeRegion" }
269+
270+
predicate contains(Node n) { none() }
271+
272+
int totalOrder() { result = 1 }
273+
}
274+
275+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation
268276

269277
/**
270278
* Holds if access paths with `c` at their head always should be tracked at high

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,16 +1247,30 @@ module IsUnreachableInCall {
12471247
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
12481248
}
12491249

1250-
predicate isUnreachableInCall(Node n, DataFlowCall call) {
1250+
class NodeRegion instanceof IRBlock {
1251+
string toString() { result = "NodeRegion" }
1252+
1253+
predicate contains(Node n) { this = n.getBasicBlock() }
1254+
1255+
int totalOrder() {
1256+
this =
1257+
rank[result](IRBlock b, int startline, int startcolumn |
1258+
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
1259+
|
1260+
b order by startline, startcolumn
1261+
)
1262+
}
1263+
}
1264+
1265+
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
12511266
exists(
12521267
InstructionDirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
1253-
IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
1268+
IntegerConstantInstruction constant, int k, Operand left, Operand right
12541269
|
12551270
// arg flows into `paramNode`
12561271
DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
12571272
left = constant.getAUse() and
1258-
right = valueNumber(paramNode.getInstruction()).getAUse() and
1259-
block = n.getBasicBlock()
1273+
right = valueNumber(paramNode.getInstruction()).getAUse()
12601274
|
12611275
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
12621276
exists(boolean areEqual |

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2380,16 +2380,31 @@ predicate expectsContent(Node n, ContentSet c) {
23802380
n.asExpr() instanceof SpreadElementExpr and c instanceof ElementContent
23812381
}
23822382

2383+
class NodeRegion instanceof ControlFlow::BasicBlock {
2384+
string toString() { result = "NodeRegion" }
2385+
2386+
predicate contains(Node n) { this = n.getControlFlowNode().getBasicBlock() }
2387+
2388+
int totalOrder() {
2389+
this =
2390+
rank[result](ControlFlow::BasicBlock b, int startline, int startcolumn |
2391+
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
2392+
|
2393+
b order by startline, startcolumn
2394+
)
2395+
}
2396+
}
2397+
23832398
/**
2384-
* Holds if the node `n` is unreachable when the call context is `call`.
2399+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
23852400
*/
2386-
predicate isUnreachableInCall(Node n, DataFlowCall call) {
2401+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) {
23872402
exists(
23882403
ExplicitParameterNode paramNode, Guard guard, ControlFlow::SuccessorTypes::BooleanSuccessor bs
23892404
|
23902405
viableConstantBooleanParamArg(paramNode, bs.getValue().booleanNot(), call) and
23912406
paramNode.getSsaDefinition().getARead() = guard and
2392-
guard.controlsBlock(n.getControlFlowNode().getBasicBlock(), bs, _)
2407+
guard.controlsBlock(nr, bs, _)
23932408
)
23942409
}
23952410

go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,11 +371,26 @@ private ControlFlow::ConditionGuardNode getAFalsifiedGuard(DataFlowCall call) {
371371
)
372372
}
373373

374+
class NodeRegion instanceof BasicBlock {
375+
string toString() { result = "NodeRegion" }
376+
377+
predicate contains(Node n) { n.getBasicBlock() = this }
378+
379+
int totalOrder() {
380+
this =
381+
rank[result](BasicBlock b, int startline, int startcolumn |
382+
b.hasLocationInfo(_, startline, startcolumn, _, _)
383+
|
384+
b order by startline, startcolumn
385+
)
386+
}
387+
}
388+
374389
/**
375-
* Holds if the node `n` is unreachable when the call context is `call`.
390+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
376391
*/
377-
predicate isUnreachableInCall(Node n, DataFlowCall call) {
378-
getAFalsifiedGuard(call).dominates(n.getBasicBlock())
392+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) {
393+
getAFalsifiedGuard(call).dominates(nr)
379394
}
380395

381396
/**

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,18 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
502502
override Location getLocation() { result = c.getLocation() }
503503
}
504504

505+
private predicate id(BasicBlock x, BasicBlock y) { x = y }
506+
507+
private predicate idOf(BasicBlock x, int y) = equivalenceRelation(id/2)(x, y)
508+
509+
class NodeRegion instanceof BasicBlock {
510+
string toString() { result = "NodeRegion" }
511+
512+
predicate contains(Node n) { n.asExpr().getBasicBlock() = this }
513+
514+
int totalOrder() { idOf(this, result) }
515+
}
516+
505517
/** Holds if `e` is an expression that always has the same Boolean value `val`. */
506518
private predicate constantBooleanExpr(Expr e, boolean val) {
507519
e.(CompileTimeConstantExpr).getBooleanValue() = val
@@ -522,9 +534,9 @@ private class ConstantBooleanArgumentNode extends ArgumentNode, ExprNode {
522534
}
523535

524536
/**
525-
* Holds if the node `n` is unreachable when the call context is `call`.
537+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
526538
*/
527-
predicate isUnreachableInCall(Node n, DataFlowCall call) {
539+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) {
528540
exists(
529541
ExplicitParameterNode paramNode, ConstantBooleanArgumentNode arg, SsaImplicitInit param,
530542
Guard guard
@@ -537,7 +549,7 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) {
537549
param.getAUse() = guard and
538550
// which controls `n` with the opposite value of `arg`
539551
guard
540-
.controls(n.asExpr().getBasicBlock(),
552+
.controls(nr,
541553
pragma[only_bind_into](pragma[only_bind_out](arg.getBooleanValue()).booleanNot()))
542554
)
543555
}

python/ql/lib/semmle/python/dataflow/new/internal/DataFlowPrivate.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,13 +1023,21 @@ predicate attributeClearStep(Node n, AttributeContent c) {
10231023
exists(PostUpdateNode post | post.getPreUpdateNode() = n | attributeStoreStep(_, c, post))
10241024
}
10251025

1026+
class NodeRegion instanceof Unit {
1027+
string toString() { result = "NodeRegion" }
1028+
1029+
predicate contains(Node n) { none() }
1030+
1031+
int totalOrder() { result = 1 }
1032+
}
1033+
10261034
//--------
10271035
// Fancy context-sensitive guards
10281036
//--------
10291037
/**
1030-
* Holds if the node `n` is unreachable when the call context is `call`.
1038+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
10311039
*/
1032-
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() }
1040+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() }
10331041

10341042
/**
10351043
* Holds if access paths with `c` at their head always should be tracked at high

ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPrivate.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2170,10 +2170,18 @@ class DataFlowExpr = CfgNodes::ExprCfgNode;
21702170
*/
21712171
predicate forceHighPrecision(Content c) { c instanceof Content::ElementContent }
21722172

2173+
class NodeRegion instanceof Unit {
2174+
string toString() { result = "NodeRegion" }
2175+
2176+
predicate contains(Node n) { none() }
2177+
2178+
int totalOrder() { result = 1 }
2179+
}
2180+
21732181
/**
2174-
* Holds if the node `n` is unreachable when the call context is `call`.
2182+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
21752183
*/
2176-
predicate isUnreachableInCall(Node n, DataFlowCall call) { none() }
2184+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() }
21772185

21782186
newtype LambdaCallKind =
21792187
TYieldCallKind() or

shared/dataflow/codeql/dataflow/DataFlow.qll

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,18 @@ signature module InputSig<LocationSig Location> {
251251
*/
252252
predicate expectsContent(Node n, ContentSet c);
253253

254+
/** A set of `Node`s in a `DataFlowCallable`. */
255+
class NodeRegion {
256+
/** Holds if this region contains `n`. */
257+
predicate contains(Node n);
258+
259+
int totalOrder();
260+
}
261+
254262
/**
255-
* Holds if the node `n` is unreachable when the call context is `call`.
263+
* Holds if the nodes in `nr` are unreachable when the call context is `call`.
256264
*/
257-
predicate isUnreachableInCall(Node n, DataFlowCall call);
265+
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call);
258266

259267
default int accessPathLimit() { result = 5 }
260268

shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
350350

351351
pragma[nomagic]
352352
private predicate isUnreachableInCall1(NodeEx n, LocalCallContextSpecificCall cc) {
353-
isUnreachableInCallCached(n.asNode(), cc.getCall())
353+
exists(NodeRegion nr |
354+
nr.contains(n.asNode()) and
355+
isUnreachableInCallCached(nr, cc.getCall())
356+
)
354357
}
355358

356359
/**
@@ -5245,7 +5248,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
52455248
TSummaryCtx2 sc2, TSummaryCtx3 sc3, TSummaryCtx4 sc4, DataFlowType t, PartialAccessPath ap,
52465249
boolean isStoreStep
52475250
) {
5248-
not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and
5251+
not exists(NodeRegion nr |
5252+
nr.contains(node.asNode()) and
5253+
isUnreachableInCallCached(nr, cc.(CallContextSpecificCall).getCall())
5254+
) and
52495255
(
52505256
localFlowStepEx(mid.getNodeEx(), node, _) and
52515257
state = mid.getState() and

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -465,10 +465,10 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
465465
*/
466466
pragma[nomagic]
467467
predicate recordDataFlowCallSiteUnreachable(DataFlowCall call, DataFlowCallable callable) {
468-
exists(Node n |
468+
exists(NodeRegion nr |
469469
relevantCallEdgeIn(call, callable) and
470-
getNodeEnclosingCallable(n) = callable and
471-
isUnreachableInCallCached(n, call)
470+
getNodeRegionEnclosingCallable(nr) = callable and
471+
isUnreachableInCallCached(nr, call)
472472
)
473473
}
474474

@@ -659,7 +659,9 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
659659
predicate expectsContentCached(Node n, ContentSet c) { expectsContent(n, c) }
660660

661661
cached
662-
predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) }
662+
predicate isUnreachableInCallCached(NodeRegion nr, DataFlowCall call) {
663+
isUnreachableInCall(nr, call)
664+
}
663665

664666
cached
665667
predicate outNodeExt(Node n) {
@@ -1823,8 +1825,14 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
18231825
override predicate relevantFor(DataFlowCallable callable) { relevantLocalCCtx(call, callable) }
18241826
}
18251827

1828+
private DataFlowCallable getNodeRegionEnclosingCallable(NodeRegion nr) {
1829+
exists(Node n | nr.contains(n) | getNodeEnclosingCallable(n) = result)
1830+
}
1831+
18261832
private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) {
1827-
exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call))
1833+
exists(NodeRegion nr |
1834+
getNodeRegionEnclosingCallable(nr) = callable and isUnreachableInCallCached(nr, call)
1835+
)
18281836
}
18291837

18301838
/**

0 commit comments

Comments
 (0)