Skip to content

Commit 43c7550

Browse files
committed
PS: Also support method calls as calls.
1 parent e36e617 commit 43c7550

File tree

4 files changed

+70
-42
lines changed

4 files changed

+70
-42
lines changed

powershell/ql/lib/semmle/code/powershell/Call.qll

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,27 @@ import powershell
33
abstract private class AbstractCall extends Ast {
44
abstract Expr getCommand();
55

6+
/** Gets the i'th argument to this call. */
67
abstract Expr getArgument(int i);
78

8-
Expr getNamedArgument(string name) { none() }
9+
/** Gets the i'th positional argument to this call. */
10+
abstract Expr getPositionalArgument(int i);
911

10-
Expr getAnArgument() { result = this.getArgument(_) or result = this.getNamedArgument(_) }
12+
/** Gets the argument to this call with the name `name`. */
13+
abstract Expr getNamedArgument(string name);
1114

15+
/** Gets any argument to this call. */
16+
final Expr getAnArgument() { result = this.getArgument(_) }
17+
18+
/** Gets the qualifier of this call, if any. */
1219
Expr getQualifier() { none() }
1320
}
1421

1522
private class CmdCall extends AbstractCall instanceof Cmd {
1623
final override Expr getCommand() { result = Cmd.super.getCommand() }
1724

25+
final override Expr getPositionalArgument(int i) { result = Cmd.super.getPositionalArgument(i) }
26+
1827
final override Expr getArgument(int i) { result = Cmd.super.getArgument(i) }
1928

2029
final override Expr getNamedArgument(string name) { result = Cmd.super.getNamedArgument(name) }
@@ -23,9 +32,15 @@ private class CmdCall extends AbstractCall instanceof Cmd {
2332
private class InvokeMemberCall extends AbstractCall instanceof InvokeMemberExpr {
2433
final override Expr getCommand() { result = super.getMember() }
2534

26-
final override Expr getArgument(int i) { result = InvokeMemberExpr.super.getArgument(i) }
35+
final override Expr getPositionalArgument(int i) {
36+
result = InvokeMemberExpr.super.getArgument(i)
37+
}
38+
39+
final override Expr getArgument(int i) { result = this.getPositionalArgument(i) }
2740

2841
final override Expr getQualifier() { result = InvokeMemberExpr.super.getQualifier() }
42+
43+
final override Expr getNamedArgument(string name) { none() }
2944
}
3045

3146
final class Call = AbstractCall;

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

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,22 @@ abstract private class NonExprChildMapping extends ChildMapping {
125125
}
126126
}
127127

128+
abstract private class AbstractCallCfgNode extends AstCfgNode {
129+
override string getAPrimaryQlClass() { result = "CfgCall" }
130+
131+
ExprCfgNode getQualifier() { none() }
132+
133+
abstract ExprCfgNode getArgument(int i);
134+
135+
abstract ExprCfgNode getPositionalArgument(int i);
136+
137+
abstract ExprCfgNode getNamedArgument(string name);
138+
139+
abstract ExprCfgNode getAnArgument();
140+
}
141+
142+
final class CallCfgNode = AbstractCallCfgNode;
143+
128144
/** Provides classes for control-flow nodes that wrap AST expressions. */
129145
module ExprNodes {
130146
private class VarAccessChildMapping extends ExprChildMapping, VarAccess {
@@ -189,14 +205,22 @@ module ExprNodes {
189205
}
190206

191207
/** A control-flow node that wraps an `InvokeMemberExpr` expression. */
192-
class InvokeMemberCfgNode extends ExprCfgNode {
208+
class InvokeMemberCfgNode extends ExprCfgNode, AbstractCallCfgNode {
193209
override string getAPrimaryQlClass() { result = "InvokeMemberCfgNode" }
194210

195211
override InvokeMemberChildMapping e;
196212

197213
final override InvokeMemberExpr getExpr() { result = super.getExpr() }
198214

199-
final ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
215+
final override ExprCfgNode getQualifier() { e.hasCfgChild(e.getQualifier(), this, result) }
216+
217+
final override ExprCfgNode getArgument(int i) { e.hasCfgChild(e.getArgument(i), this, result) }
218+
219+
final override ExprCfgNode getPositionalArgument(int i) { result = this.getArgument(i) }
220+
221+
final override ExprCfgNode getNamedArgument(string name) { none() }
222+
223+
final override ExprCfgNode getAnArgument() { e.hasCfgChild(e.getAnArgument(), this, result) }
200224
}
201225

202226
/** A control-flow node that wraps a qualifier expression. */
@@ -265,24 +289,24 @@ module StmtNodes {
265289
}
266290

267291
/** A control-flow node that wraps a `Cmd` AST expression. */
268-
class CmdCfgNode extends StmtCfgNode {
292+
class CmdCfgNode extends StmtCfgNode, AbstractCallCfgNode {
269293
override string getAPrimaryQlClass() { result = "CmdCfgNode" }
270294

271295
override CmdChildMapping s;
272296

273297
override Cmd getStmt() { result = super.getStmt() }
274298

275-
ExprCfgNode getArgument(int i) { s.hasCfgChild(s.getArgument(i), this, result) }
299+
override ExprCfgNode getArgument(int i) { s.hasCfgChild(s.getArgument(i), this, result) }
276300

277-
ExprCfgNode getPositionalArgument(int i) {
301+
override ExprCfgNode getPositionalArgument(int i) {
278302
s.hasCfgChild(s.getPositionalArgument(i), this, result)
279303
}
280304

281-
ExprCfgNode getNamedArgument(string name) {
305+
override ExprCfgNode getNamedArgument(string name) {
282306
s.hasCfgChild(s.getNamedArgument(name), this, result)
283307
}
284308

285-
ExprCfgNode getAnArgument() { s.hasCfgChild(s.getAnArgument(), this, result) }
309+
override ExprCfgNode getAnArgument() { s.hasCfgChild(s.getAnArgument(), this, result) }
286310

287311
ExprCfgNode getCommand() { s.hasCfgChild(s.getCommand(), this, result) }
288312
}

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

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ abstract class DataFlowCall extends TDataFlowCall {
7777
abstract DataFlowCallable getEnclosingCallable();
7878

7979
/** Gets the underlying source code call, if any. */
80-
abstract CfgNodes::StmtNodes::CmdCfgNode asCall();
80+
abstract CfgNodes::CallCfgNode asCall();
8181

8282
/** Gets a textual representation of this call. */
8383
abstract string toString();
@@ -107,11 +107,11 @@ abstract class DataFlowCall extends TDataFlowCall {
107107
}
108108

109109
class NormalCall extends DataFlowCall, TNormalCall {
110-
private CfgNodes::StmtNodes::CmdCfgNode c;
110+
private CfgNodes::CallCfgNode c;
111111

112112
NormalCall() { this = TNormalCall(c) }
113113

114-
override CfgNodes::StmtNodes::CmdCfgNode asCall() { result = c }
114+
override CfgNodes::CallCfgNode asCall() { result = c }
115115

116116
override DataFlowCallable getEnclosingCallable() { result = TCfgScope(c.getScope()) }
117117

@@ -121,7 +121,7 @@ class NormalCall extends DataFlowCall, TNormalCall {
121121
}
122122

123123
/** A call for which we want to compute call targets. */
124-
private class RelevantCall extends CfgNodes::StmtNodes::CmdCfgNode { }
124+
private class RelevantCall extends CfgNodes::CallCfgNode { }
125125

126126
/** Holds if `call` may resolve to the returned source-code method. */
127127
private DataFlowCallable viableSourceCallable(DataFlowCall call) {
@@ -139,15 +139,7 @@ class AdditionalCallTarget extends Unit {
139139
/**
140140
* Gets a viable target for `call`.
141141
*/
142-
abstract DataFlowCallable viableTarget(CfgNodes::StmtNodes::CmdCfgNode call);
143-
}
144-
145-
/** Holds if `call` may resolve to the returned summarized library method. */
146-
DataFlowCallable viableLibraryCallable(DataFlowCall call) {
147-
exists(LibraryCallable callable |
148-
result = TLibraryCallable(callable) and
149-
call.asCall().getStmt() = callable.getACall()
150-
)
142+
abstract DataFlowCallable viableTarget(CfgNodes::CallCfgNode call);
151143
}
152144

153145
cached
@@ -158,33 +150,29 @@ private module Cached {
158150
TLibraryCallable(LibraryCallable callable)
159151

160152
cached
161-
newtype TDataFlowCall = TNormalCall(CfgNodes::StmtNodes::CmdCfgNode c)
153+
newtype TDataFlowCall = TNormalCall(CfgNodes::CallCfgNode c)
162154

163155
/** Gets a viable run-time target for the call `call`. */
164156
cached
165-
DataFlowCallable viableCallable(DataFlowCall call) {
166-
result = viableSourceCallable(call)
167-
or
168-
result = viableLibraryCallable(call)
169-
}
157+
DataFlowCallable viableCallable(DataFlowCall call) { result = viableSourceCallable(call) }
170158

171159
cached
172160
newtype TArgumentPosition =
173161
TKeywordArgumentPosition(string name) { name = any(CmdParameter p).getName() } or
174162
TPositionalArgumentPosition(int pos, NamedSet ns) {
175-
exists(Cmd cmd |
176-
cmd = ns.getABindingCall() and
177-
exists(cmd.getArgument(pos))
163+
exists(CfgNodes::CallCfgNode call |
164+
call = ns.getABindingCall() and
165+
exists(call.getArgument(pos))
178166
)
179167
}
180168

181169
cached
182170
newtype TParameterPosition =
183171
TKeywordParameter(string name) { name = any(CmdParameter p).getName() } or
184172
TPositionalParameter(int pos, NamedSet ns) {
185-
exists(Cmd cmd |
186-
cmd = ns.getABindingCall() and
187-
exists(cmd.getArgument(pos))
173+
exists(CfgNodes::CallCfgNode call |
174+
call = ns.getABindingCall() and
175+
exists(call.getArgument(pos))
188176
)
189177
}
190178
}

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -229,9 +229,10 @@ class SsaInputNode extends SsaNode {
229229
override CfgScope getCfgScope() { result = node.getDefinitionExt().getBasicBlock().getScope() }
230230
}
231231

232-
private string getANamedArgument(Cmd c) { exists(c.getNamedArgument(result)) }
232+
private string getANamedArgument(CfgNodes::CallCfgNode c) { exists(c.getNamedArgument(result)) }
233233

234-
private module NamedSetModule = QlBuiltins::InternSets<Cmd, string, getANamedArgument/1>;
234+
private module NamedSetModule =
235+
QlBuiltins::InternSets<CfgNodes::CallCfgNode, string, getANamedArgument/1>;
235236

236237
private newtype NamedSet0 =
237238
TEmptyNamedSet() or
@@ -257,11 +258,11 @@ class NamedSet extends NamedSet0 {
257258
}
258259

259260
/**
260-
* Gets a `Cmd` that provides a named parameter for every name in `this`.
261+
* Gets a `CfgNodes::CallCfgNode` that provides a named parameter for every name in `this`.
261262
*
262-
* NOTE: The `Cmd` may also provide more names.
263+
* NOTE: The `CfgNodes::CallCfgNode` may also provide more names.
263264
*/
264-
Cmd getABindingCall() {
265+
CfgNodes::CallCfgNode getABindingCall() {
265266
forex(string name | name = this.getAName() | exists(result.getNamedArgument(name)))
266267
or
267268
this.isEmpty() and
@@ -272,7 +273,7 @@ class NamedSet extends NamedSet0 {
272273
* Gets a `Cmd` that provides exactly the named parameters represented by
273274
* this set.
274275
*/
275-
Cmd getAnExactBindingCall() {
276+
CfgNodes::CallCfgNode getAnExactBindingCall() {
276277
forex(string name | name = this.getAName() | exists(result.getNamedArgument(name))) and
277278
forex(string name | exists(result.getNamedArgument(name)) | name = this.getAName())
278279
or
@@ -366,7 +367,7 @@ module ArgumentNodes {
366367
or
367368
exists(NamedSet ns, int i |
368369
i = arg.getPosition() and
369-
ns.getAnExactBindingCall() = call.asCall().getStmt() and
370+
ns.getAnExactBindingCall() = call.asCall() and
370371
pos.isPositional(i, ns)
371372
)
372373
)

0 commit comments

Comments
 (0)