Merge branch 'main' of https://github.com/microsoft/codeql into powershell-injectionhunter-port

This commit is contained in:
Chanel Young
2025-04-03 11:24:31 -07:00
19 changed files with 647 additions and 308 deletions

View File

@@ -33,11 +33,14 @@ newtype ChildIndex =
} or
ThisVar() or
PipelineParamVar() or
// PipelineByPropertNameVar(Raw::PipelineByPropertyNameParameter p) or
PipelineByPropertyNameVar(Raw::PipelineByPropertyNameParameter p) or
PipelineIteratorVar() or
PipelineByPropertyNameIteratorVar(Raw::PipelineByPropertyNameParameter p) or
RealVar(string name) { name = variableNameInScope(_, _) } or
ProcessBlockPipelineVarReadAccess()
ProcessBlockPipelineVarReadAccess() or
ProcessBlockPipelineByPropertyNameVarReadAccess(string name) {
name = any(Raw::PipelineByPropertyNameParameter p).getName()
}
int synthPipelineParameterChildIndex(Raw::ScriptBlock sb) {
// If there is a parameter block, but no pipeline parameter
@@ -340,3 +343,7 @@ ChildIndex whileStmtCond() { result = RawChildIndex(Raw::WhileStmtCond()) }
ChildIndex whileStmtBody() { result = RawChildIndex(Raw::WhileStmtBody()) }
ChildIndex processBlockPipelineVarReadAccess() { result = ProcessBlockPipelineVarReadAccess() }
ChildIndex processBlockPipelineByPropertyNameVarReadAccess(string name) {
result = ProcessBlockPipelineByPropertyNameVarReadAccess(name)
}

View File

@@ -58,7 +58,20 @@ class ProcessBlock extends NamedBlock {
synthChild(getRawAst(this), processBlockPipelineVarReadAccess(), result)
}
PipelineByPropertyNameParameter getPipelineByPropertyNameParameter(string name) {
result = scriptBlock.getAParameter() and
result.getPropertyName() = name
}
PipelineByPropertyNameParameter getAPipelineByPropertyNameParameter() {
result = scriptBlock.getEnclosingFunction().getAParameter()
result = this.getPipelineByPropertyNameParameter(_)
}
VarReadAccess getPipelineByPropertyNameParameterAccess(string name) {
synthChild(getRawAst(this), processBlockPipelineByPropertyNameVarReadAccess(name), result)
}
VarReadAccess getAPipelineByPropertyNameParameterAccess() {
result = this.getPipelineByPropertyNameParameterAccess(_)
}
}

View File

@@ -615,7 +615,7 @@ private module LiteralSynth {
/**
* Holds if `va` is an access to the automatic variable named `name`.
*
*
* Unlike `Raw::isAutomaticVariableAccess`, this predicate also checks for
* shadowing.
*/
@@ -770,6 +770,13 @@ private module IteratorAccessSynth {
or
va.getUserPath().toLowerCase() =
pb.getScriptBlock().getParamBlock().getPipelineParameter().getName().toLowerCase()
or
va.getUserPath().toLowerCase() =
pb.getScriptBlock()
.getParamBlock()
.getAPipelineByPropertyNameParameter()
.getName()
.toLowerCase()
)
}
@@ -867,12 +874,19 @@ private module PipelineAccess {
pipelineVar = TVariableSynth(pb.getScriptBlock(), PipelineParamVar()) and
child = SynthChild(VarAccessSynthKind(pipelineVar))
)
or
exists(PipelineByPropertyNameVariable pipelineVar, Raw::PipelineByPropertyNameParameter p |
i = processBlockPipelineByPropertyNameVarReadAccess(p.getName()) and
getResultAst(p) = pipelineVar and
child = SynthChild(VarAccessSynthKind(pipelineVar))
)
)
}
final override Location getLocation(Ast n) {
exists(ProcessBlock pb |
pb.getPipelineParameterAccess() = n and
pb.getPipelineParameterAccess() = n or pb.getAPipelineByPropertyNameParameterAccess() = n
|
result = pb.getLocation()
)
}
@@ -881,6 +895,23 @@ private module PipelineAccess {
exists(ProcessBlock pb |
pb.getPipelineParameterAccess() = va and
v = pb.getPipelineParameter()
or
exists(string name |
pb.getPipelineByPropertyNameParameterAccess(name) = va and
v = pb.getPipelineByPropertyNameParameter(name)
)
)
}
}
}
private module ImplicitAssignmentInForEach {
private class ForEachAssignment extends Synthesis {
override predicate implicitAssignment(Raw::Ast dest, string name) {
exists(Raw::ForEachStmt forEach, Raw::VarAccess va |
va = forEach.getVarAccess() and
va = dest and
va.getUserPath() = name
)
}
}

View File

@@ -45,7 +45,9 @@ module Private {
class ParameterImpl extends VariableSynth {
ParameterImpl() {
i instanceof FunParam or i instanceof PipelineParamVar or i instanceof ThisVar
i instanceof FunParam or
i instanceof PipelineParamVar or
i instanceof ThisVar
}
}
@@ -59,6 +61,14 @@ module Private {
ScriptBlock getScriptBlock() { this = TVariableSynth(getRawAst(result), _) }
}
class PipelineByPropertyNameVariableImpl extends ParameterImpl {
PipelineByPropertyNameVariableImpl() {
getRawAst(this) instanceof Raw::PipelineByPropertyNameParameter
}
ScriptBlock getScriptBlock() { this = TVariableSynth(getRawAst(result), _) }
}
class PipelineIteratorVariableImpl extends VariableSynth {
override PipelineIteratorVar i;
@@ -171,6 +181,11 @@ module Public {
ScriptBlock getScriptBlock() { result = super.getScriptBlock() }
}
class PipelineByPropertyNameVariable extends Variable instanceof PipelineByPropertyNameVariableImpl
{
ScriptBlock getScriptBlock() { result = super.getScriptBlock() }
}
class PipelineIteratorVariable extends Variable instanceof PipelineIteratorVariableImpl {
ProcessBlock getProcessBlock() { result = super.getProcessBlock() }
}

View File

@@ -277,6 +277,8 @@ private class ProcessBlockChildMapping extends NamedBlockChildMapping, ProcessBl
super.relevantChild(child)
or
child = super.getPipelineParameterAccess()
or
child = super.getAPipelineByPropertyNameParameterAccess()
}
}
@@ -300,6 +302,23 @@ class ProcessBlockCfgNode extends NamedBlockCfgNode {
PipelineIteratorVariable getPipelineIteratorVariable() {
result.getProcessBlock().getScriptBlock() = this.getScriptBlock().getAstNode()
}
PipelineByPropertyNameIteratorVariable getPipelineBypropertyNameIteratorVariable(string name) {
result.getPropertyName() = name and
result.getProcessBlock().getScriptBlock() = this.getScriptBlock().getAstNode()
}
PipelineByPropertyNameIteratorVariable getAPipelineBypropertyNameIteratorVariable() {
result = this.getPipelineBypropertyNameIteratorVariable(_)
}
ExprNodes::VarReadAccessCfgNode getPipelineByPropertyNameParameterAccess(string name) {
block.hasCfgChild(block.getPipelineByPropertyNameParameterAccess(name), this, result)
}
ExprNodes::VarReadAccessCfgNode getAPipelineByPropertyNameParameterAccess() {
result = this.getPipelineByPropertyNameParameterAccess(_)
}
}
private class CatchClauseChildMapping extends NonExprChildMapping, CatchClause {

View File

@@ -188,7 +188,11 @@ private predicate inMatchingContext(Ast n) {
* Holds if a normal completion of `cfe` must be an emptiness completion. Thats is,
* whether `cfe` determines whether to execute the body of a `foreach` statement.
*/
private predicate mustHaveEmptinessCompletion(Ast n) { n instanceof ForEachStmt }
private predicate mustHaveEmptinessCompletion(Ast n) {
n instanceof ForEachStmt
or
any(CfgImpl::Trees::ProcessBlockTree pbtree).lastEmptinessCheck(n)
}
/**
* A completion that represents normal evaluation of a statement or an

View File

@@ -221,13 +221,7 @@ module Trees {
or
last(super.getProcessBlock(), pred, c) and
completionIsNormal(c) and
(
// If we process multiple items we will loop back to the process block
first(super.getProcessBlock(), succ)
or
// Once we're done process all items we will go to the end block
first(super.getEndBlock(), succ)
)
first(super.getEndBlock(), succ)
}
final override predicate propagatesAbnormal(AstNode child) {
@@ -292,25 +286,17 @@ module Trees {
final override predicate succEntry(Ast n, Completion c) { n = this and completionIsSimple(c) }
}
abstract class NamedBlockTreeBase extends ControlFlowTree instanceof NamedBlock {
final override predicate last(Ast last, Completion c) {
abstract class NamedBlockTreeBase extends PreOrderTree instanceof NamedBlock {
override predicate last(Ast last, Completion c) {
exists(int i | last(super.getStmt(i), last, c) |
completionIsNormal(c) and
not exists(super.getStmt(i + 1))
or
not completionIsNormal(c)
)
or
not exists(super.getAStmt()) and
completionIsSimple(c) and
last = this
}
override predicate succ(Ast pred, Ast succ, Completion c) {
pred = this and
completionIsSimple(c) and
first(super.getStmt(0), succ)
or
exists(int i |
last(super.getStmt(i), pred, c) and
completionIsNormal(c) and
@@ -324,20 +310,85 @@ module Trees {
class NamedBlockTree extends NamedBlockTreeBase instanceof NamedBlock {
NamedBlockTree() { not this instanceof ProcessBlock }
final override predicate first(Ast first) { first = this }
final override predicate last(Ast last, Completion c) {
super.last(last, c)
or
not exists(super.getAStmt()) and
completionIsSimple(c) and
last = this
}
final override predicate succ(Ast pred, Ast succ, Completion c) {
pred = this and
completionIsSimple(c) and
first(super.getStmt(0), succ)
or
super.succ(pred, succ, c)
}
final override predicate propagatesAbnormal(Ast child) { super.propagatesAbnormal(child) }
}
private VarAccess getRankedPipelineByPropertyNameVariable(ProcessBlock pb, int i) {
result =
rank[i + 1](string name | | pb.getPipelineByPropertyNameParameterAccess(name) order by name)
}
class ProcessBlockTree extends NamedBlockTreeBase instanceof ProcessBlock {
final override predicate first(Ast first) { first = super.getPipelineParameterAccess() }
predicate lastEmptinessCheck(AstNode last) {
last = super.getPipelineParameterAccess() and
not exists(super.getAPipelineByPropertyNameParameterAccess())
or
exists(int i |
last = getRankedPipelineByPropertyNameVariable(this, i) and
not exists(getRankedPipelineByPropertyNameVariable(this, i + 1))
)
}
private predicate succEmptinessCheck(AstNode pred, AstNode succ, Completion c) {
last(super.getPipelineParameterAccess(), pred, c) and
first(getRankedPipelineByPropertyNameVariable(this, 0), succ)
or
exists(int i |
last(getRankedPipelineByPropertyNameVariable(this, i), pred, c) and
first(getRankedPipelineByPropertyNameVariable(this, i + 1), succ)
)
}
private predicate firstEmptinessCheck(AstNode first) {
first(super.getPipelineParameterAccess(), first)
}
final override predicate last(AstNode last, Completion c) {
// Emptiness test exits with no more elements
this.lastEmptinessCheck(last) and
c.(EmptinessCompletion).isEmpty()
or
super.last(last, c)
}
final override predicate succ(Ast pred, Ast succ, Completion c) {
this.first(pred) and
completionIsSimple(c) and
succ = this
// Evaluate the pipeline access
pred = this and
this.firstEmptinessCheck(succ) and
completionIsSimple(c)
or
this.succEmptinessCheck(pred, succ, c)
or
this.lastEmptinessCheck(pred) and
c = any(EmptinessCompletion ec | not ec.isEmpty()) and
first(super.getStmt(0), succ)
or
super.succ(pred, succ, c)
or
// Body to emptiness test
exists(Ast last0 |
super.last(last0, _) and
last(last0, pred, c) and
// TODO: I don't think this correctly models the semantics inside process blocks
c.continuesLoop()
) and
this.firstEmptinessCheck(succ)
}
final override predicate propagatesAbnormal(Ast child) { super.propagatesAbnormal(child) }

View File

@@ -158,7 +158,7 @@ module Ssa {
not exists(this.getSplitString()) and
prefix = ""
|
result = prefix + "phi"
result = prefix + "phi (" + this.getSourceVariable() + ")"
)
}

View File

@@ -66,6 +66,8 @@ module SsaFlow {
result = TThisParameterNode(p.asThis())
or
result = TPipelineParameterNode(p.asPipelineParameter())
or
result = TPipelineByPropertyNameParameterNode(p.asPipelineByPropertyNameParameter())
}
/** Gets the SSA node corresponding to the PowerShell node `n`. */
@@ -83,6 +85,16 @@ module SsaFlow {
.definesAt(pb.getPipelineIteratorVariable(), bb, i)
)
or
exists(
BasicBlock bb, int i, PipelineByPropertyNameParameter p, ProcessPropertyByNameNode pbNode
|
pbNode = n and
pbNode.hasRead() and
pbNode.getParameter() = p and
bb.getNode(i) = pbNode.getProcessBlock() and
result.(Impl::SsaDefinitionNode).getDefinition().definesAt(p.getIteratorVariable(), bb, i)
)
or
result.(Impl::ExprPostUpdateNode).getExpr() = n.(PostUpdateNode).getPreUpdateNode().asExpr()
or
n = toParameterNode(result.(Impl::ParameterNode).getParameter())
@@ -145,13 +157,16 @@ module LocalFlow {
nodeTo.(ReturnNodeImpl).getCfgScope() = scriptBlock.getAstNode()
)
or
exists(CfgNodes::ExprNodes::PipelineArgumentCfgNode e | nodeFrom.asExpr() = e |
// If we are not already tracking as element content
nodeTo = TPrePipelineArgumentNode(e)
or
// If we are already tracking an element content
nodeTo = TPipelineArgumentNode(e)
nodeTo.(PreProcessPropertyByNameNode).getAccess() = nodeFrom.asExpr()
or
exists(PreProcessPropertyByNameNode pbNode |
pbNode = nodeFrom and
nodeTo = TProcessPropertyByNameNode(pbNode.getAccess().getVariable(), false)
)
or
nodeTo.(PreProcessNode).getProcessBlock().getPipelineVariableAccess() = nodeFrom.asExpr()
or
nodeTo.(ProcessNode).getProcessBlock() = nodeFrom.(PreProcessNode).getProcessBlock()
}
predicate flowSummaryLocalStep(
@@ -179,12 +194,6 @@ module VariableCapture {
// TODO
}
private predicate isProcessPropertyByNameNode(
PipelineByPropertyNameIteratorVariable iter, ProcessBlock pb
) {
pb = iter.getProcessBlock()
}
/** A collection of cached types and predicates to be evaluated in the same stage. */
cached
private module Cached {
@@ -198,8 +207,6 @@ private module Cached {
TThisParameterNode(Method m) or
TPipelineByPropertyNameParameterNode(PipelineByPropertyNameParameter p) or
TPipelineParameterNode(PipelineParameter p) or
TPrePipelineArgumentNode(CfgNodes::ExprNodes::PipelineArgumentCfgNode n) or
TPipelineArgumentNode(CfgNodes::ExprNodes::PipelineArgumentCfgNode n) or
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) {
n instanceof CfgNodes::ExprNodes::ArgumentCfgNode
or
@@ -220,9 +227,13 @@ private module Cached {
blockMayReturnMultipleValues(scriptBlock)
} or
TReturnNodeImpl(CfgScope scope) or
TPreProcessNode(CfgNodes::ProcessBlockCfgNode process) or
TProcessNode(CfgNodes::ProcessBlockCfgNode process) or
TProcessPropertyByNameNode(PipelineByPropertyNameIteratorVariable iter) {
isProcessPropertyByNameNode(iter, _)
TPreProcessPropertyByNameNode(CfgNodes::ExprNodes::VarReadAccessCfgNode va) {
any(CfgNodes::ProcessBlockCfgNode pb).getAPipelineByPropertyNameParameterAccess() = va
} or
TProcessPropertyByNameNode(PipelineByPropertyNameParameter p, Boolean hasRead) {
p.getDeclaringScope() = any(ProcessBlock pb).getScriptBlock()
} or
TScriptBlockNode(ScriptBlock scriptBlock) or
TForbiddenRecursionGuard() {
@@ -333,15 +344,13 @@ private module Cached {
cached
newtype TContentSet =
TSingletonContent(Content c) or
TAnyElementContent() or
TKnownOrUnknownElementContent(Content::KnownElementContent c)
private predicate trackKnownValue(ConstantValue cv) {
exists(cv.asString())
or
cv.asInt() = [0 .. 10]
}
TSingletonContentSet(Content c) or
TAnyElementContentSet() or
TAnyPositionalContentSet() or
TKnownOrUnknownKeyContentSet(Content::KnownKeyContent c) or
TKnownOrUnknownPositionalContentSet(Content::KnownPositionalContent c) or
TUnknownPositionalElementContentSet() or
TUnknownKeyContentSet()
cached
newtype TContent =
@@ -350,20 +359,41 @@ private module Cached {
or
name = any(MemberExpr me).getMemberName()
} or
TKnownElementContent(ConstantValue cv) { trackKnownValue(cv) } or
TUnknownElementContent()
// A known map key
TKnownKeyContent(ConstantValue cv) { exists(cv.asString()) } or
// A known array index
TKnownPositionalContent(ConstantValue cv) { cv.asInt() = [0 .. 10] } or
// An unknown key
TUnknownKeyContent() or
// An unknown positional element
TUnknownPositionalContent() or
// A unknown position or key - and we dont even know what kind it is
TUnknownKeyOrPositionContent()
cached
newtype TContentApprox =
// A field
TNonElementContentApprox(Content c) { not c instanceof Content::ElementContent } or
TUnknownElementContentApprox() or
TKnownIntegerElementContentApprox() or
TKnownElementContentApprox(string approx) { approx = approxKnownElementIndex(_) }
// An unknown key
TUnkownKeyContentApprox() or
// A known map key
TKnownKeyContentApprox(string approx) { approx = approxKnownElementIndex(_) } or
// A known positional element
TKnownPositionalContentApprox() or
// An unknown positional element
TUnknownPositionalContentApprox() or
TUnknownContentApprox()
cached
newtype TDataFlowType = TUnknownDataFlowType()
}
class TKnownElementContent = TKnownKeyContent or TKnownPositionalContent;
class TKnownKindContent = TUnknownPositionalContent or TUnknownKeyContent;
class TUnknownElementContent = TKnownKindContent or TUnknownKeyOrPositionContent;
class TElementContent = TKnownElementContent or TUnknownElementContent;
/** Gets a string for approximating known element indices. */
@@ -623,10 +653,10 @@ private module ParameterNodes {
PipelineByPropertyNameParameterNode() { this = TPipelineByPropertyNameParameterNode(parameter) }
override PipelineParameter getParameter() { result = parameter }
override PipelineByPropertyNameParameter getParameter() { result = parameter }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
pos.isPipeline() and // what about when it is applied as a normal parameter?
pos.isPipeline() and
c.asCfgScope() = parameter.getEnclosingScope()
}
@@ -690,22 +720,6 @@ abstract class ArgumentNode extends Node {
final DataFlowCall getCall() { this.argumentOf(result, _) }
}
class PrePipelineArgumentNodeImpl extends NodeImpl, TPrePipelineArgumentNode {
CfgNodes::ExprNodes::PipelineArgumentCfgNode e;
PrePipelineArgumentNodeImpl() { this = TPrePipelineArgumentNode(e) }
final override CfgScope getCfgScope() { result = e.getScope() }
final override Location getLocationImpl() { result = e.getLocation() }
final override string toStringImpl() { result = "[pre pipeline] " + e.toString() }
final override predicate nodeIsHidden() { any() }
CfgNodes::ExprNodes::PipelineArgumentCfgNode getPipelineArgument() { result = e }
}
module ArgumentNodes {
class ExplicitArgumentNode extends ArgumentNode {
CfgNodes::ExprNodes::ArgumentCfgNode arg;
@@ -749,23 +763,15 @@ module ArgumentNodes {
}
}
class PipelineArgumentNodeImpl extends NodeImpl, TPipelineArgumentNode {
CfgNodes::ExprNodes::PipelineArgumentCfgNode e;
class PipelineArgumentNode extends ArgumentNode instanceof ExprNode {
PipelineArgumentNode() {
this.getExprNode() instanceof CfgNodes::ExprNodes::PipelineArgumentCfgNode
}
PipelineArgumentNodeImpl() { this = TPipelineArgumentNode(e) }
CfgNodes::ExprNodes::PipelineArgumentCfgNode getPipelineArgument() {
result = super.getExprNode()
}
final override CfgScope getCfgScope() { result = e.getScope() }
final override Location getLocationImpl() { result = e.getLocation() }
final override string toStringImpl() { result = e.toString() }
final override predicate nodeIsHidden() { none() }
CfgNodes::ExprNodes::PipelineArgumentCfgNode getPipelineArgument() { result = e }
}
class PipelineArgumentNode extends ArgumentNode instanceof PipelineArgumentNodeImpl {
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
this.sourceArgumentOf(call.asCall(), pos)
}
@@ -773,7 +779,7 @@ module ArgumentNodes {
override predicate sourceArgumentOf(
CfgNodes::ExprNodes::CallExprCfgNode call, ArgumentPosition pos
) {
call = super.getPipelineArgument().getCall() and
call = this.getPipelineArgument().getCall() and
pos.isPipeline()
}
}
@@ -923,7 +929,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
e.getValue() = ec.getIndex()
)
or
not exists(e.getValue().asInt()) and
not exists(Content::KnownElementContent ec | ec.getIndex() = e.getValue()) and
c.isAnyElement()
)
or
@@ -931,7 +937,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
e = node1.asExpr() and
not arrayExprStore(node1, _, _, e) and
node2.asExpr().(CfgNodes::ExprNodes::ArrayLiteralCfgNode).getExpr(index) = e and
c.isKnownOrUnknownElement(ec) and
c.isKnownOrUnknownPositional(ec) and
index = ec.getIndex().asInt()
)
or
@@ -939,32 +945,32 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
node2.asExpr().(CfgNodes::ExprNodes::HashTableExprCfgNode).getValueFromKey(key) = node1.asExpr()
|
exists(Content::KnownElementContent ec |
c.isKnownOrUnknownElement(ec) and
ec.getIndex() = key.getValue()
c.isKnownOrUnknownKeyContent(ec) and
key.getValue() = ec.getIndex()
)
or
not exists(key.getValue()) and
c.isAnyElement()
not exists(Content::KnownKeyContent ec | ec.getIndex() = key.getValue()) and
c.isUnknownKeyContent()
)
or
arrayExprStore(node1, c, node2, _)
or
c.isAnyElement() and
c.isUnknownPositionalContent() and
exists(CfgNode cfgNode |
node1 = TPreReturnNodeImpl(cfgNode, false) and
node2.(ReturnNodeImpl).getCfgScope() = cfgNode.getScope()
)
or
c.isAnyElement() and
c.isUnknownPositionalContent() and
exists(CfgNode cfgNode |
node1 = TImplicitWrapNode(cfgNode, true) and
node2.(ReturnNodeImpl).getCfgScope() = cfgNode.getScope()
)
or
c.isAnyElement() and
exists(CfgNodes::ExprNodes::PipelineArgumentCfgNode arg |
node1 = TPrePipelineArgumentNode(arg) and
node2 = TPipelineArgumentNode(arg)
c.isUnknownPositionalContent() and
exists(CfgNodes::ProcessBlockCfgNode process |
node1 = TPreProcessNode(process) and
node2 = TProcessNode(process)
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
@@ -992,7 +998,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
e.getValue() = ec.getIndex()
)
or
not exists(e.getValue()) and
not exists(Content::KnownElementContent ec | ec.getIndex() = e.getValue()) and
c.isAnyElement()
)
or
@@ -1002,27 +1008,24 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
c.isSingleton(any(Content::KnownElementContent ec | exists(ec.getIndex().asInt())))
)
or
c.isAnyElement() and
c.isAnyPositional() and
exists(CfgNodes::ProcessBlockCfgNode processBlock |
processBlock.getPipelineVariableAccess() = node1.asExpr() and
node2 = TProcessNode(processBlock)
)
or
exists(
Content::KnownElementContent ec, PipelineByPropertyNameParameter p, SsaImpl::DefinitionExt def
|
c.isSingleton(ec) and
p.getIteratorVariable() = node1.(ProcessPropertyByNameNode).getVariable() and
p.getName() = ec.getIndex().asString() and
def.getSourceVariable() = p.getIteratorVariable() and
SsaImpl::firstRead(def, node2.asExpr())
c.isAnyPositional() and
exists(CfgNodes::ProcessBlockCfgNode pb, CfgNodes::ExprNodes::VarReadAccessCfgNode va |
va = pb.getAPipelineByPropertyNameParameterAccess() and
node1.asExpr() = va and
node2 = TProcessPropertyByNameNode(va.getVariable(), false)
)
or
exists(Content::KnownElementContent ec, SsaImpl::DefinitionExt def |
c.isSingleton(ec) and
node1.(PipelineByPropertyNameParameterNode).getPropertyName() = ec.getIndex().asString() and
def = SsaImpl::getParameterDef(node1.(PipelineByPropertyNameParameterNode).getParameter()) and
SsaImpl::firstRead(def, node2.asExpr())
exists(PipelineByPropertyNameParameter p, Content::KnownElementContent ec |
c.isKnownOrUnknownElement(ec) and
ec.getIndex().asString() = p.getPropertyName() and
node1 = TProcessPropertyByNameNode(p, false) and
node2 = TProcessPropertyByNameNode(p, true)
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
@@ -1043,8 +1046,11 @@ predicate clearsContent(Node n, ContentSet c) {
n = TPreReturnNodeImpl(_, false) and
c.isAnyElement()
or
n instanceof PrePipelineArgumentNodeImpl and
c.isAnyElement()
c.isAnyPositional() and
n instanceof PreProcessPropertyByNameNode
or
c.isAnyPositional() and
n instanceof PreProcessNode
}
/**
@@ -1059,9 +1065,6 @@ predicate expectsContent(Node n, ContentSet c) {
or
n = TImplicitWrapNode(_, false) and
c.isSingleton(any(Content::UnknownElementContent ec))
or
n instanceof PipelineArgumentNode and
c.isAnyElement()
}
class DataFlowType extends TDataFlowType {
@@ -1191,6 +1194,22 @@ private class ReturnNodeImpl extends TReturnNodeImpl, NodeImpl {
override predicate nodeIsHidden() { any() }
}
private class PreProcessNode extends TPreProcessNode, NodeImpl {
CfgNodes::ProcessBlockCfgNode process;
PreProcessNode() { this = TPreProcessNode(process) }
override CfgScope getCfgScope() { result = process.getScope() }
override Location getLocationImpl() { result = process.getLocation() }
override string toStringImpl() { result = "pre-process node for " + process.toString() }
override predicate nodeIsHidden() { any() }
CfgNodes::ProcessBlockCfgNode getProcessBlock() { result = process }
}
private class ProcessNode extends TProcessNode, NodeImpl {
CfgNodes::ProcessBlockCfgNode process;
@@ -1211,26 +1230,53 @@ private class ProcessNode extends TProcessNode, NodeImpl {
CfgNodes::ProcessBlockCfgNode getProcessBlock() { result = process }
}
private class ProcessPropertyByNameNode extends TProcessPropertyByNameNode, NodeImpl {
private PipelineByPropertyNameIteratorVariable iter;
private class PreProcessPropertyByNameNode extends TPreProcessPropertyByNameNode, NodeImpl {
private CfgNodes::ExprNodes::VarReadAccessCfgNode va;
ProcessPropertyByNameNode() { this = TProcessPropertyByNameNode(iter) }
PreProcessPropertyByNameNode() { this = TPreProcessPropertyByNameNode(va) }
PipelineByPropertyNameIteratorVariable getVariable() { result = iter }
CfgNodes::ExprNodes::VarReadAccessCfgNode getAccess() { result = va }
override CfgScope getCfgScope() { result = iter.getDeclaringScope() }
override CfgScope getCfgScope() { result = va.getScope() }
override Location getLocationImpl() { result = iter.getLocation() }
override Location getLocationImpl() { result = this.getProcessBlock().getLocation() }
override string toStringImpl() { result = "process node for " + iter.toString() }
override string toStringImpl() { result = "pre-process node for " + va.toString() }
override predicate nodeIsHidden() { any() }
CfgNodes::ProcessBlockCfgNode getProcessBlock() {
isProcessPropertyByNameNode(iter, result.getAstNode())
result.getAPipelineByPropertyNameParameterAccess() = va
}
}
private class ProcessPropertyByNameNode extends TProcessPropertyByNameNode, NodeImpl {
private PipelineByPropertyNameParameter p;
private boolean hasRead;
ProcessPropertyByNameNode() { this = TProcessPropertyByNameNode(p, hasRead) }
PipelineByPropertyNameParameter getParameter() { result = p }
override CfgScope getCfgScope() { result = p.getDeclaringScope() }
override Location getLocationImpl() { result = this.getProcessBlock().getLocation() }
override string toStringImpl() {
hasRead = false and
result = "process node for " + p.toString()
or
hasRead = true and
result = "[has read] process node for " + p.toString()
}
override predicate nodeIsHidden() { any() }
CfgNodes::ProcessBlockCfgNode getProcessBlock() { result.getScope().getAParameter() = p }
predicate hasRead() { hasRead = true }
}
class ScriptBlockNode extends TScriptBlockNode, NodeImpl {
private ScriptBlock scriptBlock;
@@ -1338,18 +1384,38 @@ class ContentApprox extends TContentApprox {
/** Gets an approximated value for content `c`. */
ContentApprox getContentApprox(Content c) {
c instanceof Content::UnknownElementContent and
result = TUnknownElementContentApprox()
c instanceof Content::KnownPositionalContent and
result = TKnownPositionalContentApprox()
or
exists(c.(Content::KnownElementContent).getIndex().asInt()) and
result = TKnownIntegerElementContentApprox()
or
result =
TKnownElementContentApprox(approxKnownElementIndex(c.(Content::KnownElementContent).getIndex()))
result = TKnownKeyContentApprox(approxKnownElementIndex(c.(Content::KnownKeyContent).getIndex()))
or
result = TNonElementContentApprox(c)
or
c instanceof Content::UnknownKeyContent and
result = TUnkownKeyContentApprox()
or
c instanceof Content::UnknownPositionalContent and
result = TUnknownPositionalContentApprox()
or
c instanceof Content::UnknownKeyOrPositionContent and
result = TUnknownContentApprox()
}
// TFieldContent(string name) {
// name = any(PropertyMember member).getName()
// or
// name = any(MemberExpr me).getMemberName()
// } or
// // A known map key
// TKnownKeyContent(ConstantValue cv) { exists(cv.asString()) } or
// // A known array index
// TKnownPositionalContent(ConstantValue cv) { cv.asInt() = [0 .. 10] } or
// // An unknown key
// TUnknownKeyContent() or
// // An unknown positional element
// TUnknownPositionalContent() or
// // A unknown position or key - and we dont even know what kind it is
// TUnknownKeyOrPositionContent()
/**
* A unit class for adding additional jump steps.
*

View File

@@ -255,21 +255,43 @@ module Content {
/** An element in a collection, for example an element in an array or in a hash. */
class ElementContent extends Content, TElementContent { }
/** An element in a collection at a known index. */
class KnownElementContent extends ElementContent, TKnownElementContent {
private ConstantValue cv;
KnownElementContent() { this = TKnownElementContent(cv) }
abstract class KnownElementContent extends ElementContent, TKnownElementContent {
ConstantValue cv;
/** Gets the index in the collection. */
ConstantValue getIndex() { result = cv }
final ConstantValue getIndex() { result = cv }
override string toString() { result = "element " + cv }
}
/** An element in a collection at an unknown index. */
class UnknownElementContent extends ElementContent, TUnknownElementContent {
override string toString() { result = "element" }
/** An element in a collection at a known index. */
class KnownKeyContent extends KnownElementContent, TKnownKeyContent {
KnownKeyContent() { this = TKnownKeyContent(cv) }
}
/** An element in a collection at a known index. */
class KnownPositionalContent extends KnownElementContent, TKnownPositionalContent {
KnownPositionalContent() { this = TKnownPositionalContent(cv) }
}
class UnknownElementContent extends ElementContent, TUnknownElementContent { }
class UnknownKeyContent extends UnknownElementContent, TUnknownKeyContent {
UnknownKeyContent() { this = TUnknownKeyContent() }
override string toString() { result = "unknown map key" }
}
class UnknownPositionalContent extends UnknownElementContent, TUnknownPositionalContent {
UnknownPositionalContent() { this = TUnknownPositionalContent() }
override string toString() { result = "unknown index" }
}
class UnknownKeyOrPositionContent extends UnknownElementContent, TUnknownKeyOrPositionContent {
UnknownKeyOrPositionContent() { this = TUnknownKeyOrPositionContent() }
override string toString() { result = "unknown" }
}
/** A field of an object. */
@@ -285,20 +307,18 @@ module Content {
}
/** Gets the element content corresponding to constant value `cv`. */
ElementContent getElementContent(ConstantValue cv) {
result = TKnownElementContent(cv)
KnownElementContent getKnownElementContent(ConstantValue cv) {
result = TKnownPositionalContent(cv)
or
not exists(TKnownElementContent(cv)) and
result = TUnknownElementContent()
result = TKnownKeyContent(cv)
}
/**
* Gets the constant value of `e`, which corresponds to a valid known
* element index. Unlike calling simply `e.getConstantValue()`, this
* excludes negative array indices.
* element index.
*/
ConstantValue getKnownElementIndex(Expr e) {
result = getElementContent(e.getValue()).(KnownElementContent).getIndex()
result = getKnownElementContent(e.getValue()).getIndex()
}
}
@@ -310,19 +330,31 @@ module Content {
*/
class ContentSet extends TContentSet {
/** Holds if this content set is the singleton `{c}`. */
predicate isSingleton(Content c) { this = TSingletonContent(c) }
predicate isSingleton(Content c) { this = TSingletonContentSet(c) }
/** Holds if this content set represents all `ElementContent`s. */
predicate isAnyElement() { this = TAnyElementContent() }
/**
* Holds if this content set represents a specific known element index, or an
* unknown element index.
*/
predicate isKnownOrUnknownElement(Content::KnownElementContent c) {
this = TKnownOrUnknownElementContent(c)
predicate isKnownOrUnknownKeyContent(Content::KnownKeyContent c) {
this = TKnownOrUnknownKeyContentSet(c)
}
predicate isKnownOrUnknownPositional(Content::KnownPositionalContent c) {
this = TKnownOrUnknownPositionalContentSet(c)
}
predicate isKnownOrUnknownElement(Content::KnownElementContent c) {
this.isKnownOrUnknownKeyContent(c)
or
this.isKnownOrUnknownPositional(c)
}
predicate isUnknownPositionalContent() { this = TUnknownPositionalElementContentSet() }
predicate isUnknownKeyContent() { this = TUnknownKeyContentSet() }
predicate isAnyElement() { this = TAnyElementContentSet() }
predicate isAnyPositional() { this = TAnyPositionalContentSet() }
// predicate isPipelineContentSet() { this = TPipelineContentSet() }
/** Gets a textual representation of this content set. */
string toString() {
exists(Content c |
@@ -330,15 +362,25 @@ class ContentSet extends TContentSet {
result = c.toString()
)
or
this.isAnyElement() and
result = "any element"
or
exists(Content::KnownElementContent c |
this.isKnownOrUnknownElement(c) and
result = c + " or unknown"
result = c.toString() + " or unknown"
)
or
this.isUnknownPositionalContent() and
result = "unknown positional"
or
this.isUnknownKeyContent() and
result = "unknown key"
or
this.isAnyPositional() and
result = "any positional"
or
this.isAnyElement() and
result = "any element"
}
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() {
this.isSingleton(result)
or
@@ -346,20 +388,25 @@ class ContentSet extends TContentSet {
// from `a` to `a[unknown]` (which can read any element), gets translated into
// a reverse store step that store only into `?`
this.isAnyElement() and
result = TUnknownElementContent()
result = TUnknownKeyOrPositionContent()
or
// For reverse stores, `a[1][0] = x`, it is important that the read-step
// from `a` to `a[1]` (which can read both elements stored at exactly index `1`
// and elements stored at unknown index), gets translated into a reverse store
// step that store only into `1`
this.isKnownOrUnknownElement(result)
}
pragma[nomagic]
private Content getAnElementReadContent() {
exists(Content::KnownElementContent c | this.isKnownOrUnknownElement(c) |
result = c or
result = TUnknownElementContent()
or
this.isUnknownPositionalContent() and
result = TUnknownPositionalContent()
or
this.isUnknownKeyContent() and
result = TUnknownKeyContent()
or
this.isAnyPositional() and
(
result instanceof Content::KnownPositionalContent
or
result = TUnknownPositionalContent()
)
}
@@ -370,7 +417,36 @@ class ContentSet extends TContentSet {
this.isAnyElement() and
result instanceof Content::ElementContent
or
result = this.getAnElementReadContent()
exists(Content::KnownElementContent c |
this.isKnownOrUnknownKeyContent(c) and
(
result = c
or
result = TUnknownKeyContent()
or
result = TUnknownKeyOrPositionContent()
)
or
this.isKnownOrUnknownPositional(c) and
(
result = c or
result = TUnknownPositionalContent() or
result = TUnknownKeyOrPositionContent()
)
)
or
this.isUnknownPositionalContent() and
result = TUnknownPositionalContent()
or
this.isUnknownKeyContent() and
result = TUnknownKeyContent()
or
this.isAnyPositional() and
(
result instanceof Content::KnownPositionalContent
or
result = TUnknownPositionalContent()
)
}
}

View File

@@ -52,22 +52,24 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PowershellDataF
}
string encodeContent(ContentSet cs, string arg) {
exists(Content c | cs = TSingletonContent(c) |
exists(Content c | cs = TSingletonContentSet(c) |
c = TFieldContent(arg) and result = "Field"
or
exists(ConstantValue cv |
c = TKnownElementContent(cv) and
exists(ConstantValue cv | c = TKnownKeyContent(cv) or c = TKnownPositionalContent(cv) |
result = "Element" and
arg = cv.serialize() + "!"
)
or
c = TUnknownElementContent() and result = "Element" and arg = "?"
(c = TUnknownPositionalContent() or c = TUnknownKeyContent()) and
result = "Element" and
arg = "?"
)
or
cs = TAnyElementContent() and result = "Element" and arg = "any"
cs = TAnyElementContentSet() and result = "Element" and arg = "any"
or
exists(Content::KnownElementContent kec |
cs = TKnownOrUnknownElementContent(kec) and
cs = TKnownOrUnknownKeyContentSet(kec) or cs = TKnownOrUnknownPositionalContentSet(kec)
|
result = "Element" and
arg = kec.getIndex().serialize()
)
@@ -102,13 +104,13 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PowershellDataF
bindingset[token]
ContentSet decodeUnknownContent(AccessPath::AccessPathTokenBase token) {
token.getName() = "Element" and
result = TSingletonContent(TUnknownElementContent())
result = TSingletonContentSet(TUnknownKeyOrPositionContent())
}
bindingset[token]
ContentSet decodeUnknownWithContent(AccessPath::AccessPathTokenBase token) {
token.getName() = "WithElement" and
result = TAnyElementContent()
result = TAnyElementContentSet()
}
}
@@ -152,12 +154,12 @@ module Private {
/** Gets a summary component that represents an element in a collection at an unknown index. */
SummaryComponent elementUnknown() {
result = SC::content(TSingletonContent(TUnknownElementContent()))
result = SC::content(TSingletonContentSet(TUnknownKeyOrPositionContent()))
}
/** Gets a summary component that represents an element in a collection at a known index. */
SummaryComponent elementKnown(ConstantValue cv) {
result = SC::content(TSingletonContent(Content::getElementContent(cv)))
result = SC::content(TSingletonContentSet(Content::getKnownElementContent(cv)))
}
/**
@@ -165,9 +167,14 @@ module Private {
* known index `cv`, or an unknown index.
*/
SummaryComponent elementKnownOrUnknown(ConstantValue cv) {
result = SC::content(TKnownOrUnknownElementContent(TKnownElementContent(cv)))
result =
SC::content(any(ContentSet cs |
cs.isKnownOrUnknownElement(Content::getKnownElementContent(cv))
))
or
not exists(TKnownElementContent(cv)) and
not exists(
any(ContentSet cs | cs.isKnownOrUnknownElement(Content::getKnownElementContent(cv)))
) and
result = elementUnknown()
}
@@ -181,7 +188,7 @@ module Private {
*
* but is more efficient, because it is represented by a single value.
*/
SummaryComponent elementAny() { result = SC::content(TAnyElementContent()) }
SummaryComponent elementAny() { result = SC::content(TAnyElementContentSet()) }
/** Gets a summary component that represents the return value of a call. */
SummaryComponent return() { result = SC::return(any(NormalReturnKind rk)) }

View File

@@ -31,9 +31,10 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
or
variableWriteActual(bb, i, v, _)
or
exists(ProcessBlockCfgNode processBlock |
bb.getNode(i) = processBlock and
exists(ProcessBlockCfgNode processBlock | bb.getNode(i) = processBlock |
processBlock.getPipelineIteratorVariable() = v
or
processBlock.getAPipelineBypropertyNameIteratorVariable() = v
)
or
parameterWrite(bb, i, v)
@@ -301,7 +302,8 @@ class NormalParameter extends Parameter {
private newtype TParameterExt =
TNormalParameter(NormalParameter p) or
TThisMethodParameter(Method m) or
TPipelineParameter(PipelineParameter p)
TPipelineParameter(PipelineParameter p) or
TPipelineByPropertyNameParameter(PipelineByPropertyNameParameter p)
/** A normal parameter or an implicit `this` parameter. */
class ParameterExt extends TParameterExt {
@@ -311,11 +313,17 @@ class ParameterExt extends TParameterExt {
PipelineParameter asPipelineParameter() { this = TPipelineParameter(result) }
PipelineByPropertyNameParameter asPipelineByPropertyNameParameter() {
this = TPipelineByPropertyNameParameter(result)
}
predicate isInitializedBy(WriteDefinition def) {
def = getParameterDef(this.asParameter())
or
def = getParameterDef(this.asPipelineParameter())
or
def = getParameterDef(this.asPipelineByPropertyNameParameter())
or
def.(Ssa::ThisDefinition).getSourceVariable().getDeclaringScope() = this.asThis().getBody()
}
@@ -323,7 +331,7 @@ class ParameterExt extends TParameterExt {
result =
[
this.asParameter().toString(), this.asThis().toString(),
this.asPipelineParameter().toString()
this.asPipelineParameter().toString(), this.asPipelineByPropertyNameParameter().toString()
]
}
@@ -331,7 +339,8 @@ class ParameterExt extends TParameterExt {
result =
[
this.asParameter().getLocation(), this.asThis().getLocation(),
this.asPipelineParameter().getLocation()
this.asPipelineParameter().getLocation(),
this.asPipelineByPropertyNameParameter().getLocation()
]
}
}

View File

@@ -271,8 +271,14 @@
| functions.ps1:28:5:28:8 | sum | functions.ps1:28:12:28:12 | 0 | |
| functions.ps1:28:5:28:12 | ...=... | functions.ps1:28:5:28:8 | sum | |
| functions.ps1:28:12:28:12 | 0 | functions.ps1:29:25:29:32 | numbers | |
| functions.ps1:29:5:32:5 | forach(... in ...) | functions.ps1:29:14:29:20 | number | non-empty |
| functions.ps1:29:5:32:5 | forach(... in ...) | functions.ps1:33:5:33:8 | [Stmt] sum | empty |
| functions.ps1:29:14:29:20 | number | functions.ps1:29:35:32:5 | {...} | |
| functions.ps1:29:25:29:32 | numbers | functions.ps1:29:5:32:5 | forach(... in ...) | |
| functions.ps1:29:35:32:5 | {...} | functions.ps1:31:9:31:23 | ...=... | |
| functions.ps1:31:9:31:12 | sum | functions.ps1:31:17:31:23 | number | |
| functions.ps1:31:9:31:23 | ...=... | functions.ps1:31:9:31:12 | sum | |
| functions.ps1:31:17:31:23 | number | functions.ps1:29:5:32:5 | forach(... in ...) | |
| functions.ps1:33:5:33:8 | [Stmt] sum | functions.ps1:33:5:33:8 | sum | |
| functions.ps1:33:5:33:8 | sum | functions.ps1:22:33:34:1 | exit {...} (normal) | |
| functions.ps1:36:1:52:1 | def of Add-Numbers-From-Pipeline | functions.ps1:1:1:54:0 | exit {...} (normal) | |
@@ -284,9 +290,10 @@
| functions.ps1:41:5:43:5 | {...} | functions.ps1:42:9:42:16 | ...=... | |
| functions.ps1:42:9:42:12 | sum | functions.ps1:42:16:42:16 | 0 | |
| functions.ps1:42:9:42:16 | ...=... | functions.ps1:42:9:42:12 | sum | |
| functions.ps1:42:16:42:16 | 0 | functions.ps1:44:5:47:5 | [synth] pipeline | |
| functions.ps1:44:5:47:5 | [synth] pipeline | functions.ps1:44:5:47:5 | {...} | |
| functions.ps1:44:5:47:5 | {...} | functions.ps1:46:9:46:18 | ...=... | |
| functions.ps1:42:16:42:16 | 0 | functions.ps1:44:5:47:5 | {...} | |
| functions.ps1:44:5:47:5 | [synth] pipeline | functions.ps1:46:9:46:18 | ...=... | non-empty |
| functions.ps1:44:5:47:5 | [synth] pipeline | functions.ps1:48:5:51:5 | {...} | empty |
| functions.ps1:44:5:47:5 | {...} | functions.ps1:44:5:47:5 | [synth] pipeline | |
| functions.ps1:46:9:46:12 | sum | functions.ps1:46:17:46:18 | __pipeline_iterator | |
| functions.ps1:46:9:46:18 | ...=... | functions.ps1:46:9:46:12 | sum | |
| functions.ps1:46:17:46:18 | __pipeline_iterator | functions.ps1:44:5:47:5 | [synth] pipeline | |
@@ -452,7 +459,15 @@
| loops.ps1:51:5:51:10 | ...=... | loops.ps1:51:5:51:6 | a | |
| loops.ps1:51:10:51:10 | 0 | loops.ps1:52:25:52:36 | letterArray | |
| loops.ps1:52:5:55:5 | forach(... in ...) | loops.ps1:49:23:56:1 | exit {...} (normal) | empty |
| loops.ps1:52:5:55:5 | forach(... in ...) | loops.ps1:52:14:52:20 | letter | non-empty |
| loops.ps1:52:14:52:20 | letter | loops.ps1:53:5:55:5 | {...} | |
| loops.ps1:52:25:52:36 | letterArray | loops.ps1:52:5:55:5 | forach(... in ...) | |
| loops.ps1:53:5:55:5 | {...} | loops.ps1:54:9:54:19 | ...=... | |
| loops.ps1:54:9:54:10 | a | loops.ps1:54:14:54:15 | a | |
| loops.ps1:54:9:54:19 | ...=... | loops.ps1:54:9:54:10 | a | |
| loops.ps1:54:14:54:15 | a | loops.ps1:54:19:54:19 | 1 | |
| loops.ps1:54:14:54:19 | ...+... | loops.ps1:52:5:55:5 | forach(... in ...) | |
| loops.ps1:54:19:54:19 | 1 | loops.ps1:54:14:54:19 | ...+... | |
| loops.ps1:58:1:68:1 | def of Test-For-Ever | loops.ps1:1:1:70:0 | exit {...} (normal) | |
| loops.ps1:58:24:68:1 | [synth] pipeline | loops.ps1:59:5:67:5 | {...} | |
| loops.ps1:58:24:68:1 | enter {...} | loops.ps1:58:24:68:1 | {...} | |

View File

@@ -6,33 +6,33 @@ edges
| test.ps1:10:1:10:5 | [post] arr1 [element 3] | test.ps1:11:6:11:10 | arr1 [element 3] | provenance | |
| test.ps1:10:12:10:21 | Call to Source | test.ps1:10:1:10:5 | [post] arr1 [element 3] | provenance | |
| test.ps1:11:6:11:10 | arr1 [element 3] | test.ps1:11:6:11:13 | ...[...] | provenance | |
| test.ps1:14:1:14:5 | [post] arr2 [element] | test.ps1:15:6:15:10 | arr2 [element] | provenance | |
| test.ps1:14:19:14:28 | Call to Source | test.ps1:14:1:14:5 | [post] arr2 [element] | provenance | |
| test.ps1:15:6:15:10 | arr2 [element] | test.ps1:15:6:15:13 | ...[...] | provenance | |
| test.ps1:14:1:14:5 | [post] arr2 [unknown] | test.ps1:15:6:15:10 | arr2 [unknown] | provenance | |
| test.ps1:14:19:14:28 | Call to Source | test.ps1:14:1:14:5 | [post] arr2 [unknown] | provenance | |
| test.ps1:15:6:15:10 | arr2 [unknown] | test.ps1:15:6:15:13 | ...[...] | provenance | |
| test.ps1:17:1:17:5 | [post] arr3 [element 3] | test.ps1:18:6:18:10 | arr3 [element 3] | provenance | |
| test.ps1:17:12:17:21 | Call to Source | test.ps1:17:1:17:5 | [post] arr3 [element 3] | provenance | |
| test.ps1:18:6:18:10 | arr3 [element 3] | test.ps1:18:6:18:20 | ...[...] | provenance | |
| test.ps1:20:1:20:5 | [post] arr4 [element] | test.ps1:21:6:21:10 | arr4 [element] | provenance | |
| test.ps1:20:20:20:29 | Call to Source | test.ps1:20:1:20:5 | [post] arr4 [element] | provenance | |
| test.ps1:21:6:21:10 | arr4 [element] | test.ps1:21:6:21:21 | ...[...] | provenance | |
| test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | test.ps1:24:6:24:10 | arr5 [element, element 1] | provenance | |
| test.ps1:23:1:23:16 | [post] ...[...] [element 1] | test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | provenance | |
| test.ps1:20:1:20:5 | [post] arr4 [unknown] | test.ps1:21:6:21:10 | arr4 [unknown] | provenance | |
| test.ps1:20:20:20:29 | Call to Source | test.ps1:20:1:20:5 | [post] arr4 [unknown] | provenance | |
| test.ps1:21:6:21:10 | arr4 [unknown] | test.ps1:21:6:21:21 | ...[...] | provenance | |
| test.ps1:23:1:23:5 | [post] arr5 [unknown, element 1] | test.ps1:24:6:24:10 | arr5 [unknown, element 1] | provenance | |
| test.ps1:23:1:23:16 | [post] ...[...] [element 1] | test.ps1:23:1:23:5 | [post] arr5 [unknown, element 1] | provenance | |
| test.ps1:23:23:23:32 | Call to Source | test.ps1:23:1:23:16 | [post] ...[...] [element 1] | provenance | |
| test.ps1:24:6:24:10 | arr5 [element, element 1] | test.ps1:24:6:24:21 | ...[...] [element 1] | provenance | |
| test.ps1:24:6:24:10 | arr5 [unknown, element 1] | test.ps1:24:6:24:21 | ...[...] [element 1] | provenance | |
| test.ps1:24:6:24:21 | ...[...] [element 1] | test.ps1:24:6:24:24 | ...[...] | provenance | |
| test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | test.ps1:28:6:28:10 | arr6 [element 1, element] | provenance | |
| test.ps1:27:1:27:8 | [post] ...[...] [element] | test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | provenance | |
| test.ps1:27:23:27:32 | Call to Source | test.ps1:27:1:27:8 | [post] ...[...] [element] | provenance | |
| test.ps1:28:6:28:10 | arr6 [element 1, element] | test.ps1:28:6:28:13 | ...[...] [element] | provenance | |
| test.ps1:28:6:28:13 | ...[...] [element] | test.ps1:28:6:28:24 | ...[...] | provenance | |
| test.ps1:31:1:31:5 | [post] arr7 [element, element] | test.ps1:32:6:32:10 | arr7 [element, element] | provenance | |
| test.ps1:31:1:31:5 | [post] arr7 [element, element] | test.ps1:33:6:33:10 | arr7 [element, element] | provenance | |
| test.ps1:31:1:31:16 | [post] ...[...] [element] | test.ps1:31:1:31:5 | [post] arr7 [element, element] | provenance | |
| test.ps1:31:31:31:40 | Call to Source | test.ps1:31:1:31:16 | [post] ...[...] [element] | provenance | |
| test.ps1:32:6:32:10 | arr7 [element, element] | test.ps1:32:6:32:13 | ...[...] [element] | provenance | |
| test.ps1:32:6:32:13 | ...[...] [element] | test.ps1:32:6:32:16 | ...[...] | provenance | |
| test.ps1:33:6:33:10 | arr7 [element, element] | test.ps1:33:6:33:21 | ...[...] [element] | provenance | |
| test.ps1:33:6:33:21 | ...[...] [element] | test.ps1:33:6:33:32 | ...[...] | provenance | |
| test.ps1:27:1:27:5 | [post] arr6 [element 1, unknown] | test.ps1:28:6:28:10 | arr6 [element 1, unknown] | provenance | |
| test.ps1:27:1:27:8 | [post] ...[...] [unknown] | test.ps1:27:1:27:5 | [post] arr6 [element 1, unknown] | provenance | |
| test.ps1:27:23:27:32 | Call to Source | test.ps1:27:1:27:8 | [post] ...[...] [unknown] | provenance | |
| test.ps1:28:6:28:10 | arr6 [element 1, unknown] | test.ps1:28:6:28:13 | ...[...] [unknown] | provenance | |
| test.ps1:28:6:28:13 | ...[...] [unknown] | test.ps1:28:6:28:24 | ...[...] | provenance | |
| test.ps1:31:1:31:5 | [post] arr7 [unknown, unknown] | test.ps1:32:6:32:10 | arr7 [unknown, unknown] | provenance | |
| test.ps1:31:1:31:5 | [post] arr7 [unknown, unknown] | test.ps1:33:6:33:10 | arr7 [unknown, unknown] | provenance | |
| test.ps1:31:1:31:16 | [post] ...[...] [unknown] | test.ps1:31:1:31:5 | [post] arr7 [unknown, unknown] | provenance | |
| test.ps1:31:31:31:40 | Call to Source | test.ps1:31:1:31:16 | [post] ...[...] [unknown] | provenance | |
| test.ps1:32:6:32:10 | arr7 [unknown, unknown] | test.ps1:32:6:32:13 | ...[...] [unknown] | provenance | |
| test.ps1:32:6:32:13 | ...[...] [unknown] | test.ps1:32:6:32:16 | ...[...] | provenance | |
| test.ps1:33:6:33:10 | arr7 [unknown, unknown] | test.ps1:33:6:33:21 | ...[...] [unknown] | provenance | |
| test.ps1:33:6:33:21 | ...[...] [unknown] | test.ps1:33:6:33:32 | ...[...] | provenance | |
| test.ps1:35:6:35:16 | Call to Source | test.ps1:37:15:37:16 | x | provenance | |
| test.ps1:37:9:37:16 | ...,... [element 2] | test.ps1:40:6:40:10 | arr8 [element 2] | provenance | |
| test.ps1:37:9:37:16 | ...,... [element 2] | test.ps1:41:6:41:10 | arr8 [element 2] | provenance | |
@@ -53,15 +53,15 @@ edges
| test.ps1:66:10:66:20 | Call to Source | test.ps1:69:5:69:6 | x | provenance | |
| test.ps1:67:10:67:20 | Call to Source | test.ps1:70:5:70:6 | y | provenance | |
| test.ps1:68:10:68:20 | Call to Source | test.ps1:70:9:70:10 | z | provenance | |
| test.ps1:69:5:69:6 | x | test.ps1:73:6:73:12 | Call to produce [element] | provenance | |
| test.ps1:70:5:70:6 | y | test.ps1:73:6:73:12 | Call to produce [element] | provenance | |
| test.ps1:70:9:70:10 | z | test.ps1:73:6:73:12 | Call to produce [element] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [element] | test.ps1:74:6:74:7 | x [element] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [element] | test.ps1:75:6:75:7 | x [element] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [element] | test.ps1:76:6:76:7 | x [element] | provenance | |
| test.ps1:74:6:74:7 | x [element] | test.ps1:74:6:74:10 | ...[...] | provenance | |
| test.ps1:75:6:75:7 | x [element] | test.ps1:75:6:75:10 | ...[...] | provenance | |
| test.ps1:76:6:76:7 | x [element] | test.ps1:76:6:76:10 | ...[...] | provenance | |
| test.ps1:69:5:69:6 | x | test.ps1:73:6:73:12 | Call to produce [unknown index] | provenance | |
| test.ps1:70:5:70:6 | y | test.ps1:73:6:73:12 | Call to produce [unknown index] | provenance | |
| test.ps1:70:9:70:10 | z | test.ps1:73:6:73:12 | Call to produce [unknown index] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [unknown index] | test.ps1:74:6:74:7 | x [unknown index] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [unknown index] | test.ps1:75:6:75:7 | x [unknown index] | provenance | |
| test.ps1:73:6:73:12 | Call to produce [unknown index] | test.ps1:76:6:76:7 | x [unknown index] | provenance | |
| test.ps1:74:6:74:7 | x [unknown index] | test.ps1:74:6:74:10 | ...[...] | provenance | |
| test.ps1:75:6:75:7 | x [unknown index] | test.ps1:75:6:75:10 | ...[...] | provenance | |
| test.ps1:76:6:76:7 | x [unknown index] | test.ps1:76:6:76:10 | ...[...] | provenance | |
| test.ps1:78:9:81:1 | ${...} [element a] | test.ps1:83:6:83:10 | hash [element a] | provenance | |
| test.ps1:78:9:81:1 | ${...} [element a] | test.ps1:87:6:87:10 | hash [element a] | provenance | |
| test.ps1:79:7:79:17 | Call to Source | test.ps1:78:9:81:1 | ${...} [element a] | provenance | |
@@ -79,38 +79,38 @@ nodes
| test.ps1:10:12:10:21 | Call to Source | semmle.label | Call to Source |
| test.ps1:11:6:11:10 | arr1 [element 3] | semmle.label | arr1 [element 3] |
| test.ps1:11:6:11:13 | ...[...] | semmle.label | ...[...] |
| test.ps1:14:1:14:5 | [post] arr2 [element] | semmle.label | [post] arr2 [element] |
| test.ps1:14:1:14:5 | [post] arr2 [unknown] | semmle.label | [post] arr2 [unknown] |
| test.ps1:14:19:14:28 | Call to Source | semmle.label | Call to Source |
| test.ps1:15:6:15:10 | arr2 [element] | semmle.label | arr2 [element] |
| test.ps1:15:6:15:10 | arr2 [unknown] | semmle.label | arr2 [unknown] |
| test.ps1:15:6:15:13 | ...[...] | semmle.label | ...[...] |
| test.ps1:17:1:17:5 | [post] arr3 [element 3] | semmle.label | [post] arr3 [element 3] |
| test.ps1:17:12:17:21 | Call to Source | semmle.label | Call to Source |
| test.ps1:18:6:18:10 | arr3 [element 3] | semmle.label | arr3 [element 3] |
| test.ps1:18:6:18:20 | ...[...] | semmle.label | ...[...] |
| test.ps1:20:1:20:5 | [post] arr4 [element] | semmle.label | [post] arr4 [element] |
| test.ps1:20:1:20:5 | [post] arr4 [unknown] | semmle.label | [post] arr4 [unknown] |
| test.ps1:20:20:20:29 | Call to Source | semmle.label | Call to Source |
| test.ps1:21:6:21:10 | arr4 [element] | semmle.label | arr4 [element] |
| test.ps1:21:6:21:10 | arr4 [unknown] | semmle.label | arr4 [unknown] |
| test.ps1:21:6:21:21 | ...[...] | semmle.label | ...[...] |
| test.ps1:23:1:23:5 | [post] arr5 [element, element 1] | semmle.label | [post] arr5 [element, element 1] |
| test.ps1:23:1:23:5 | [post] arr5 [unknown, element 1] | semmle.label | [post] arr5 [unknown, element 1] |
| test.ps1:23:1:23:16 | [post] ...[...] [element 1] | semmle.label | [post] ...[...] [element 1] |
| test.ps1:23:23:23:32 | Call to Source | semmle.label | Call to Source |
| test.ps1:24:6:24:10 | arr5 [element, element 1] | semmle.label | arr5 [element, element 1] |
| test.ps1:24:6:24:10 | arr5 [unknown, element 1] | semmle.label | arr5 [unknown, element 1] |
| test.ps1:24:6:24:21 | ...[...] [element 1] | semmle.label | ...[...] [element 1] |
| test.ps1:24:6:24:24 | ...[...] | semmle.label | ...[...] |
| test.ps1:27:1:27:5 | [post] arr6 [element 1, element] | semmle.label | [post] arr6 [element 1, element] |
| test.ps1:27:1:27:8 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
| test.ps1:27:1:27:5 | [post] arr6 [element 1, unknown] | semmle.label | [post] arr6 [element 1, unknown] |
| test.ps1:27:1:27:8 | [post] ...[...] [unknown] | semmle.label | [post] ...[...] [unknown] |
| test.ps1:27:23:27:32 | Call to Source | semmle.label | Call to Source |
| test.ps1:28:6:28:10 | arr6 [element 1, element] | semmle.label | arr6 [element 1, element] |
| test.ps1:28:6:28:13 | ...[...] [element] | semmle.label | ...[...] [element] |
| test.ps1:28:6:28:10 | arr6 [element 1, unknown] | semmle.label | arr6 [element 1, unknown] |
| test.ps1:28:6:28:13 | ...[...] [unknown] | semmle.label | ...[...] [unknown] |
| test.ps1:28:6:28:24 | ...[...] | semmle.label | ...[...] |
| test.ps1:31:1:31:5 | [post] arr7 [element, element] | semmle.label | [post] arr7 [element, element] |
| test.ps1:31:1:31:16 | [post] ...[...] [element] | semmle.label | [post] ...[...] [element] |
| test.ps1:31:1:31:5 | [post] arr7 [unknown, unknown] | semmle.label | [post] arr7 [unknown, unknown] |
| test.ps1:31:1:31:16 | [post] ...[...] [unknown] | semmle.label | [post] ...[...] [unknown] |
| test.ps1:31:31:31:40 | Call to Source | semmle.label | Call to Source |
| test.ps1:32:6:32:10 | arr7 [element, element] | semmle.label | arr7 [element, element] |
| test.ps1:32:6:32:13 | ...[...] [element] | semmle.label | ...[...] [element] |
| test.ps1:32:6:32:10 | arr7 [unknown, unknown] | semmle.label | arr7 [unknown, unknown] |
| test.ps1:32:6:32:13 | ...[...] [unknown] | semmle.label | ...[...] [unknown] |
| test.ps1:32:6:32:16 | ...[...] | semmle.label | ...[...] |
| test.ps1:33:6:33:10 | arr7 [element, element] | semmle.label | arr7 [element, element] |
| test.ps1:33:6:33:21 | ...[...] [element] | semmle.label | ...[...] [element] |
| test.ps1:33:6:33:10 | arr7 [unknown, unknown] | semmle.label | arr7 [unknown, unknown] |
| test.ps1:33:6:33:21 | ...[...] [unknown] | semmle.label | ...[...] [unknown] |
| test.ps1:33:6:33:32 | ...[...] | semmle.label | ...[...] |
| test.ps1:35:6:35:16 | Call to Source | semmle.label | Call to Source |
| test.ps1:37:9:37:16 | ...,... [element 2] | semmle.label | ...,... [element 2] |
@@ -138,12 +138,12 @@ nodes
| test.ps1:69:5:69:6 | x | semmle.label | x |
| test.ps1:70:5:70:6 | y | semmle.label | y |
| test.ps1:70:9:70:10 | z | semmle.label | z |
| test.ps1:73:6:73:12 | Call to produce [element] | semmle.label | Call to produce [element] |
| test.ps1:74:6:74:7 | x [element] | semmle.label | x [element] |
| test.ps1:73:6:73:12 | Call to produce [unknown index] | semmle.label | Call to produce [unknown index] |
| test.ps1:74:6:74:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:74:6:74:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:75:6:75:7 | x [element] | semmle.label | x [element] |
| test.ps1:75:6:75:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:75:6:75:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:76:6:76:7 | x [element] | semmle.label | x [element] |
| test.ps1:76:6:76:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:76:6:76:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:78:9:81:1 | ${...} [element a] | semmle.label | ${...} [element a] |
| test.ps1:79:7:79:17 | Call to Source | semmle.label | Call to Source |

View File

@@ -6,11 +6,11 @@
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:4:1:4:2 | b | test.ps1:5:4:5:5 | b |
| test.ps1:4:6:4:12 | Call to GetBool | test.ps1:4:1:4:2 | b |
| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
| test.ps1:5:1:7:1 | phi (a2) | test.ps1:8:6:8:8 | a2 |
| test.ps1:5:4:5:5 | b | test.ps1:10:14:10:15 | b |
| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi |
| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi (a2) |
| test.ps1:6:11:6:16 | Call to Source | test.ps1:6:5:6:7 | a2 |
| test.ps1:6:11:6:16 | [input] phi | test.ps1:5:1:7:1 | phi |
| test.ps1:6:11:6:16 | [input] phi (a2) | test.ps1:5:1:7:1 | phi (a2) |
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |

View File

@@ -7,11 +7,11 @@
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:4:1:4:2 | b | test.ps1:5:4:5:5 | b |
| test.ps1:4:6:4:12 | Call to GetBool | test.ps1:4:1:4:2 | b |
| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
| test.ps1:5:1:7:1 | phi (a2) | test.ps1:8:6:8:8 | a2 |
| test.ps1:5:4:5:5 | b | test.ps1:10:14:10:15 | b |
| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi |
| test.ps1:6:5:6:7 | a2 | test.ps1:6:11:6:16 | [input] phi (a2) |
| test.ps1:6:11:6:16 | Call to Source | test.ps1:6:5:6:7 | a2 |
| test.ps1:6:11:6:16 | [input] phi | test.ps1:5:1:7:1 | phi |
| test.ps1:6:11:6:16 | [input] phi (a2) | test.ps1:5:1:7:1 | phi (a2) |
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:24:22 | pre-return value for {...} |
| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |

View File

@@ -3,24 +3,21 @@ edges
| test.ps1:2:10:2:19 | Call to Source | test.ps1:5:5:5:6 | x | provenance | |
| test.ps1:3:10:3:19 | Call to Source | test.ps1:6:5:6:6 | y | provenance | |
| test.ps1:4:10:4:19 | Call to Source | test.ps1:6:9:6:10 | z | provenance | |
| test.ps1:5:5:5:6 | x | test.ps1:17:1:17:7 | Call to produce [element] | provenance | |
| test.ps1:6:5:6:6 | y | test.ps1:17:1:17:7 | Call to produce [element] | provenance | |
| test.ps1:6:9:6:10 | z | test.ps1:17:1:17:7 | Call to produce [element] | provenance | |
| test.ps1:5:5:5:6 | x | test.ps1:17:1:17:7 | Call to produce [unknown index] | provenance | |
| test.ps1:6:5:6:6 | y | test.ps1:17:1:17:7 | Call to produce [unknown index] | provenance | |
| test.ps1:6:9:6:10 | z | test.ps1:17:1:17:7 | Call to produce [unknown index] | provenance | |
| test.ps1:9:29:15:1 | [synth] pipeline [element 0] | test.ps1:12:5:14:5 | [synth] pipeline [element 0] | provenance | |
| test.ps1:9:29:15:1 | [synth] pipeline [element 1] | test.ps1:12:5:14:5 | [synth] pipeline [element 1] | provenance | |
| test.ps1:9:29:15:1 | [synth] pipeline [element] | test.ps1:12:5:14:5 | [synth] pipeline [element] | provenance | |
| test.ps1:9:29:15:1 | [synth] pipeline [unknown index] | test.ps1:12:5:14:5 | [synth] pipeline [unknown index] | provenance | |
| test.ps1:12:5:14:5 | [synth] pipeline [element 0] | test.ps1:13:9:13:15 | __pipeline_iterator | provenance | |
| test.ps1:12:5:14:5 | [synth] pipeline [element 1] | test.ps1:13:9:13:15 | __pipeline_iterator | provenance | |
| test.ps1:12:5:14:5 | [synth] pipeline [element] | test.ps1:13:9:13:15 | __pipeline_iterator | provenance | |
| test.ps1:17:1:17:7 | Call to produce [element] | test.ps1:9:29:15:1 | [synth] pipeline [element] | provenance | |
| test.ps1:17:1:17:7 | Call to produce [element] | test.ps1:17:1:17:7 | Call to produce [element] | provenance | |
| test.ps1:12:5:14:5 | [synth] pipeline [unknown index] | test.ps1:13:9:13:15 | __pipeline_iterator | provenance | |
| test.ps1:17:1:17:7 | Call to produce [unknown index] | test.ps1:9:29:15:1 | [synth] pipeline [unknown index] | provenance | |
| test.ps1:19:6:19:15 | Call to Source | test.ps1:21:1:21:2 | x | provenance | |
| test.ps1:20:6:20:15 | Call to Source | test.ps1:21:5:21:6 | y | provenance | |
| test.ps1:21:1:21:2 | x | test.ps1:21:1:21:6 | ...,... [element 0] | provenance | |
| test.ps1:21:1:21:6 | ...,... [element 0] | test.ps1:9:29:15:1 | [synth] pipeline [element 0] | provenance | |
| test.ps1:21:1:21:6 | ...,... [element 0] | test.ps1:21:1:21:6 | ...,... [element 0] | provenance | |
| test.ps1:21:1:21:6 | ...,... [element 1] | test.ps1:9:29:15:1 | [synth] pipeline [element 1] | provenance | |
| test.ps1:21:1:21:6 | ...,... [element 1] | test.ps1:21:1:21:6 | ...,... [element 1] | provenance | |
| test.ps1:21:5:21:6 | y | test.ps1:21:1:21:6 | ...,... [element 1] | provenance | |
| test.ps1:23:38:27:1 | [synth] pipeline [element 0] | test.ps1:24:5:26:5 | [synth] pipeline [element 0] | provenance | |
| test.ps1:23:38:27:1 | [synth] pipeline [element 1] | test.ps1:24:5:26:5 | [synth] pipeline [element 1] | provenance | |
@@ -30,10 +27,26 @@ edges
| test.ps1:30:6:30:15 | Call to Source | test.ps1:31:5:31:6 | y | provenance | |
| test.ps1:31:1:31:2 | x | test.ps1:31:1:31:6 | ...,... [element 0] | provenance | |
| test.ps1:31:1:31:6 | ...,... [element 0] | test.ps1:23:38:27:1 | [synth] pipeline [element 0] | provenance | |
| test.ps1:31:1:31:6 | ...,... [element 0] | test.ps1:31:1:31:6 | ...,... [element 0] | provenance | |
| test.ps1:31:1:31:6 | ...,... [element 1] | test.ps1:23:38:27:1 | [synth] pipeline [element 1] | provenance | |
| test.ps1:31:1:31:6 | ...,... [element 1] | test.ps1:31:1:31:6 | ...,... [element 1] | provenance | |
| test.ps1:31:5:31:6 | y | test.ps1:31:1:31:6 | ...,... [element 1] | provenance | |
| test.ps1:42:60:48:1 | x [element 0, element x] | test.ps1:45:5:47:5 | x [element 0, element x] | provenance | |
| test.ps1:42:60:48:1 | x [element 1, element x] | test.ps1:45:5:47:5 | x [element 1, element x] | provenance | |
| test.ps1:42:60:48:1 | x [element 2, element x] | test.ps1:45:5:47:5 | x [element 2, element x] | provenance | |
| test.ps1:45:5:47:5 | x [element 0, element x] | test.ps1:46:9:46:15 | __pipeline_iterator for x | provenance | |
| test.ps1:45:5:47:5 | x [element 1, element x] | test.ps1:46:9:46:15 | __pipeline_iterator for x | provenance | |
| test.ps1:45:5:47:5 | x [element 2, element x] | test.ps1:46:9:46:15 | __pipeline_iterator for x | provenance | |
| test.ps1:50:1:50:33 | [...]... [element x] | test.ps1:50:1:50:105 | ...,... [element 0, element x] | provenance | |
| test.ps1:50:1:50:105 | ...,... [element 0, element x] | test.ps1:42:60:48:1 | x [element 0, element x] | provenance | |
| test.ps1:50:1:50:105 | ...,... [element 1, element x] | test.ps1:42:60:48:1 | x [element 1, element x] | provenance | |
| test.ps1:50:1:50:105 | ...,... [element 2, element x] | test.ps1:42:60:48:1 | x [element 2, element x] | provenance | |
| test.ps1:50:17:50:33 | ${...} [element x] | test.ps1:50:1:50:33 | [...]... [element x] | provenance | |
| test.ps1:50:23:50:32 | Call to Source | test.ps1:50:17:50:33 | ${...} [element x] | provenance | |
| test.ps1:50:36:50:69 | [...]... [element x] | test.ps1:50:1:50:105 | ...,... [element 1, element x] | provenance | |
| test.ps1:50:52:50:69 | ${...} [element x] | test.ps1:50:36:50:69 | [...]... [element x] | provenance | |
| test.ps1:50:58:50:68 | Call to Source | test.ps1:50:52:50:69 | ${...} [element x] | provenance | |
| test.ps1:50:72:50:105 | [...]... [element x] | test.ps1:50:1:50:105 | ...,... [element 2, element x] | provenance | |
| test.ps1:50:88:50:105 | ${...} [element x] | test.ps1:50:72:50:105 | [...]... [element x] | provenance | |
| test.ps1:50:94:50:104 | Call to Source | test.ps1:50:88:50:105 | ${...} [element x] | provenance | |
nodes
| test.ps1:2:10:2:19 | Call to Source | semmle.label | Call to Source |
| test.ps1:3:10:3:19 | Call to Source | semmle.label | Call to Source |
@@ -43,19 +56,16 @@ nodes
| test.ps1:6:9:6:10 | z | semmle.label | z |
| test.ps1:9:29:15:1 | [synth] pipeline [element 0] | semmle.label | [synth] pipeline [element 0] |
| test.ps1:9:29:15:1 | [synth] pipeline [element 1] | semmle.label | [synth] pipeline [element 1] |
| test.ps1:9:29:15:1 | [synth] pipeline [element] | semmle.label | [synth] pipeline [element] |
| test.ps1:9:29:15:1 | [synth] pipeline [unknown index] | semmle.label | [synth] pipeline [unknown index] |
| test.ps1:12:5:14:5 | [synth] pipeline [element 0] | semmle.label | [synth] pipeline [element 0] |
| test.ps1:12:5:14:5 | [synth] pipeline [element 1] | semmle.label | [synth] pipeline [element 1] |
| test.ps1:12:5:14:5 | [synth] pipeline [element] | semmle.label | [synth] pipeline [element] |
| test.ps1:12:5:14:5 | [synth] pipeline [unknown index] | semmle.label | [synth] pipeline [unknown index] |
| test.ps1:13:9:13:15 | __pipeline_iterator | semmle.label | __pipeline_iterator |
| test.ps1:17:1:17:7 | Call to produce [element] | semmle.label | Call to produce [element] |
| test.ps1:17:1:17:7 | Call to produce [element] | semmle.label | Call to produce [element] |
| test.ps1:17:1:17:7 | Call to produce [unknown index] | semmle.label | Call to produce [unknown index] |
| test.ps1:19:6:19:15 | Call to Source | semmle.label | Call to Source |
| test.ps1:20:6:20:15 | Call to Source | semmle.label | Call to Source |
| test.ps1:21:1:21:2 | x | semmle.label | x |
| test.ps1:21:1:21:6 | ...,... [element 0] | semmle.label | ...,... [element 0] |
| test.ps1:21:1:21:6 | ...,... [element 0] | semmle.label | ...,... [element 0] |
| test.ps1:21:1:21:6 | ...,... [element 1] | semmle.label | ...,... [element 1] |
| test.ps1:21:1:21:6 | ...,... [element 1] | semmle.label | ...,... [element 1] |
| test.ps1:21:5:21:6 | y | semmle.label | y |
| test.ps1:23:38:27:1 | [synth] pipeline [element 0] | semmle.label | [synth] pipeline [element 0] |
@@ -67,16 +77,29 @@ nodes
| test.ps1:30:6:30:15 | Call to Source | semmle.label | Call to Source |
| test.ps1:31:1:31:2 | x | semmle.label | x |
| test.ps1:31:1:31:6 | ...,... [element 0] | semmle.label | ...,... [element 0] |
| test.ps1:31:1:31:6 | ...,... [element 0] | semmle.label | ...,... [element 0] |
| test.ps1:31:1:31:6 | ...,... [element 1] | semmle.label | ...,... [element 1] |
| test.ps1:31:1:31:6 | ...,... [element 1] | semmle.label | ...,... [element 1] |
| test.ps1:31:5:31:6 | y | semmle.label | y |
| test.ps1:42:60:48:1 | x [element 0, element x] | semmle.label | x [element 0, element x] |
| test.ps1:42:60:48:1 | x [element 1, element x] | semmle.label | x [element 1, element x] |
| test.ps1:42:60:48:1 | x [element 2, element x] | semmle.label | x [element 2, element x] |
| test.ps1:45:5:47:5 | x [element 0, element x] | semmle.label | x [element 0, element x] |
| test.ps1:45:5:47:5 | x [element 1, element x] | semmle.label | x [element 1, element x] |
| test.ps1:45:5:47:5 | x [element 2, element x] | semmle.label | x [element 2, element x] |
| test.ps1:46:9:46:15 | __pipeline_iterator for x | semmle.label | __pipeline_iterator for x |
| test.ps1:50:1:50:33 | [...]... [element x] | semmle.label | [...]... [element x] |
| test.ps1:50:1:50:105 | ...,... [element 0, element x] | semmle.label | ...,... [element 0, element x] |
| test.ps1:50:1:50:105 | ...,... [element 1, element x] | semmle.label | ...,... [element 1, element x] |
| test.ps1:50:1:50:105 | ...,... [element 2, element x] | semmle.label | ...,... [element 2, element x] |
| test.ps1:50:17:50:33 | ${...} [element x] | semmle.label | ${...} [element x] |
| test.ps1:50:23:50:32 | Call to Source | semmle.label | Call to Source |
| test.ps1:50:36:50:69 | [...]... [element x] | semmle.label | [...]... [element x] |
| test.ps1:50:52:50:69 | ${...} [element x] | semmle.label | ${...} [element x] |
| test.ps1:50:58:50:68 | Call to Source | semmle.label | Call to Source |
| test.ps1:50:72:50:105 | [...]... [element x] | semmle.label | [...]... [element x] |
| test.ps1:50:88:50:105 | ${...} [element x] | semmle.label | ${...} [element x] |
| test.ps1:50:94:50:104 | Call to Source | semmle.label | Call to Source |
subpaths
testFailures
| test.ps1:36:13:36:30 | # $ hasValueFlow=8 | Missing result: hasValueFlow=8 |
| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=9 |
| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=10 |
| test.ps1:46:17:46:66 | # $ hasValueFlow=9 hasValueFlow=10 hasValueFlow=11 | Missing result: hasValueFlow=11 |
#select
| test.ps1:13:9:13:15 | __pipeline_iterator | test.ps1:2:10:2:19 | Call to Source | test.ps1:13:9:13:15 | __pipeline_iterator | $@ | test.ps1:2:10:2:19 | Call to Source | Call to Source |
| test.ps1:13:9:13:15 | __pipeline_iterator | test.ps1:3:10:3:19 | Call to Source | test.ps1:13:9:13:15 | __pipeline_iterator | $@ | test.ps1:3:10:3:19 | Call to Source | Call to Source |
@@ -85,3 +108,6 @@ testFailures
| test.ps1:13:9:13:15 | __pipeline_iterator | test.ps1:20:6:20:15 | Call to Source | test.ps1:13:9:13:15 | __pipeline_iterator | $@ | test.ps1:20:6:20:15 | Call to Source | Call to Source |
| test.ps1:25:9:25:15 | __pipeline_iterator | test.ps1:29:6:29:15 | Call to Source | test.ps1:25:9:25:15 | __pipeline_iterator | $@ | test.ps1:29:6:29:15 | Call to Source | Call to Source |
| test.ps1:25:9:25:15 | __pipeline_iterator | test.ps1:30:6:30:15 | Call to Source | test.ps1:25:9:25:15 | __pipeline_iterator | $@ | test.ps1:30:6:30:15 | Call to Source | Call to Source |
| test.ps1:46:9:46:15 | __pipeline_iterator for x | test.ps1:50:23:50:32 | Call to Source | test.ps1:46:9:46:15 | __pipeline_iterator for x | $@ | test.ps1:50:23:50:32 | Call to Source | Call to Source |
| test.ps1:46:9:46:15 | __pipeline_iterator for x | test.ps1:50:58:50:68 | Call to Source | test.ps1:46:9:46:15 | __pipeline_iterator for x | $@ | test.ps1:50:58:50:68 | Call to Source | Call to Source |
| test.ps1:46:9:46:15 | __pipeline_iterator for x | test.ps1:50:94:50:104 | Call to Source | test.ps1:46:9:46:15 | __pipeline_iterator for x | $@ | test.ps1:50:94:50:104 | Call to Source | Call to Source |

View File

@@ -33,7 +33,7 @@ $x, $y | consumeWithProcessAnonymous
function consumeValueFromPipelineByPropertyNameWithoutProcess {
Param([Parameter(ValueFromPipelineByPropertyName)] $x)
Sink $x # $ hasValueFlow=8
Sink $x # $ MISSING: hasValueFlow=8
}
$x = Source "8"

View File

@@ -2,37 +2,37 @@ models
edges
| test.ps1:2:5:2:14 | Call to Source | test.ps1:5:6:5:19 | Call to callSourceOnce | provenance | |
| test.ps1:5:6:5:19 | Call to callSourceOnce | test.ps1:6:6:6:7 | x | provenance | |
| test.ps1:9:5:9:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [element] | provenance | |
| test.ps1:10:5:10:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [element] | provenance | |
| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | test.ps1:15:6:15:7 | x [element] | provenance | |
| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | test.ps1:16:6:16:7 | x [element] | provenance | |
| test.ps1:15:6:15:7 | x [element] | test.ps1:15:6:15:10 | ...[...] | provenance | |
| test.ps1:16:6:16:7 | x [element] | test.ps1:16:6:16:10 | ...[...] | provenance | |
| test.ps1:9:5:9:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [unknown index] | provenance | |
| test.ps1:10:5:10:14 | Call to Source | test.ps1:13:6:13:20 | Call to callSourceTwice [unknown index] | provenance | |
| test.ps1:13:6:13:20 | Call to callSourceTwice [unknown index] | test.ps1:15:6:15:7 | x [unknown index] | provenance | |
| test.ps1:13:6:13:20 | Call to callSourceTwice [unknown index] | test.ps1:16:6:16:7 | x [unknown index] | provenance | |
| test.ps1:15:6:15:7 | x [unknown index] | test.ps1:15:6:15:10 | ...[...] | provenance | |
| test.ps1:16:6:16:7 | x [unknown index] | test.ps1:16:6:16:10 | ...[...] | provenance | |
| test.ps1:19:12:19:21 | Call to Source | test.ps1:22:6:22:18 | Call to returnSource1 | provenance | |
| test.ps1:22:6:22:18 | Call to returnSource1 | test.ps1:23:6:23:7 | x | provenance | |
| test.ps1:26:10:26:19 | Call to Source | test.ps1:27:5:27:6 | x | provenance | |
| test.ps1:27:5:27:6 | x | test.ps1:32:6:32:18 | Call to returnSource2 [element] | provenance | |
| test.ps1:27:5:27:6 | x | test.ps1:32:6:32:18 | Call to returnSource2 [unknown index] | provenance | |
| test.ps1:28:10:28:19 | Call to Source | test.ps1:29:12:29:13 | y | provenance | |
| test.ps1:29:12:29:13 | y | test.ps1:32:6:32:18 | Call to returnSource2 [element] | provenance | |
| test.ps1:32:6:32:18 | Call to returnSource2 [element] | test.ps1:33:6:33:7 | x [element] | provenance | |
| test.ps1:32:6:32:18 | Call to returnSource2 [element] | test.ps1:34:6:34:7 | x [element] | provenance | |
| test.ps1:33:6:33:7 | x [element] | test.ps1:33:6:33:10 | ...[...] | provenance | |
| test.ps1:34:6:34:7 | x [element] | test.ps1:34:6:34:10 | ...[...] | provenance | |
| test.ps1:38:9:38:18 | Call to Source | test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | provenance | |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | test.ps1:43:6:43:7 | x [element] | provenance | |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | test.ps1:44:6:44:7 | x [element] | provenance | |
| test.ps1:43:6:43:7 | x [element] | test.ps1:43:6:43:10 | ...[...] | provenance | |
| test.ps1:44:6:44:7 | x [element] | test.ps1:44:6:44:10 | ...[...] | provenance | |
| test.ps1:29:12:29:13 | y | test.ps1:32:6:32:18 | Call to returnSource2 [unknown index] | provenance | |
| test.ps1:32:6:32:18 | Call to returnSource2 [unknown index] | test.ps1:33:6:33:7 | x [unknown index] | provenance | |
| test.ps1:32:6:32:18 | Call to returnSource2 [unknown index] | test.ps1:34:6:34:7 | x [unknown index] | provenance | |
| test.ps1:33:6:33:7 | x [unknown index] | test.ps1:33:6:33:10 | ...[...] | provenance | |
| test.ps1:34:6:34:7 | x [unknown index] | test.ps1:34:6:34:10 | ...[...] | provenance | |
| test.ps1:38:9:38:18 | Call to Source | test.ps1:42:6:42:21 | Call to callSourceInLoop [unknown index] | provenance | |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [unknown index] | test.ps1:43:6:43:7 | x [unknown index] | provenance | |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [unknown index] | test.ps1:44:6:44:7 | x [unknown index] | provenance | |
| test.ps1:43:6:43:7 | x [unknown index] | test.ps1:43:6:43:10 | ...[...] | provenance | |
| test.ps1:44:6:44:7 | x [unknown index] | test.ps1:44:6:44:10 | ...[...] | provenance | |
nodes
| test.ps1:2:5:2:14 | Call to Source | semmle.label | Call to Source |
| test.ps1:5:6:5:19 | Call to callSourceOnce | semmle.label | Call to callSourceOnce |
| test.ps1:6:6:6:7 | x | semmle.label | x |
| test.ps1:9:5:9:14 | Call to Source | semmle.label | Call to Source |
| test.ps1:10:5:10:14 | Call to Source | semmle.label | Call to Source |
| test.ps1:13:6:13:20 | Call to callSourceTwice [element] | semmle.label | Call to callSourceTwice [element] |
| test.ps1:15:6:15:7 | x [element] | semmle.label | x [element] |
| test.ps1:13:6:13:20 | Call to callSourceTwice [unknown index] | semmle.label | Call to callSourceTwice [unknown index] |
| test.ps1:15:6:15:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:15:6:15:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:16:6:16:7 | x [element] | semmle.label | x [element] |
| test.ps1:16:6:16:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:16:6:16:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:19:12:19:21 | Call to Source | semmle.label | Call to Source |
| test.ps1:22:6:22:18 | Call to returnSource1 | semmle.label | Call to returnSource1 |
@@ -41,16 +41,16 @@ nodes
| test.ps1:27:5:27:6 | x | semmle.label | x |
| test.ps1:28:10:28:19 | Call to Source | semmle.label | Call to Source |
| test.ps1:29:12:29:13 | y | semmle.label | y |
| test.ps1:32:6:32:18 | Call to returnSource2 [element] | semmle.label | Call to returnSource2 [element] |
| test.ps1:33:6:33:7 | x [element] | semmle.label | x [element] |
| test.ps1:32:6:32:18 | Call to returnSource2 [unknown index] | semmle.label | Call to returnSource2 [unknown index] |
| test.ps1:33:6:33:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:33:6:33:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:34:6:34:7 | x [element] | semmle.label | x [element] |
| test.ps1:34:6:34:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:34:6:34:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:38:9:38:18 | Call to Source | semmle.label | Call to Source |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [element] | semmle.label | Call to callSourceInLoop [element] |
| test.ps1:43:6:43:7 | x [element] | semmle.label | x [element] |
| test.ps1:42:6:42:21 | Call to callSourceInLoop [unknown index] | semmle.label | Call to callSourceInLoop [unknown index] |
| test.ps1:43:6:43:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:43:6:43:10 | ...[...] | semmle.label | ...[...] |
| test.ps1:44:6:44:7 | x [element] | semmle.label | x [element] |
| test.ps1:44:6:44:7 | x [unknown index] | semmle.label | x [unknown index] |
| test.ps1:44:6:44:10 | ...[...] | semmle.label | ...[...] |
subpaths
testFailures