Skip to content

Commit a6a157a

Browse files
committed
PS: Add initial parameter definitions.
1 parent f0429fa commit a6a157a

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

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

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,24 @@ class VarAccess extends @variable_expression, Expr {
3434
Variable getVariable() { result.getAnAccess() = this }
3535
}
3636

37-
private predicate isVariableWriteAccess(Expr e) {
38-
e = any(AssignStmt assign).getLeftHandSide()
37+
private predicate isExplicitVariableWriteAccess(Expr e, AssignStmt assign) {
38+
e = assign.getLeftHandSide()
3939
or
40-
e = any(ConvertExpr convert | isVariableWriteAccess(convert)).getExpr()
40+
e = any(ConvertExpr convert | isExplicitVariableWriteAccess(convert, assign)).getExpr()
4141
or
42-
e = any(ArrayLiteral array | isVariableWriteAccess(array)).getAnElement()
42+
e = any(ArrayLiteral array | isExplicitVariableWriteAccess(array, assign)).getAnElement()
4343
}
4444

45+
private predicate isImplicitVariableWriteAccess(Expr e) { none() }
46+
4547
class VarReadAccess extends VarAccess {
4648
VarReadAccess() { not this instanceof VarWriteAccess }
4749
}
4850

4951
class VarWriteAccess extends VarAccess {
50-
VarWriteAccess() { isVariableWriteAccess(this) }
52+
VarWriteAccess() { isExplicitVariableWriteAccess(this, _) or isImplicitVariableWriteAccess(this) }
53+
54+
predicate isExplicit(AssignStmt assign) { isExplicitVariableWriteAccess(this, assign) }
55+
56+
predicate isImplicit() { isImplicitVariableWriteAccess(this) }
5157
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ module ExprNodes {
163163
predicate isExplicitWrite(StmtNodes::AssignStmtCfgNode assignment) {
164164
this = assignment.getLeftHandSide()
165165
}
166+
167+
predicate isImplicitWrite() { e.isImplicit() }
166168
}
167169
}
168170

powershell/ql/lib/semmle/code/powershell/dataflow/Ssa.qll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,21 @@ module Ssa {
103103
final override Location getLocation() { result = write.getLocation() }
104104
}
105105

106+
class ParameterDefinition extends Definition, SsaImpl::WriteDefinition {
107+
private Variable v;
108+
109+
ParameterDefinition() {
110+
exists(BasicBlock bb, int i |
111+
this.definesAt(v, bb, i) and
112+
SsaImpl::parameterWrite(bb, i, v)
113+
)
114+
}
115+
116+
final override string toString() { result = "<parameter> " + v }
117+
118+
final override Location getLocation() { result = v.getLocation() }
119+
}
120+
106121
/**
107122
* An SSA definition inserted at the beginning of a scope to represent an
108123
* uninitialized local variable.

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

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
2929
(
3030
uninitializedWrite(bb, i, v)
3131
or
32+
parameterWrite(bb, i, v)
33+
or
3234
variableWriteActual(bb, i, v, _)
3335
) and
3436
certain = true
@@ -58,6 +60,39 @@ predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
5860
i = -1
5961
}
6062

63+
/**
64+
* Gets index of `p` in a version of the enclosing function where the parameter
65+
* list is reversed.
66+
*
67+
* For example, given
68+
* ```ps
69+
* function f($a, $b) { ... }
70+
* ```
71+
* the inverted index of `$a` is 1, and the inverted index of `$b` is 0.
72+
*/
73+
private int getInvertedIndex(Parameter p) {
74+
exists(int i |
75+
p.getIndex() = i or
76+
p.hasParameterBlock(_, i)
77+
|
78+
result = p.getFunction().getNumberOfParameters() - i - 1
79+
)
80+
}
81+
82+
/**
83+
* Holds if the the SSA definition of `p` should be placed at index `i` in
84+
* block `bb`. Note that the index may be negative.
85+
*/
86+
predicate parameterWrite(Cfg::EntryBasicBlock bb, int i, Parameter p) {
87+
exists(Function f |
88+
f.getEntryBasicBlock() = bb and
89+
p.getFunction() = f and
90+
// If the enclosing function has 2 parameters we map the index of parameter
91+
// 0 to -2, the index of parameter 1 to -1.
92+
i = -getInvertedIndex(p) - 1
93+
)
94+
}
95+
6196
/** Holds if `v` is read at index `i` in basic block `bb`. */
6297
private predicate variableReadActual(Cfg::BasicBlock bb, int i, LocalScopeVariable v) {
6398
exists(VarReadAccess read |
@@ -159,6 +194,9 @@ private module Cached {
159194
n = bb.getNode(i)
160195
|
161196
write.isExplicitWrite(n)
197+
or
198+
write.isImplicitWrite() and
199+
n = write
162200
)
163201
}
164202

@@ -281,19 +319,20 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
281319
override Location getLocation() { result = Impl::PhiReadNode.super.getLocation() }
282320
}
283321

284-
abstract class NormalParameter extends Parameter { }
285-
286322
/** Gets the SSA definition node corresponding to parameter `p`. */
287323
pragma[nomagic]
288324
DefinitionExt getParameterDef(Parameter p) {
289-
none() // TODO
325+
exists(Cfg::EntryBasicBlock bb, int i |
326+
parameterWrite(bb, i, p) and
327+
result.definesAt(p, bb, i, _)
328+
)
290329
}
291330

292-
private newtype TParameterExt = TNormalParameter(NormalParameter p)
331+
private newtype TParameterExt = TNormalParameter(Parameter p)
293332

294333
/** A normal parameter or an implicit `self` parameter. */
295334
class ParameterExt extends TParameterExt {
296-
NormalParameter asParameter() { this = TNormalParameter(result) }
335+
Parameter asParameter() { this = TNormalParameter(result) }
297336

298337
predicate isInitializedBy(WriteDefinition def) { def = getParameterDef(this.asParameter()) }
299338

0 commit comments

Comments
 (0)