Skip to content

Commit 6de4765

Browse files
committed
PS: Support implicit imports in API graphs.
1 parent a5afc3c commit 6de4765

File tree

2 files changed

+56
-11
lines changed

2 files changed

+56
-11
lines changed

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

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ private import semmle.code.powershell.dataflow.DataFlow
1010
private import semmle.code.powershell.typetracking.ApiGraphShared
1111
private import semmle.code.powershell.typetracking.internal.TypeTrackingImpl
1212
private import semmle.code.powershell.controlflow.Cfg
13+
private import frameworks.data.internal.ApiGraphModelsExtensions as Extensions
14+
private import frameworks.data.internal.ApiGraphModelsSpecific as Specific
1315
private import semmle.code.powershell.dataflow.internal.DataFlowPrivate as DataFlowPrivate
1416
private import semmle.code.powershell.dataflow.internal.DataFlowDispatch as DataFlowDispatch
1517

@@ -514,12 +516,48 @@ module API {
514516
)
515517
}
516518

519+
bindingset[name]
520+
private string memberOrMethodReturnValue(string name) {
521+
// This predicate is a bit ad-hoc, but it's okay for now.
522+
// We can delete it once we no longer use the typeModel and summaryModel
523+
// tables to represent implicit root members.
524+
result = "Method[" + name + "]"
525+
or
526+
result = "Method[" + name + "].ReturnValue"
527+
or
528+
result = "Member[" + name + "]"
529+
}
530+
531+
private Node getAnImplicitRootMember(string name) {
532+
exists(DataFlow::CallNode call |
533+
Extensions::typeModel(_, Specific::getAnImplicitImport(), memberOrMethodReturnValue(name))
534+
or
535+
Extensions::summaryModel(Specific::getAnImplicitImport(), memberOrMethodReturnValue(name),
536+
_, _, _, _)
537+
or
538+
Extensions::sourceModel(Specific::getAnImplicitImport(), memberOrMethodReturnValue(name), _,
539+
_)
540+
|
541+
result = MkMethodAccessNode(call) and
542+
name = call.getName().toLowerCase()
543+
)
544+
}
545+
517546
cached
518547
predicate memberEdge(Node pred, string name, Node succ) {
519-
exists(StringConstExpr read |
520-
succ = getForwardStartNode(getNodeFromExpr(read)) and
521-
pred = MkRoot() and
522-
name = read.getValueString()
548+
pred = API::root() and
549+
(
550+
exists(StringConstExpr read |
551+
succ = getForwardStartNode(getNodeFromExpr(read)) and
552+
name = read.getValueString()
553+
)
554+
or
555+
exists(DataFlow::AutomaticVariableNode automatic |
556+
automatic.getName() = name and
557+
succ = getForwardStartNode(automatic)
558+
)
559+
or
560+
succ = getAnImplicitRootMember(name)
523561
)
524562
or
525563
exists(DataFlow::QualifiedTypeNameNode typeName |
@@ -528,12 +566,6 @@ module API {
528566
succ = getForwardStartNode(typeName)
529567
)
530568
or
531-
pred = MkRoot() and
532-
exists(DataFlow::AutomaticVariableNode automatic |
533-
automatic.getName() = name and
534-
succ = getForwardStartNode(automatic)
535-
)
536-
or
537569
exists(MemberExprReadAccess read |
538570
read.getMemberName().toLowerCase() = name and
539571
pred = getForwardEndNode(getALocalSourceStrict(getNodeFromExpr(read.getQualifier()))) and
@@ -548,6 +580,9 @@ module API {
548580
|
549581
pred = getForwardEndNode(getALocalSourceStrict(call.getQualifier()))
550582
)
583+
or
584+
pred = API::root() and
585+
succ = getAnImplicitRootMember(name)
551586
}
552587

553588
cached

powershell/ql/lib/semmle/code/powershell/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ API::Node getExtraNodeFromPath(string type, AccessPath path, int n) {
6868
)
6969
}
7070

71+
/**
72+
* Gets a string that represents a module that is always implicitly
73+
* imported in any powershell script.
74+
*/
75+
string getAnImplicitImport() {
76+
result = "microsoft.powershell.management!"
77+
or
78+
result = "microsoft.powershell.utility!"
79+
}
80+
7181
/** Gets a Powershell-specific interpretation of the given `type`. */
7282
API::Node getExtraNodeFromType(string rawType) {
7383
exists(
@@ -85,7 +95,7 @@ API::Node getExtraNodeFromType(string rawType) {
8595
result = qualifiedTypeName.(DataFlow::LocalSourceNode).track().getInstance()
8696
)
8797
or
88-
rawType = "" and
98+
(rawType = ["", getAnImplicitImport()]) and
8999
result = API::root()
90100
}
91101

0 commit comments

Comments
 (0)