Skip to content

Commit f103fed

Browse files
committed
PS: Use ! to mark static members/methods.
1 parent 50c0551 commit f103fed

File tree

11 files changed

+200
-98
lines changed

11 files changed

+200
-98
lines changed

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

Lines changed: 45 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,25 @@ module API {
326326

327327
/** A node representing a module/class object with epsilon edges to its descendents. */
328328
private class ModuleNode extends Node, Impl::MkModule {
329-
/** Gets the module represented by this API node. */
330-
string getModule() { this = Impl::MkModule(result) }
329+
string qualifiedModule;
330+
int n;
331331

332-
override string toString() { result = "Module(" + this.getModule() + ")" }
332+
ModuleNode() { this = Impl::MkModule(qualifiedModule, n) }
333333

334-
TypeNode getType(string name) { result.getType() = this.getModule() + "." + name } // TODO: Check that name exists in module
335-
}
334+
ModuleNode getNext() { result = Impl::MkModule(qualifiedModule, n + 1) }
335+
336+
ModuleNode getPred() { result.getNext() = this }
337+
338+
string getComponent() { result = qualifiedModule.splitAt(".", n) }
336339

337-
private class TypeNode extends Node, Impl::MkType {
338-
/** Gets the type represented by this API node. */
339-
string getType() { this = Impl::MkType(result) }
340+
string getModule() {
341+
not exists(this.getPred()) and
342+
result = this.getComponent()
343+
or
344+
result = this.getPred().getModule() + "." + this.getComponent()
345+
}
340346

341-
override string toString() { result = "Type(" + this.getType() + ")" }
347+
override string toString() { result = "Module(" + this.getModule() + ")" }
342348
}
343349

344350
/** A node representing instances of a module/class with epsilon edges to its ancestors. */
@@ -413,13 +419,7 @@ module API {
413419
* Gets the node that represents the module with qualified
414420
* name `qualifiedModule`.
415421
*/
416-
ModuleNode mod(string qualifiedModule) { result = Impl::MkModule(qualifiedModule) }
417-
418-
/**
419-
* Gets the node that represents the type with qualified
420-
* name `qualifiedType`.
421-
*/
422-
TypeNode type(string qualifiedType) { result = Impl::MkType(qualifiedType) }
422+
ModuleNode mod(string qualifiedModule, int n) { result = Impl::MkModule(qualifiedModule, n) }
423423

424424
/**
425425
* Gets an unqualified call at the top-level with the given method name.
@@ -466,26 +466,31 @@ module API {
466466

467467
cached
468468
private module Impl {
469+
470+
private predicate isModule(string s, int n) {
471+
(
472+
any(UsingStmt using).getName() = s
473+
or
474+
any(Cmd cmd).getNamespaceQualifier() = s
475+
or
476+
any(TypeNameExpr tn).getName() = s
477+
or
478+
any(ModuleManifest manifest).getModuleName() = s
479+
) and
480+
exists(s.splitAt(".", n))
481+
}
482+
469483
cached
470484
newtype TApiNode =
471485
/** The root of the API graph. */
472486
MkRoot() or
473487
/** The method accessed at `call`, synthetically treated as a separate object. */
474488
MkMethodAccessNode(DataFlow::CallNode call) or
475-
MkModule(string qualifiedModule) {
476-
any(UsingStmt using).getName() = qualifiedModule
477-
or
478-
any(Cmd cmd).getNamespaceQualifier() = qualifiedModule
479-
or
480-
any(TypeNameExpr tn).getName() = qualifiedModule
481-
or
482-
any(ModuleManifest manifest).getModuleName() = qualifiedModule
483-
} or
484-
MkType(string qualifiedType) { any(ConstantValue cv).asString() = qualifiedType } or // TODO
489+
MkModule(string qualifiedModule, int n) { isModule(qualifiedModule, n) } or
485490
/** Instances of `mod` with epsilon edges to its ancestors. */
486-
MkInstanceUp(string qualifiedType) { exists(MkType(qualifiedType)) } or
491+
MkInstanceUp(string qualifiedType) { exists(MkModule(qualifiedType, _)) } or
487492
/** Instances of `mod` with epsilon edges to its descendents, and to its upward node. */
488-
MkInstanceDown(string qualifiedType) { exists(MkType(qualifiedType)) } or
493+
MkInstanceDown(string qualifiedType) { exists(MkModule(qualifiedType, _)) } or
489494
/** Intermediate node for following forward data flow. */
490495
MkForwardNode(DataFlow::LocalSourceNode node, TypeTracker t) { isReachable(node, t) } or
491496
/** Intermediate node for following backward data flow. */
@@ -525,14 +530,6 @@ module API {
525530
)
526531
}
527532

528-
cached
529-
predicate typeEdge(Node pred, string name, Node succ) {
530-
exists(ModuleNode mod |
531-
pred = mod and
532-
succ = mod.getType(name)
533-
)
534-
}
535-
536533
cached
537534
predicate memberEdge(Node pred, string name, Node succ) {
538535
exists(MemberExpr member | succ = getForwardStartNode(getNodeFromExpr(member)) |
@@ -546,8 +543,9 @@ module API {
546543
exists(DataFlow::CallNode call | succ = MkMethodAccessNode(call) and name = call.getName() |
547544
pred = getForwardEndNode(getALocalSourceStrict(call.getQualifier()))
548545
or
549-
exists(string qualifiedModule, ModuleManifest manifest |
550-
pred = mod(qualifiedModule) and
546+
exists(string qualifiedModule, ModuleManifest manifest, int n |
547+
pred = mod(qualifiedModule, n) and
548+
not exists(mod(qualifiedModule, n + 1)) and
551549
manifest.getModuleName() = qualifiedModule
552550
|
553551
manifest.getACmdLetToExport() = name
@@ -647,8 +645,15 @@ module API {
647645

648646
cached
649647
predicate instanceEdge(Node pred, Node succ) {
650-
// An instance of a type
651-
exists(string qualifiedType | pred = MkType(qualifiedType) |
648+
exists(string qualifiedType, int n |
649+
pred = MkModule(qualifiedType, n) and
650+
not exists(MkModule(qualifiedType, n + 1))
651+
|
652+
exists(DataFlow::TypeNameNode typeName |
653+
typeName.getTypeName() = qualifiedType and
654+
succ = getForwardStartNode(typeName)
655+
)
656+
or
652657
exists(DataFlow::ObjectCreationNode objCreation |
653658
objCreation.getConstructedTypeName() = qualifiedType and
654659
succ = getForwardStartNode(objCreation)
@@ -659,15 +664,6 @@ module API {
659664
succ = getForwardStartNode(p)
660665
)
661666
)
662-
or
663-
// A use of a module (or static type?)
664-
// TODO: Consider implicit module qualiifers and use instance on all of them
665-
exists(string qualifiedType, DataFlow::TypeNameNode typeName |
666-
pred = MkModule(qualifiedType) and
667-
typeName.getTypeName() = qualifiedType
668-
|
669-
succ = getForwardStartNode(typeName)
670-
)
671667
}
672668

673669
cached

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,13 @@ module StmtNodes {
610610

611611
final override ExprCfgNode getCommand() { s.hasCfgChild(s.getCommand(), this, result) }
612612

613-
final override string getName() { result = s.getCmdName().getValue().getValue() }
613+
final override string getName() { result = s.getCommandName() }
614+
615+
/** Holds if the command is qualified. */
616+
predicate isQualified() { s.isQualified() }
617+
618+
/** Gets the namespace qualifier of this command, if any. */
619+
string getNamespaceQualifier() { result = s.getNamespaceQualifier() }
614620
}
615621

616622
/** A control-flow node that wraps a call to operator `&` */

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ private module Cached {
202202
isProcessPropertyByNameNode(iter, _)
203203
} or
204204
TScriptBlockNode(ScriptBlock scriptBlock) or
205+
TTypePathNode(int n, CfgNode cfg) { isTypePathNode(_, n, cfg) } or
205206
TForbiddenRecursionGuard() {
206207
none() and
207208
// We want to prune irrelevant models before materialising data flow nodes, so types contributed
@@ -1148,6 +1149,64 @@ class ScriptBlockNode extends TScriptBlockNode, NodeImpl {
11481149
override predicate nodeIsHidden() { any() }
11491150
}
11501151

1152+
private predicate isTypePathNode(string type, int n, CfgNode cfg) {
1153+
exists(CfgNodes::ExprNodes::TypeNameCfgNode typeName, string s |
1154+
cfg = typeName and
1155+
type = typeName.getTypeName() and
1156+
s = type.splitAt(".", n)
1157+
)
1158+
or
1159+
exists(CfgNodes::StmtNodes::CmdCfgNode cmd, string s |
1160+
cfg = cmd.getCommand() and
1161+
type = cmd.getNamespaceQualifier() and
1162+
s = type.splitAt(".", n)
1163+
)
1164+
}
1165+
1166+
/**
1167+
* A dataflow node that represents a component of a type or module path.
1168+
*
1169+
* For example, `System`, `System.Management`, `System.Management.Automation`,
1170+
* and `System.Management.Automation.PowerShell` in the type
1171+
* name `[System.Management.Automation.PowerShell]`.
1172+
*/
1173+
class TypePathNodeImpl extends TTypePathNode, NodeImpl {
1174+
int n;
1175+
CfgNode cfg;
1176+
1177+
TypePathNodeImpl() { this = TTypePathNode(n, cfg) }
1178+
1179+
string getType() { isTypePathNode(result, n, cfg) }
1180+
1181+
predicate isComplete() { not exists(this.getNext()) }
1182+
1183+
int getIndex() { result = n }
1184+
1185+
string getComponent() { result = this.getType().splitAt(".", n) }
1186+
1187+
override CfgScope getCfgScope() { result = cfg.getScope() }
1188+
1189+
override Location getLocationImpl() { result = cfg.getLocation() }
1190+
1191+
override string toStringImpl() {
1192+
not exists(this.getPrev()) and
1193+
result = this.getComponent()
1194+
or
1195+
result = this.getPrev() + "." + this.getComponent()
1196+
}
1197+
1198+
override predicate nodeIsHidden() { any() }
1199+
1200+
TypePathNodeImpl getNext() { result = TTypePathNode(n + 1, cfg) }
1201+
1202+
TypePathNodeImpl getPrev() { result.getNext() = this }
1203+
1204+
TypePathNodeImpl getConstant(string s) {
1205+
s = result.getComponent() and
1206+
result = this.getNext()
1207+
}
1208+
}
1209+
11511210
/** A node that performs a type cast. */
11521211
class CastNode extends Node {
11531212
CastNode() { none() }

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,21 @@ class PostUpdateNode extends Node {
193193
Node getPreUpdateNode() { result = pre }
194194
}
195195

196+
/**
197+
* A dataflow node that represents a component of a type or module path.
198+
*
199+
* For example, `System`, `System.Management`, `System.Management.Automation`,
200+
* and `System.Management.Automation.PowerShell` in the type
201+
* name `[System.Management.Automation.PowerShell]`.
202+
*/
203+
class TypePathNode extends Node instanceof TypePathNodeImpl {
204+
string getComponent() { result = super.getComponent() }
205+
206+
TypePathNode getConstant(string s) { result = super.getConstant(s) }
207+
208+
API::Node track() { result = API::mod(super.getType(), super.getIndex()) }
209+
}
210+
196211
cached
197212
private module Cached {
198213
cached

powershell/ql/lib/semmle/code/powershell/frameworks/MicrosoftPowershellUtility/model.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["Microsoft.PowerShell.Utility", "Method[Read-Host].ReturnValue", "stdin"]
6+
- ["Microsoft.PowerShell.Utility!", "Method[Read-Host].ReturnValue", "stdin"]

powershell/ql/lib/semmle/code/powershell/frameworks/MicrosoftWin32Registry/model.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["Microsoft.Win32.Registry", "Method[GetValue]", "windows-registry"]
6+
- ["Microsoft.Win32.Registry!", "Method[GetValue]", "windows-registry"]

powershell/ql/lib/semmle/code/powershell/frameworks/MicrosoftWin32RegistryKey/model.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["Microsoft.Win32.RegistryKey", "Instance.Method[GetValue].ReturnValue", "windows-registry"]
7-
- ["Microsoft.Win32.RegistryKey", "Instance.Method[GetValueNames].ReturnValue", "windows-registry"]
8-
- ["Microsoft.Win32.RegistryKey", "Instance.Method[GetSubKeyNames].ReturnValue", "windows-registry"]
6+
- ["Microsoft.Win32.RegistryKey", "Method[GetValue].ReturnValue", "windows-registry"]
7+
- ["Microsoft.Win32.RegistryKey", "Method[GetValueNames].ReturnValue", "windows-registry"]
8+
- ["Microsoft.Win32.RegistryKey", "Method[GetSubKeyNames].ReturnValue", "windows-registry"]

powershell/ql/lib/semmle/code/powershell/frameworks/SystemEnvironment/model.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["System.Environment", "Method[ExpandEnvironmentVariables].ReturnValue", "environment"]
7-
- ["System.Environment", "Method[GetCommandLineArgs].ReturnValue", "commandargs"]
8-
- ["System.Environment", "Method[GetEnvironmentVariable].ReturnValue", "environment"]
9-
- ["System.Environment", "Method[GetEnvironmentVariables].ReturnValue", "environment"]
6+
- ["System.Environment!", "Method[ExpandEnvironmentVariables].ReturnValue", "environment"]
7+
- ["System.Environment!", "Method[GetCommandLineArgs].ReturnValue", "commandargs"]
8+
- ["System.Environment!", "Method[GetEnvironmentVariable].ReturnValue", "environment"]
9+
- ["System.Environment!", "Method[GetEnvironmentVariables].ReturnValue", "environment"]

powershell/ql/lib/semmle/code/powershell/frameworks/SystemIOFile/model.yml

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["System.IO.File", "Method[AppendText].ReturnValue", "file-write"]
7-
- ["System.IO.File", "Method[Create].ReturnValue", "file-write"]
8-
- ["System.IO.File", "Method[CreateText].ReturnValue", "file-write"]
9-
- ["System.IO.File", "Method[Open].ReturnValue", "file-write"]
10-
- ["System.IO.File", "Method[Open].ReturnValue", "file"]
11-
- ["System.IO.File", "Method[OpenRead].ReturnValue", "file"]
12-
- ["System.IO.File", "Method[OpenText].ReturnValue", "file"]
13-
- ["System.IO.File", "Method[OpenWrite].ReturnValue", "file-write"]
14-
- ["System.IO.File", "Method[ReadAllBytes].ReturnValue", "file"]
15-
- ["System.IO.File", "Method[ReadAllBytesAsync].ReturnValue", "file"]
16-
- ["System.IO.File", "Method[ReadAllLines].ReturnValue", "file"]
17-
- ["System.IO.File", "Method[ReadAllLinesAsync].ReturnValue", "file"]
18-
- ["System.IO.File", "Method[ReadAllText].ReturnValue", "file"]
19-
- ["System.IO.File", "Method[ReadAllTextAsync].ReturnValue", "file"]
20-
- ["System.IO.File", "Method[ReadLines].ReturnValue", "file"]
21-
- ["System.IO.File", "Method[ReadLinesAsync].ReturnValue", "file"]
6+
- ["System.IO.File!", "Method[AppendText].ReturnValue", "file-write"]
7+
- ["System.IO.File!", "Method[Create].ReturnValue", "file-write"]
8+
- ["System.IO.File!", "Method[CreateText].ReturnValue", "file-write"]
9+
- ["System.IO.File!", "Method[Open].ReturnValue", "file-write"]
10+
- ["System.IO.File!", "Method[Open].ReturnValue", "file"]
11+
- ["System.IO.File!", "Method[OpenRead].ReturnValue", "file"]
12+
- ["System.IO.File!", "Method[OpenText].ReturnValue", "file"]
13+
- ["System.IO.File!", "Method[OpenWrite].ReturnValue", "file-write"]
14+
- ["System.IO.File!", "Method[ReadAllBytes].ReturnValue", "file"]
15+
- ["System.IO.File!", "Method[ReadAllBytesAsync].ReturnValue", "file"]
16+
- ["System.IO.File!", "Method[ReadAllLines].ReturnValue", "file"]
17+
- ["System.IO.File!", "Method[ReadAllLinesAsync].ReturnValue", "file"]
18+
- ["System.IO.File!", "Method[ReadAllText].ReturnValue", "file"]
19+
- ["System.IO.File!", "Method[ReadAllTextAsync].ReturnValue", "file"]
20+
- ["System.IO.File!", "Method[ReadLines].ReturnValue", "file"]
21+
- ["System.IO.File!", "Method[ReadLinesAsync].ReturnValue", "file"]

powershell/ql/lib/semmle/code/powershell/frameworks/SystemIOFileInfo/model.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ extensions:
33
pack: microsoft-sdl/powershell-all
44
extensible: sourceModel
55
data:
6-
- ["System.IO.FileInfo", "Method[AppendText].ReturnValue", "file-write"]
7-
- ["System.IO.FileInfo", "Method[Create].ReturnValue", "file-write"]
8-
- ["System.IO.FileInfo", "Method[CreateText].ReturnValue", "file-write"]
9-
- ["System.IO.FileInfo", "Method[Open].ReturnValue", "file-write"]
10-
- ["System.IO.FileInfo", "Method[Open].ReturnValue", "file"]
11-
- ["System.IO.FileInfo", "Method[OpenRead].ReturnValue", "file"]
12-
- ["System.IO.FileInfo", "Method[OpenText].ReturnValue", "file"]
13-
- ["System.IO.FileInfo", "Method[OpenWrite].ReturnValue", "file-write"]
6+
- ["System.IO.FileInfo!", "Method[AppendText].ReturnValue", "file-write"]
7+
- ["System.IO.FileInfo!", "Method[Create].ReturnValue", "file-write"]
8+
- ["System.IO.FileInfo!", "Method[CreateText].ReturnValue", "file-write"]
9+
- ["System.IO.FileInfo!", "Method[Open].ReturnValue", "file-write"]
10+
- ["System.IO.FileInfo!", "Method[Open].ReturnValue", "file"]
11+
- ["System.IO.FileInfo!", "Method[OpenRead].ReturnValue", "file"]
12+
- ["System.IO.FileInfo!", "Method[OpenText].ReturnValue", "file"]
13+
- ["System.IO.FileInfo!", "Method[OpenWrite].ReturnValue", "file-write"]

0 commit comments

Comments
 (0)