Skip to content

Commit d616506

Browse files
committed
PS: Integrate SSA computations into dataflow.
1 parent c87873b commit d616506

File tree

1 file changed

+130
-18
lines changed

1 file changed

+130
-18
lines changed

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

Lines changed: 130 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ private import codeql.util.Boolean
22
private import codeql.util.Unit
33
private import powershell
44
private import semmle.code.powershell.Cfg
5+
private import semmle.code.powershell.dataflow.Ssa
56
private import DataFlowPublic
67
private import DataFlowDispatch
8+
private import SsaImpl as SsaImpl
79

810
/** Gets the callable in which this node occurs. */
911
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.(NodeImpl).getEnclosingCallable() }
@@ -39,9 +41,40 @@ private class ExprNodeImpl extends ExprNode, NodeImpl {
3941
override string toStringImpl() { result = this.getExprNode().toString() }
4042
}
4143

44+
/** Gets the SSA definition node corresponding to parameter `p`. */
45+
pragma[nomagic]
46+
SsaImpl::DefinitionExt getParameterDef(Parameter p) {
47+
exists(EntryBasicBlock bb, int i |
48+
SsaImpl::parameterWrite(bb, i, p) and
49+
result.definesAt(p, bb, i, _)
50+
)
51+
}
52+
4253
/** Provides logic related to SSA. */
4354
module SsaFlow {
44-
// TODO
55+
private module Impl = SsaImpl::DataFlowIntegration;
56+
57+
private ParameterNodeImpl toParameterNode(SsaImpl::ParameterExt p) {
58+
result = TNormalParameterNode(p.asParameter())
59+
}
60+
61+
Impl::Node asNode(Node n) {
62+
n = TSsaNode(result)
63+
or
64+
result.(Impl::ExprNode).getExpr() = n.asExpr()
65+
or
66+
result.(Impl::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
67+
or
68+
n = toParameterNode(result.(Impl::ParameterNode).getParameter())
69+
}
70+
71+
predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
72+
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep)
73+
}
74+
75+
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
76+
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
77+
}
4578
}
4679

4780
/** Provides predicates related to local data flow. */
@@ -54,19 +87,6 @@ module LocalFlow {
5487
predicate localMustFlowStep(Node node1, Node node2) { none() }
5588
}
5689

57-
/** An argument of a call (including qualifier arguments and block arguments). */
58-
private class Argument extends CfgNodes::ExprCfgNode {
59-
private CfgNodes::StmtNodes::CmdCfgNode call;
60-
private ArgumentPosition arg;
61-
62-
Argument() { none() }
63-
64-
/** Holds if this expression is the `i`th argument of `c`. */
65-
predicate isArgumentOf(CfgNodes::StmtNodes::CmdCfgNode c, ArgumentPosition pos) {
66-
c = call and pos = arg
67-
}
68-
}
69-
7090
/** Provides logic related to captured variables. */
7191
module VariableCapture {
7292
// TODO
@@ -78,8 +98,11 @@ private module Cached {
7898
cached
7999
newtype TNode =
80100
TExprNode(CfgNodes::ExprCfgNode n) or
101+
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
102+
TNormalParameterNode(Parameter p) or
81103
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) {
82-
none() // TODO
104+
n instanceof CfgNodes::ExprNodes::ArgumentCfgNode or
105+
n instanceof CfgNodes::ExprNodes::QualifierCfgNode
83106
}
84107

85108
cached
@@ -117,6 +140,60 @@ import Cached
117140
/** Holds if `n` should be hidden from path explanations. */
118141
predicate nodeIsHidden(Node n) { none() }
119142

143+
/** An SSA node. */
144+
abstract class SsaNode extends NodeImpl, TSsaNode {
145+
SsaImpl::DataFlowIntegration::SsaNode node;
146+
SsaImpl::DefinitionExt def;
147+
148+
SsaNode() {
149+
this = TSsaNode(node) and
150+
def = node.getDefinitionExt()
151+
}
152+
153+
SsaImpl::DefinitionExt getDefinitionExt() { result = def }
154+
155+
/** Holds if this node should be hidden from path explanations. */
156+
abstract predicate isHidden();
157+
158+
override Location getLocationImpl() { result = node.getLocation() }
159+
160+
override string toStringImpl() { result = node.toString() }
161+
}
162+
163+
/** An (extended) SSA definition, viewed as a node in a data flow graph. */
164+
class SsaDefinitionExtNode extends SsaNode {
165+
override SsaImpl::DataFlowIntegration::SsaDefinitionExtNode node;
166+
167+
/** Gets the underlying variable. */
168+
Variable getVariable() { result = def.getSourceVariable() }
169+
170+
override predicate isHidden() {
171+
not def instanceof Ssa::WriteDefinition
172+
or
173+
def = getParameterDef(_)
174+
}
175+
176+
override CfgScope getCfgScope() { result = def.getBasicBlock().getScope() }
177+
}
178+
179+
class SsaDefinitionNodeImpl extends SsaDefinitionExtNode {
180+
Ssa::Definition ssaDef;
181+
182+
SsaDefinitionNodeImpl() { ssaDef = def }
183+
184+
override Location getLocationImpl() { result = ssaDef.getLocation() }
185+
186+
override string toStringImpl() { result = ssaDef.toString() }
187+
}
188+
189+
class SsaInputNode extends SsaNode {
190+
override SsaImpl::DataFlowIntegration::SsaInputNode node;
191+
192+
override predicate isHidden() { any() }
193+
194+
override CfgScope getCfgScope() { result = node.getDefinitionExt().getBasicBlock().getScope() }
195+
}
196+
120197
private module ParameterNodes {
121198
abstract class ParameterNodeImpl extends NodeImpl {
122199
abstract Parameter getParameter();
@@ -130,7 +207,30 @@ private module ParameterNodes {
130207
)
131208
}
132209
}
133-
// TODO
210+
211+
/**
212+
* The value of a normal parameter at function entry, viewed as a node in a data
213+
* flow graph.
214+
*/
215+
class NormalParameterNode extends ParameterNodeImpl, TNormalParameterNode {
216+
Parameter parameter;
217+
218+
NormalParameterNode() { this = TNormalParameterNode(parameter) }
219+
220+
override Parameter getParameter() { result = parameter }
221+
222+
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
223+
exists(CfgScope callable, int i |
224+
callable = c.asCfgScope() and pos.isPositional(i) and callable.getParameter(i) = parameter
225+
)
226+
}
227+
228+
override CfgScope getCfgScope() { result.getAParameter() = parameter }
229+
230+
override Location getLocationImpl() { result = parameter.getLocation() }
231+
232+
override string toStringImpl() { result = parameter.toString() }
233+
}
134234
}
135235

136236
import ParameterNodes
@@ -252,7 +352,19 @@ abstract class PostUpdateNodeImpl extends Node {
252352
}
253353

254354
private module PostUpdateNodes {
255-
// TODO
355+
class ExprPostUpdateNode extends PostUpdateNodeImpl, NodeImpl, TExprPostUpdateNode {
356+
private CfgNodes::ExprCfgNode e;
357+
358+
ExprPostUpdateNode() { this = TExprPostUpdateNode(e) }
359+
360+
override ExprNode getPreUpdateNode() { e = result.getExprNode() }
361+
362+
override CfgScope getCfgScope() { result = e.getExpr().getEnclosingScope() }
363+
364+
override Location getLocationImpl() { result = e.getLocation() }
365+
366+
override string toStringImpl() { result = "[post] " + e.toString() }
367+
}
256368
}
257369

258370
private import PostUpdateNodes
@@ -276,7 +388,7 @@ class NodeRegion instanceof Unit {
276388
predicate contains(Node n) { none() }
277389

278390
/** Gets a best-effort total ordering. */
279-
int totalOrder() { none() }
391+
int totalOrder() { result = 1 }
280392
}
281393

282394
/**

0 commit comments

Comments
 (0)