Skip to content

Commit 03a7d3d

Browse files
authored
Merge pull request #261 from microsoft/global-flow-through-env-variables-2
PS: Global flow through environment variables
2 parents 5fde177 + b72af27 commit 03a7d3d

File tree

17 files changed

+302
-90
lines changed

17 files changed

+302
-90
lines changed

powershell/ql/lib/semmle/code/powershell/ast/internal/ChildIndex.qll

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,16 @@ newtype ChildIndex =
2626
ExprRedirection(int i) { exists(any(Raw::Cmd cmdExpr).getRedirection(i)) } or
2727
FunDefFun() or
2828
TypeDefType() or
29-
TypeMember(int i) {
30-
exists(any(Raw::TypeStmt typedef).getMember(i))
31-
// or
32-
// hasMemberInType(_, _, i, _)
33-
} or
29+
TypeMember(int i) { exists(any(Raw::TypeStmt typedef).getMember(i)) } or
3430
ThisVar() or
3531
PipelineIteratorVar() or
3632
PipelineByPropertyNameIteratorVar(Raw::PipelineByPropertyNameParameter p) or
3733
RealVar(string name) { name = variableNameInScope(_, _) } or
3834
ProcessBlockPipelineVarReadAccess() or
3935
ProcessBlockPipelineByPropertyNameVarReadAccess(string name) {
4036
name = any(Raw::PipelineByPropertyNameParameter p).getLowerCaseName()
41-
}
37+
} or
38+
EnvVar(string var) { Raw::isEnvVariableAccess(_, var) }
4239

4340
int synthPipelineParameterChildIndex(Raw::ScriptBlock sb) {
4441
// If there is a parameter block, but no pipeline parameter
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
private import AstImport
22

3-
class EnvVariable extends Expr, TEnvVariable {
4-
final override string toString() { result = this.getName() }
3+
class EnvVariable extends Variable instanceof EnvVariableImpl {
4+
string getLowerCaseName() { result = super.getLowerCaseNameImpl() }
55

6-
string getName() { any(Synthesis s).envVariableName(this, result) }
7-
}
6+
bindingset[name]
7+
pragma[inline_late]
8+
final predicate matchesName(string name) { this.getLowerCaseName() = name.toLowerCase() }
9+
10+
bindingset[result]
11+
pragma[inline_late]
12+
final string getAName() { result.toLowerCase() = this.getLowerCaseName() }
813

9-
class SystemDrive extends EnvVariable {
10-
SystemDrive() { this.getName() = "systemdrive" }
11-
}
14+
override Ast getChild(ChildIndex childIndex) { none() }
15+
}

powershell/ql/lib/semmle/code/powershell/ast/internal/Synthesis.qll

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ private import Type
1515
private import Scopes
1616
private import BoolLiteral
1717
private import Member
18-
private import EnvVariable
1918
private import Raw.Raw as Raw
2019
private import codeql.util.Boolean
2120
private import AutomaticVariable
2221

2322
newtype VarKind =
2423
ThisVarKind() or
24+
EnvVarKind(string var) { Raw::isEnvVariableAccess(_, var) } or
2525
ParamVarRealKind() or
2626
PipelineIteratorKind() or
2727
PipelineByPropertyNameIteratorKind(string name) {
@@ -39,7 +39,6 @@ newtype SynthKind =
3939
TypeSynthKind() or
4040
BoolLiteralKind(Boolean b) or
4141
NullLiteralKind() or
42-
EnvVariableKind(string var) { Raw::isEnvVariableAccess(_, var) } or
4342
AutomaticVariableKind(string var) { Raw::isAutomaticVariableAccess(_, var) } or
4443
VarSynthKind(VarKind k)
4544

@@ -96,8 +95,6 @@ class Synthesis extends TSynthesis {
9695

9796
predicate booleanValue(BoolLiteral b, boolean value) { none() }
9897

99-
predicate envVariableName(EnvVariable var, string name) { none() }
100-
10198
predicate automaticVariableName(AutomaticVariable var, string name) { none() }
10299

103100
final string toString() { none() }
@@ -152,6 +149,77 @@ private module ThisSynthesis {
152149
}
153150
}
154151

152+
private module EnvironmentVariables {
153+
bindingset[var]
154+
private Raw::TopLevelScriptBlock getScope(string var) {
155+
result =
156+
min(Raw::TopLevelScriptBlock scriptBlock, Raw::VarAccess va, Location loc |
157+
Raw::isEnvVariableAccess(va, var) and
158+
va.getParent+() = scriptBlock and
159+
loc = scriptBlock.getLocation()
160+
|
161+
scriptBlock order by loc.getFile().getAbsolutePath()
162+
)
163+
}
164+
165+
private class EnvironmentVariables extends Synthesis {
166+
final override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
167+
exists(Raw::VarAccess va, string s0 |
168+
parent = getScope(s0) and
169+
va.getUserPath().toLowerCase() = "env:" + s0 and
170+
Raw::isEnvVariableAccess(va, s0) and
171+
child = SynthChild(VarSynthKind(EnvVarKind(s0))) and
172+
i = EnvVar(s0)
173+
)
174+
}
175+
176+
override predicate variableSynthName(VariableSynth v, string name) {
177+
exists(string name0 |
178+
v = TVariableSynth(_, EnvVar(name0)) and
179+
name = "env:" + name0
180+
)
181+
}
182+
}
183+
}
184+
185+
private module EnvironmentVariableAccessSynth {
186+
private class EnvVarAccessSynthesis extends Synthesis {
187+
final override predicate isRelevant(Raw::Ast a) { Raw::isEnvVariableAccess(a, _) }
188+
189+
final override VarAccess getResultAstImpl(Raw::Ast r) {
190+
exists(Raw::Ast parent, ChildIndex i |
191+
this.envVarAccess(parent, i, _, r, _) and
192+
result = TVarAccessSynth(parent, i)
193+
)
194+
}
195+
196+
private predicate envVarAccess(Raw::Ast parent, ChildIndex i, Child child, Raw::VarAccess va, string var) {
197+
va = parent.getChild(toRawChildIndex(i)) and
198+
Raw::isEnvVariableAccess(va, var) and
199+
child = SynthChild(VarAccessSynthKind(TVariableSynth(_, EnvVar(var))))
200+
}
201+
202+
override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
203+
this.envVarAccess(parent, i, child, _, _)
204+
}
205+
206+
final override predicate getAnAccess(VarAccessSynth va, Variable v) {
207+
exists(Raw::Ast parent, ChildIndex i, string var |
208+
this.envVarAccess(parent, i, _, _, var) and
209+
v = TVariableSynth(_, EnvVar(var)) and
210+
va = TVarAccessSynth(parent, i)
211+
)
212+
}
213+
214+
override Location getLocation(Ast n) {
215+
exists(Raw::Ast scope |
216+
n = TVariableSynth(scope, EnvVar(_)) and
217+
result = scope.getLocation()
218+
)
219+
}
220+
}
221+
}
222+
155223
private module SetVariableAssignment {
156224
private class SetVariableAssignment extends Synthesis {
157225
override predicate explicitAssignment(Raw::Ast dest, string name, Raw::Ast assignment) {
@@ -673,7 +741,6 @@ private module LiteralSynth {
673741
exists(Raw::Ast parent, ChildIndex i | this.child(parent, i, _, r) |
674742
result = TBoolLiteral(parent, i) or
675743
result = TNullLiteral(parent, i) or
676-
result = TEnvVariable(parent, i) or
677744
result = TAutomaticVariable(parent, i)
678745
)
679746
}
@@ -692,12 +759,6 @@ private module LiteralSynth {
692759
s = "null" and
693760
child = SynthChild(NullLiteralKind())
694761
or
695-
exists(string s0 |
696-
s = "env:" + s0 and
697-
Raw::isEnvVariableAccess(va, s0) and
698-
child = SynthChild(EnvVariableKind(s0))
699-
)
700-
or
701762
isAutomaticVariableAccess(va, s) and
702763
child = SynthChild(AutomaticVariableKind(s))
703764
)
@@ -714,13 +775,6 @@ private module LiteralSynth {
714775
)
715776
}
716777

717-
final override predicate envVariableName(EnvVariable var, string name) {
718-
exists(Raw::Ast parent, ChildIndex i |
719-
var = TEnvVariable(parent, i) and
720-
this.child(parent, i, SynthChild(EnvVariableKind(name)))
721-
)
722-
}
723-
724778
final override predicate automaticVariableName(AutomaticVariable var, string name) {
725779
exists(Raw::Ast parent, ChildIndex i |
726780
var = TAutomaticVariable(parent, i) and

powershell/ql/lib/semmle/code/powershell/ast/internal/TAst.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ private module Cached {
160160
TUsingExpr(Raw::UsingExpr u) or
161161
TBoolLiteral(Raw::Ast parent, ChildIndex i) { mkSynthChild(BoolLiteralKind(_), parent, i) } or
162162
TNullLiteral(Raw::Ast parent, ChildIndex i) { mkSynthChild(NullLiteralKind(), parent, i) } or
163-
TEnvVariable(Raw::Ast parent, ChildIndex i) { mkSynthChild(EnvVariableKind(_), parent, i) } or
164163
TAutomaticVariable(Raw::Ast parent, ChildIndex i) {
165164
mkSynthChild(AutomaticVariableKind(_), parent, i)
166165
}
@@ -180,15 +179,15 @@ private module Cached {
180179

181180
class TAstSynth =
182181
TExprStmtSynth or TFunctionSynth or TBoolLiteral or TNullLiteral or TVarAccessSynth or
183-
TEnvVariable or TTypeSynth or TAutomaticVariable or TVariableSynth;
182+
TTypeSynth or TAutomaticVariable or TVariableSynth;
184183

185184
class TExpr =
186185
TArrayExpr or TArrayLiteral or TOperation or TConstExpr or TConvertExpr or TErrorExpr or
187186
THashTableExpr or TIndexExpr or TInvokeMemberExpr or TCmd or TMemberExpr or TPipeline or
188187
TPipelineChain or TStringConstExpr or TConditionalExpr or TVarAccess or
189188
TExpandableStringExpr or TScriptBlockExpr or TExpandableSubExpr or TTypeNameExpr or
190189
TUsingExpr or TAttributedExpr or TIf or TBoolLiteral or TNullLiteral or TThisExpr or
191-
TEnvVariable or TAutomaticVariable or TParenExpr;
190+
TAutomaticVariable or TParenExpr;
192191

193192
class TStmt =
194193
TAssignStmt or TBreakStmt or TContinueStmt or TDataStmt or TDoUntilStmt or TDoWhileStmt or
@@ -308,7 +307,6 @@ private module Cached {
308307
result = TBoolLiteral(parent, i) or
309308
result = TNullLiteral(parent, i) or
310309
result = TVarAccessSynth(parent, i) or
311-
result = TEnvVariable(parent, i) or
312310
result = TTypeSynth(parent, i) or
313311
result = TAutomaticVariable(parent, i) or
314312
result = TVariableSynth(parent, i)

powershell/ql/lib/semmle/code/powershell/ast/internal/Variable.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ module Private {
106106
}
107107
}
108108

109+
class EnvVariableImpl extends VariableSynth {
110+
override EnvVar i;
111+
}
112+
109113
abstract class VarAccessImpl extends Expr, TVarAccess {
110114
abstract VariableImpl getVariableImpl();
111115
}

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,20 +1093,6 @@ module ExprNodes {
10931093
CallExprCfgNode getCall() { result.getPipelineArgument() = this }
10941094
}
10951095

1096-
private class EnvVariableChildMapping extends ExprChildMapping, EnvVariable {
1097-
override predicate relevantChild(Ast child) { none() }
1098-
}
1099-
1100-
class EnvVariableCfgNode extends ExprCfgNode {
1101-
override string getAPrimaryQlClass() { result = "EnvVariableCfgNode" }
1102-
1103-
override EnvVariableChildMapping e;
1104-
1105-
override EnvVariable getExpr() { result = e }
1106-
1107-
string getName() { result = e.getName() }
1108-
}
1109-
11101096
private class OperationChildMapping extends ExprChildMapping, Operation {
11111097
override predicate relevantChild(Ast child) { child = this.getAnOperand() }
11121098
}

powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,8 +736,6 @@ module Trees {
736736

737737
class VarTree extends LeafTree instanceof Variable { }
738738

739-
class EnvVariableTree extends LeafTree instanceof EnvVariable { }
740-
741739
class AutomaticVariableTree extends LeafTree instanceof AutomaticVariable { }
742740

743741
class BinaryExprTree extends StandardPostOrderTree instanceof BinaryExpr {

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,21 @@ module Ssa {
130130
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
131131
}
132132

133+
class InitialEnvVarDefinition extends Definition, SsaImpl::WriteDefinition {
134+
private EnvVariable v;
135+
136+
InitialEnvVarDefinition() {
137+
exists(BasicBlock bb, int i |
138+
this.definesAt(v, bb, i) and
139+
SsaImpl::envVarWrite(bb, i, v)
140+
)
141+
}
142+
143+
final override string toString() { result = "<initial env var> " + v }
144+
145+
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
146+
}
147+
133148
/** phi node. */
134149
class PhiNode extends Definition, SsaImpl::PhiNode {
135150
/** Gets an input of this phi node. */

powershell/ql/lib/semmle/code/powershell/dataflow/flowsources/Local.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ abstract class EnvironmentVariableSource extends LocalFlowSource {
3131
}
3232

3333
private class EnvironmentVariableEnv extends EnvironmentVariableSource {
34-
EnvironmentVariableEnv() { this.asExpr().getExpr() instanceof EnvVariable }
34+
EnvironmentVariableEnv() { this.asExpr().getExpr() = any(EnvVariable env).getAnAccess() }
3535
}
3636

3737
private class ExternalEnvironmentVariableSource extends EnvironmentVariableSource {

0 commit comments

Comments
 (0)