Skip to content

Commit 2ec78ed

Browse files
committed
PS: Fix 'getIterableExpr' on 'ForEachStmtCfgNode'.
1 parent 831f25d commit 2ec78ed

File tree

2 files changed

+37
-32
lines changed

2 files changed

+37
-32
lines changed

powershell/ql/lib/semmle/code/powershell/controlflow/CfgNodes.qll

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,25 @@ abstract private class ChildMapping extends Ast {
7272
*/
7373
abstract predicate relevantChild(Ast child);
7474

75+
/**
76+
* Holds if `child` appears before its parent in the control-flow graph.
77+
* This always holds for expressions, and _almost_ never for statements.
78+
*/
79+
abstract predicate precedesParent(Ast child);
80+
7581
pragma[nomagic]
76-
abstract predicate reachesBasicBlock(Ast child, CfgNode cfn, BasicBlock bb);
82+
final predicate reachesBasicBlock(Ast child, CfgNode cfn, BasicBlock bb) {
83+
this.relevantChild(child) and
84+
cfn.getAstNode() = this and
85+
bb.getANode() = cfn
86+
or
87+
exists(BasicBlock mid |
88+
this.reachesBasicBlock(child, cfn, mid) and
89+
not mid.getANode().getAstNode() = child
90+
|
91+
if this.precedesParent(child) then bb = mid.getAPredecessor() else bb = mid.getASuccessor()
92+
)
93+
}
7794

7895
/**
7996
* Holds if there is a control-flow path from `cfn` to `cfnChild`, where `cfn`
@@ -93,18 +110,7 @@ abstract private class ChildMapping extends Ast {
93110
* A class for mapping parent-child AST nodes to parent-child CFG nodes.
94111
*/
95112
abstract private class ExprChildMapping extends Expr, ChildMapping {
96-
pragma[nomagic]
97-
override predicate reachesBasicBlock(Ast child, CfgNode cfn, BasicBlock bb) {
98-
this.relevantChild(child) and
99-
cfn.getAstNode() = this and
100-
bb.getANode() = cfn
101-
or
102-
exists(BasicBlock mid |
103-
this.reachesBasicBlock(child, cfn, mid) and
104-
bb = mid.getAPredecessor() and
105-
not mid.getANode().getAstNode() = child
106-
)
107-
}
113+
final override predicate precedesParent(Ast child) { this.relevantChild(child) }
108114
}
109115

110116
/**
@@ -113,18 +119,7 @@ abstract private class ExprChildMapping extends Expr, ChildMapping {
113119
abstract private class NonExprChildMapping extends ChildMapping {
114120
NonExprChildMapping() { not this instanceof Expr }
115121

116-
pragma[nomagic]
117-
override predicate reachesBasicBlock(Ast child, CfgNode cfn, BasicBlock bb) {
118-
this.relevantChild(child) and
119-
cfn.getAstNode() = this and
120-
bb.getANode() = cfn
121-
or
122-
exists(BasicBlock mid |
123-
this.reachesBasicBlock(child, cfn, mid) and
124-
bb = mid.getASuccessor() and
125-
not mid.getANode().getAstNode() = child
126-
)
127-
}
122+
override predicate precedesParent(Ast child) { none() } // this is not final because it is overriden by ForEachStmt
128123
}
129124

130125
private class AttributeBaseChildMapping extends NonExprChildMapping, AttributeBase {
@@ -1208,7 +1203,7 @@ module StmtNodes {
12081203
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
12091204
}
12101205

1211-
private class LoopStmtChildMapping extends NonExprChildMapping, LoopStmt {
1206+
abstract private class LoopStmtChildMapping extends ChildMapping, LoopStmt {
12121207
override predicate relevantChild(Ast child) { child = this.getBody() }
12131208
}
12141209

@@ -1222,7 +1217,9 @@ module StmtNodes {
12221217
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
12231218
}
12241219

1225-
private class DoUntilStmtChildMapping extends LoopStmtChildMapping, DoUntilStmt {
1220+
private class DoUntilStmtChildMapping extends LoopStmtChildMapping, NonExprChildMapping,
1221+
DoUntilStmt
1222+
{
12261223
override predicate relevantChild(Ast child) {
12271224
child = this.getCondition() or super.relevantChild(child)
12281225
}
@@ -1238,7 +1235,9 @@ module StmtNodes {
12381235
ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
12391236
}
12401237

1241-
private class DoWhileStmtChildMapping extends LoopStmtChildMapping, DoWhileStmt {
1238+
private class DoWhileStmtChildMapping extends LoopStmtChildMapping, NonExprChildMapping,
1239+
DoWhileStmt
1240+
{
12421241
override predicate relevantChild(Ast child) {
12431242
child = this.getCondition() or super.relevantChild(child)
12441243
}
@@ -1300,10 +1299,14 @@ module StmtNodes {
13001299
ExprCfgNode getHashTableExpr() { s.hasCfgChild(s.getHashTableExpr(), this, result) }
13011300
}
13021301

1303-
private class ForEachStmtChildMapping extends LoopStmtChildMapping, ForEachStmt {
1302+
private class ForEachStmtChildMapping extends LoopStmtChildMapping, NonExprChildMapping,
1303+
ForEachStmt
1304+
{
13041305
override predicate relevantChild(Ast child) {
13051306
child = this.getVarAccess() or child = this.getIterableExpr() or super.relevantChild(child)
13061307
}
1308+
1309+
override predicate precedesParent(Ast child) { child = this.getIterableExpr() }
13071310
}
13081311

13091312
class ForEachStmtCfgNode extends LoopStmtCfgNode {
@@ -1313,12 +1316,12 @@ module StmtNodes {
13131316

13141317
override ForEachStmt getStmt() { result = s }
13151318

1316-
ExprCfgNode getVarAccess() { s.hasCfgChild(s.getVarAccess(), this, result) }
1319+
ExprNodes::VarAccessCfgNode getVarAccess() { s.hasCfgChild(s.getVarAccess(), this, result) }
13171320

13181321
ExprCfgNode getIterableExpr() { s.hasCfgChild(s.getIterableExpr(), this, result) }
13191322
}
13201323

1321-
private class ForStmtChildMapping extends LoopStmtChildMapping, ForStmt {
1324+
private class ForStmtChildMapping extends LoopStmtChildMapping, NonExprChildMapping, ForStmt {
13221325
override predicate relevantChild(Ast child) {
13231326
child = this.getInitializer() or
13241327
child = this.getCondition() or
@@ -1476,7 +1479,7 @@ module StmtNodes {
14761479
override UsingStmt getStmt() { result = s }
14771480
}
14781481

1479-
private class WhileStmtChildMapping extends LoopStmtChildMapping, WhileStmt {
1482+
private class WhileStmtChildMapping extends LoopStmtChildMapping, NonExprChildMapping, WhileStmt {
14801483
override predicate relevantChild(Ast child) {
14811484
child = this.getCondition() or
14821485
super.relevantChild(child)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
| graph/functions.ps1:29:5:32:5 | forach(... in ...) | graph/functions.ps1:29:14:29:20 | number | graph/functions.ps1:29:25:29:32 | numbers | graph/functions.ps1:29:35:32:5 | {...} |
2+
| graph/loops.ps1:52:5:55:5 | forach(... in ...) | graph/loops.ps1:52:14:52:20 | letter | graph/loops.ps1:52:25:52:36 | letterArray | graph/loops.ps1:53:5:55:5 | {...} |

0 commit comments

Comments
 (0)