Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
55 changes: 45 additions & 10 deletions powershell/ql/lib/semmle/code/powershell/ApiGraphs.qll
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ private import semmle.code.powershell.dataflow.DataFlow
private import semmle.code.powershell.typetracking.ApiGraphShared
private import semmle.code.powershell.typetracking.internal.TypeTrackingImpl
private import semmle.code.powershell.controlflow.Cfg
private import frameworks.data.internal.ApiGraphModelsExtensions as Extensions
private import frameworks.data.internal.ApiGraphModelsSpecific as Specific
private import semmle.code.powershell.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.code.powershell.dataflow.internal.DataFlowDispatch as DataFlowDispatch

Expand Down Expand Up @@ -514,12 +516,48 @@ module API {
)
}

bindingset[name]
private string memberOrMethodReturnValue(string name) {
// This predicate is a bit ad-hoc, but it's okay for now.
// We can delete it once we no longer use the typeModel and summaryModel
// tables to represent implicit root members.
result = "Method[" + name + "]"
or
result = "Method[" + name + "].ReturnValue"
or
result = "Member[" + name + "]"
}

private Node getAnImplicitRootMember(string name) {
exists(DataFlow::CallNode call |
Extensions::typeModel(_, Specific::getAnImplicitImport(), memberOrMethodReturnValue(name))
or
Extensions::summaryModel(Specific::getAnImplicitImport(), memberOrMethodReturnValue(name),
_, _, _, _)
or
Extensions::sourceModel(Specific::getAnImplicitImport(), memberOrMethodReturnValue(name), _,
_)
|
result = MkMethodAccessNode(call) and
name = call.getName().toLowerCase()
)
}

cached
predicate memberEdge(Node pred, string name, Node succ) {
exists(StringConstExpr read |
succ = getForwardStartNode(getNodeFromExpr(read)) and
pred = MkRoot() and
name = read.getValueString()
pred = API::root() and
(
exists(StringConstExpr read |
succ = getForwardStartNode(getNodeFromExpr(read)) and
name = read.getValueString()
)
or
exists(DataFlow::AutomaticVariableNode automatic |
automatic.getName() = name and
succ = getForwardStartNode(automatic)
)
or
succ = getAnImplicitRootMember(name)
)
or
exists(DataFlow::QualifiedTypeNameNode typeName |
Expand All @@ -528,12 +566,6 @@ module API {
succ = getForwardStartNode(typeName)
)
or
pred = MkRoot() and
exists(DataFlow::AutomaticVariableNode automatic |
automatic.getName() = name and
succ = getForwardStartNode(automatic)
)
or
exists(MemberExprReadAccess read |
read.getMemberName().toLowerCase() = name and
pred = getForwardEndNode(getALocalSourceStrict(getNodeFromExpr(read.getQualifier()))) and
Expand All @@ -548,6 +580,9 @@ module API {
|
pred = getForwardEndNode(getALocalSourceStrict(call.getQualifier()))
)
or
pred = API::root() and
succ = getAnImplicitRootMember(name)
}

cached
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,14 @@ class ConstructorCall extends InvokeMemberExpr {
/** Gets the name of the type being constructed by this constructor call. */
string getConstructedTypeName() { result = typename.getName() }
}

/**
* A call to a `toString` method. For example:
*
* ```powershell
* $x.ToString()
* ```
*/
class ToStringCall extends InvokeMemberExpr {
ToStringCall() { this.getName().toLowerCase() = "toString" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,11 @@ class Pipeline extends Expr, TPipeline {
Expr getAComponent() { result = this.getComponent(_) }

int getNumberOfComponents() { result = getRawAst(this).(Raw::Pipeline).getNumberOfComponents() }

Expr getLastComponent() {
exists(int i |
result = this.getComponent(i) and
not exists(this.getComponent(i + 1))
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ module ExprNodes {
}

private class CallOperatorChildMapping extends CallExprChildMapping instanceof CallOperator {
override predicate relevantChild(Ast child) { none() }
override predicate relevantChild(Ast child) { super.relevantChild(child) }
}

class CallOperatorCfgNode extends CallExprCfgNode {
Expand All @@ -600,6 +600,18 @@ module ExprNodes {
ExprCfgNode getCommand() { result = this.getArgument(0) }
}

private class ToStringCallChildmapping extends CallExprChildMapping instanceof ToStringCall {
override predicate relevantChild(Ast child) { super.relevantChild(child) }
}

class ToStringCallCfgNode extends CallExprCfgNode {
override string getAPrimaryQlClass() { result = "ToStringCallCfgNode" }

override ToStringCallChildmapping e;

override ToStringCall getExpr() { result = e }
}

private class MemberExprChildMapping extends ExprChildMapping, MemberExpr {
override predicate relevantChild(Ast child) {
child = this.getQualifier()
Expand Down Expand Up @@ -847,6 +859,8 @@ module ExprNodes {
ExprCfgNode getComponent(int i) { e.hasCfgChild(e.getComponent(i), this, result) }

ExprCfgNode getAComponent() { result = this.getComponent(_) }

ExprCfgNode getLastComponent() { e.hasCfgChild(e.getLastComponent(), this, result) }
}

private class PipelineChainChildMapping extends ExprChildMapping, PipelineChain {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ module LocalFlow {
or
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ArrayExprCfgNode)
or
nodeTo.asExpr().(CfgNodes::ExprNodes::PipelineCfgNode).getLastComponent() = nodeFrom.asExpr()
or
exists(CfgNodes::ExprCfgNode e |
e = nodeFrom.(AstNode).getCfgNode() and
isReturned(e) and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,13 @@ class CallOperatorNode extends CallNode {
Node getCommand() { result.asExpr() = call.getCommand() } // TODO: Alternatively, we could remap calls to & as command expressions.
}

/**
* A call to `ToString`, viewed as a node in a data flow graph.
*/
class ToStringCallNode extends CallNode {
override CfgNodes::ExprNodes::ToStringCallCfgNode call;
}

/** A use of a type name, viewed as a node in a data flow graph. */
class TypeNameNode extends ExprNode {
override CfgNodes::ExprNodes::TypeNameExprCfgNode n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PowershellDataF
or
pos.isThis() and
result = "this"
or
pos.isPipeline() and
result = "pipeline"
}

string encodeArgumentPosition(ArgumentPosition pos) {
pos.isThis() and result = "this"
or
pos.isPipeline() and result = "pipeline"
or
exists(int i |
pos.isPositional(i, emptyNamedSet()) and
result = i.toString()
Expand All @@ -52,20 +57,20 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PowershellDataF
}

string encodeContent(ContentSet cs, string arg) {
exists(Content c | cs = TSingletonContentSet(c) |
exists(Content c | cs.isSingleton(c) |
c = TFieldContent(arg) and result = "Field"
or
exists(ConstantValue cv | c = TKnownKeyContent(cv) or c = TKnownPositionalContent(cv) |
result = "Element" and
arg = cv.serialize() + "!"
)
or
(c = TUnknownPositionalContent() or c = TUnknownKeyContent()) and
result = "Element" and
arg = "?"
)
or
cs = TAnyElementContentSet() and result = "Element" and arg = "any"
cs.isAnyPositional() and result = "Element" and arg = "?"
or
cs.isUnknownKeyContent() and result = "Element" and arg = "#"
or
cs.isAnyElement() and result = "Element" and arg = "any"
or
exists(Content::KnownElementContent kec |
cs = TKnownOrUnknownKeyContentSet(kec) or cs = TKnownOrUnknownPositionalContentSet(kec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ private module Cached {
or
c.isAnyElement()
)
or
nodeTo.(DataFlow::ToStringCallNode).getQualifier() = nodeFrom
) and
model = ""
or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.String", "Accessibility.IAccessible", "Property[accHelp]"]
- ["System.Object", "Accessibility.IAccessible", "Method[accHitTest].ReturnValue"]
- ["System.Int32", "Accessibility._RemotableHandle", "Field[fContext]"]
- ["System.Int32", "Accessibility.IAccessible", "Property[accChildCount]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accState]"]
- ["Accessibility.AnnoScope", "Accessibility.AnnoScope!", "Field[ANNO_THIS]"]
- ["System.Int32", "Accessibility.__MIDL_IWinTypes_0009", "Field[hRemote]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accParent]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accRole]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accChild]"]
- ["System.String", "Accessibility.IAccessible", "Property[accKeyboardShortcut]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accSelection]"]
- ["System.Int32", "Accessibility.IAccessible", "Property[accHelpTopic]"]
- ["System.String", "Accessibility.IAccessible", "Property[accDescription]"]
- ["System.String", "Accessibility.IAccessible", "Property[accDefaultAction]"]
- ["System.Object", "Accessibility.IAccessible", "Property[accFocus]"]
- ["Accessibility.__MIDL_IWinTypes_0009", "Accessibility._RemotableHandle", "Field[u]"]
- ["System.String", "Accessibility.IAccessible", "Property[accValue]"]
- ["System.Int32", "Accessibility.__MIDL_IWinTypes_0009", "Field[hInproc]"]
- ["System.String", "Accessibility.IAccessible", "Property[accName]"]
- ["Accessibility.AnnoScope", "Accessibility.AnnoScope!", "Field[ANNO_CONTAINER]"]
- ["System.Object", "Accessibility.IAccessible", "Method[accNavigate].ReturnValue"]
- ["system.string", "accessibility.iaccessible", "Property[acchelp]"]
- ["system.object", "accessibility.iaccessible", "Method[acchittest].ReturnValue"]
- ["system.int32", "accessibility._remotablehandle", "Field[fcontext]"]
- ["system.int32", "accessibility.iaccessible", "Property[accchildcount]"]
- ["system.object", "accessibility.iaccessible", "Property[accstate]"]
- ["accessibility.annoscope", "accessibility.annoscope!", "Field[anno_this]"]
- ["system.int32", "accessibility.__midl_iwintypes_0009", "Field[hremote]"]
- ["system.object", "accessibility.iaccessible", "Property[accparent]"]
- ["system.object", "accessibility.iaccessible", "Property[accrole]"]
- ["system.object", "accessibility.iaccessible", "Property[accchild]"]
- ["system.string", "accessibility.iaccessible", "Property[acckeyboardshortcut]"]
- ["system.object", "accessibility.iaccessible", "Property[accselection]"]
- ["system.int32", "accessibility.iaccessible", "Property[acchelptopic]"]
- ["system.string", "accessibility.iaccessible", "Property[accdescription]"]
- ["system.string", "accessibility.iaccessible", "Property[accdefaultaction]"]
- ["system.object", "accessibility.iaccessible", "Property[accfocus]"]
- ["accessibility.__midl_iwintypes_0009", "accessibility._remotablehandle", "Field[u]"]
- ["system.string", "accessibility.iaccessible", "Property[accvalue]"]
- ["system.int32", "accessibility.__midl_iwintypes_0009", "Field[hinproc]"]
- ["system.string", "accessibility.iaccessible", "Property[accname]"]
- ["accessibility.annoscope", "accessibility.annoscope!", "Field[anno_container]"]
- ["system.object", "accessibility.iaccessible", "Method[accnavigate].ReturnValue"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.Int32", "IEHost.Execute.IEExecuteRemote", "Method[ExecuteAsDll].ReturnValue"]
- ["System.IO.Stream", "IEHost.Execute.IEExecuteRemote", "Property[Exception]"]
- ["System.Object", "IEHost.Execute.IEExecuteRemote", "Method[InitializeLifetimeService].ReturnValue"]
- ["System.Int32", "IEHost.Execute.IEExecuteRemote", "Method[ExecuteAsAssembly].ReturnValue"]
- ["system.int32", "iehost.execute.ieexecuteremote", "Method[executeasdll].ReturnValue"]
- ["system.io.stream", "iehost.execute.ieexecuteremote", "Property[exception]"]
- ["system.object", "iehost.execute.ieexecuteremote", "Method[initializelifetimeservice].ReturnValue"]
- ["system.int32", "iehost.execute.ieexecuteremote", "Method[executeasassembly].ReturnValue"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.Boolean", "Microsoft.Activities.Build.WorkflowBuildMessageTask", "Method[Execute].ReturnValue"]
- ["System.String", "Microsoft.Activities.Build.WorkflowBuildMessageTask", "Property[ResourceName]"]
- ["System.String", "Microsoft.Activities.Build.WorkflowBuildMessageTask", "Property[MessageType]"]
- ["system.boolean", "microsoft.activities.build.workflowbuildmessagetask", "Method[execute].ReturnValue"]
- ["system.string", "microsoft.activities.build.workflowbuildmessagetask", "Property[resourcename]"]
- ["system.string", "microsoft.activities.build.workflowbuildmessagetask", "Property[messagetype]"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.Boolean", "Microsoft.Activities.Build.Debugger.DebugBuildExtension", "Method[Execute].ReturnValue"]
- ["system.boolean", "microsoft.activities.build.debugger.debugbuildextension", "Method[execute].ReturnValue"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.Boolean", "Microsoft.Activities.Build.Expressions.ExpressionsBuildExtension", "Method[Execute].ReturnValue"]
- ["system.boolean", "microsoft.activities.build.expressions.expressionsbuildextension", "Method[execute].ReturnValue"]
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ extensions:
pack: microsoft-sdl/powershell-all
extensible: typeModel
data:
- ["System.Boolean", "Microsoft.Activities.Build.Validation.ReportDeferredValidationErrorsTask", "Method[Execute].ReturnValue"]
- ["System.String", "Microsoft.Activities.Build.Validation.DeferredValidationTask", "Property[DeferredValidationErrorsFilePath]"]
- ["System.String", "Microsoft.Activities.Build.Validation.ReportDeferredValidationErrorsTask", "Property[DeferredValidationErrorsFilePath]"]
- ["System.Boolean", "Microsoft.Activities.Build.Validation.DeferredValidationTask", "Method[Execute].ReturnValue"]
- ["system.boolean", "microsoft.activities.build.validation.reportdeferredvalidationerrorstask", "Method[execute].ReturnValue"]
- ["system.string", "microsoft.activities.build.validation.deferredvalidationtask", "Property[deferredvalidationerrorsfilepath]"]
- ["system.string", "microsoft.activities.build.validation.reportdeferredvalidationerrorstask", "Property[deferredvalidationerrorsfilepath]"]
- ["system.boolean", "microsoft.activities.build.validation.deferredvalidationtask", "Method[execute].ReturnValue"]
Loading