mirror of
https://github.com/github/codeql.git
synced 2026-05-25 00:27:09 +02:00
Merge pull request #180 from microsoft/powershell-ast-modernization-follow-up
PS: Fix PowerShell dataflow/taint-tracking failures
This commit is contained in:
@@ -53,5 +53,13 @@ class If extends Expr, TIf {
|
||||
)
|
||||
}
|
||||
|
||||
StmtBlock getABranch(boolean b) {
|
||||
b = true and result = this.getAThen()
|
||||
or
|
||||
b = false and result = this.getElse()
|
||||
}
|
||||
|
||||
StmtBlock getABranch() { result = this.getAThen() or result = this.getElse() }
|
||||
|
||||
predicate hasElse() { exists(this.getElse()) }
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ class ScriptBlock extends Ast, TScriptBlock {
|
||||
result = this.getParameter(index)
|
||||
)
|
||||
or
|
||||
i = ThisVar() and
|
||||
result = this.getThisParameter()
|
||||
or
|
||||
exists(int index |
|
||||
i = scriptBlockUsing(index) and
|
||||
result = this.getUsingStmt(index)
|
||||
@@ -90,13 +93,14 @@ class ScriptBlock extends Ast, TScriptBlock {
|
||||
or
|
||||
any(Synthesis s).pipelineParameterHasIndex(this, i) and
|
||||
synthChild(getRawAst(this), PipelineParamVar(), result)
|
||||
or
|
||||
i = -1 and
|
||||
synthChild(getRawAst(this), ThisVar(), result)
|
||||
}
|
||||
|
||||
Parameter getThisParameter() { synthChild(getRawAst(this), ThisVar(), result) }
|
||||
|
||||
/**
|
||||
* Gets a parameter of this block.
|
||||
*
|
||||
* Note: This does not include the `this` parameter, but it does include pipeline parameters.
|
||||
*/
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ class Synthesis extends TSynthesis {
|
||||
|
||||
predicate functionName(FunctionBase f, string name) { none() }
|
||||
|
||||
predicate getAnAccess(VarAccessSynth va, Variable v) { none() }
|
||||
|
||||
predicate memberName(Member m, string name) { none() }
|
||||
|
||||
predicate typeName(Type t, string name) { none() }
|
||||
@@ -116,13 +118,26 @@ Raw::Ast getRawAst(Ast r) { r = getResultAst(result) }
|
||||
|
||||
private module ThisSynthesis {
|
||||
private class ThisSynthesis extends Synthesis {
|
||||
private predicate thisAccess(Raw::Ast parent, ChildIndex i, Child child, Raw::Scope scope) {
|
||||
scope = parent.getScope() and
|
||||
parent.getChild(toRawChildIndex(i)).(Raw::VarAccess).getUserPath().toLowerCase() = "this" and
|
||||
child = SynthChild(VarAccessSynthKind(TVariableSynth(scope, ThisVar())))
|
||||
}
|
||||
|
||||
override predicate child(Raw::Ast parent, ChildIndex i, Child child) {
|
||||
parent instanceof Raw::MethodScriptBlock and
|
||||
i = ThisVar() and
|
||||
child = SynthChild(VarSynthKind(ThisVarKind()))
|
||||
or
|
||||
parent.getChild(toRawChildIndex(i)).(Raw::VarAccess).getUserPath().toLowerCase() = "this" and
|
||||
child = SynthChild(VarAccessSynthKind(TVariableSynth(parent.getScope(), ThisVar())))
|
||||
this.thisAccess(parent, i, child, _)
|
||||
}
|
||||
|
||||
final override predicate getAnAccess(VarAccessSynth va, Variable v) {
|
||||
exists(Raw::Ast parent, Raw::Scope scope, ChildIndex i |
|
||||
this.thisAccess(parent, i, _, scope) and
|
||||
v = TVariableSynth(scope, ThisVar()) and
|
||||
va = TVarAccessSynth(parent, i)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate variableSynthName(VariableSynth v, string name) {
|
||||
@@ -731,18 +746,26 @@ private module IteratorAccessSynth {
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate getAnAccess(VarAccessSynth va, Variable v) {
|
||||
exists(Raw::Ast parent, ChildIndex i, Raw::VarAccess r |
|
||||
this.expr(parent, i, r, _) and
|
||||
va = TVarAccessSynth(parent, i) and
|
||||
v = this.varAccess(r)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate exprStmtExpr(ExprStmt e, Expr expr) {
|
||||
exists(Raw::Ast p, Raw::VarAccess va, Raw::CmdExpr cmdExpr, ChildIndex i1, ChildIndex i2 |
|
||||
this.stmt(p, i1, _, _) and
|
||||
this.expr(cmdExpr, i2, va, _) and
|
||||
e = TExprStmtSynth(p, i1) and
|
||||
expr = TVarAccessSynth(cmdExpr, i2, this.varAccess(va))
|
||||
expr = TVarAccessSynth(cmdExpr, i2)
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getResultAstImpl(Raw::Ast r) {
|
||||
exists(Raw::Ast parent, ChildIndex i | this.expr(parent, i, r, _) |
|
||||
result = TVarAccessSynth(parent, i, this.varAccess(r))
|
||||
result = TVarAccessSynth(parent, i)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ private predicate hasScopeAndName(VariableImpl variable, Scope::Range scope, str
|
||||
scope = variable.getDeclaringScopeImpl()
|
||||
}
|
||||
|
||||
private predicate access(Raw::VarAccess va, VariableImpl v) {
|
||||
predicate access(Raw::VarAccess va, VariableImpl v) {
|
||||
exists(string name, Scope::Range scope |
|
||||
pragma[only_bind_into](name) = variableNameInScope(va, scope)
|
||||
|
|
||||
@@ -150,11 +150,11 @@ private module Cached {
|
||||
)
|
||||
} or
|
||||
TVariableSynth(Raw::Ast scope, ChildIndex i) { mkSynthChild(VarSynthKind(_), scope, i) } or
|
||||
TVarAccessReal(Raw::VarAccess va, Variable v) { access(va, v) } or
|
||||
TVarAccessSynth(Raw::Ast parent, ChildIndex i, Variable v) {
|
||||
mkSynthChild(VarAccessRealKind(v), parent, i)
|
||||
TVarAccessReal(Raw::VarAccess va) { access(va, _) } or
|
||||
TVarAccessSynth(Raw::Ast parent, ChildIndex i) {
|
||||
mkSynthChild(VarAccessRealKind(_), parent, i)
|
||||
or
|
||||
mkSynthChild(VarAccessSynthKind(v), parent, i)
|
||||
mkSynthChild(VarAccessSynthKind(_), parent, i)
|
||||
} or
|
||||
TWhileStmt(Raw::WhileStmt w) or
|
||||
TTypeNameExpr(Raw::TypeNameExpr t) or
|
||||
@@ -277,7 +277,7 @@ private module Cached {
|
||||
n = TTypeConstraint(result) or
|
||||
n = TUnaryExpr(result) or
|
||||
n = TUsingStmt(result) or
|
||||
n = TVarAccessReal(result, _) or
|
||||
n = TVarAccessReal(result) or
|
||||
n = TWhileStmt(result) or
|
||||
n = TFunctionDefinitionStmt(result) or
|
||||
n = TExpandableSubExpr(result) or
|
||||
@@ -308,7 +308,7 @@ private module Cached {
|
||||
result = TFunctionSynth(parent, i) or
|
||||
result = TBoolLiteral(parent, i) or
|
||||
result = TNullLiteral(parent, i) or
|
||||
result = TVarAccessSynth(parent, i, _) or
|
||||
result = TVarAccessSynth(parent, i) or
|
||||
result = TEnvVariable(parent, i) or
|
||||
result = TTypeSynth(parent, i) or
|
||||
result = TAutomaticVariable(parent, i) or
|
||||
|
||||
@@ -95,25 +95,23 @@ module Private {
|
||||
|
||||
class VarAccessReal extends VarAccessImpl, TVarAccessReal {
|
||||
Raw::VarAccess va;
|
||||
Variable v;
|
||||
|
||||
VarAccessReal() { this = TVarAccessReal(va, v) }
|
||||
VarAccessReal() { this = TVarAccessReal(va) }
|
||||
|
||||
final override Variable getVariableImpl() { result = v }
|
||||
final override Variable getVariableImpl() { access(va, result) }
|
||||
|
||||
final override string toString() { result = v.getName() }
|
||||
final override string toString() { result = va.getUserPath() }
|
||||
}
|
||||
|
||||
class VarAccessSynth extends VarAccessImpl, TVarAccessSynth {
|
||||
Raw::Ast parent;
|
||||
ChildIndex i;
|
||||
Variable v;
|
||||
|
||||
VarAccessSynth() { this = TVarAccessSynth(parent, i, v) }
|
||||
VarAccessSynth() { this = TVarAccessSynth(parent, i) }
|
||||
|
||||
final override Variable getVariableImpl() { result = v }
|
||||
final override Variable getVariableImpl() { any(Synthesis s).getAnAccess(this, result) }
|
||||
|
||||
final override string toString() { result = v.getName() }
|
||||
final override string toString() { result = this.getVariableImpl().getName() }
|
||||
|
||||
final override Location getLocation() { result = parent.getLocation() }
|
||||
}
|
||||
|
||||
@@ -284,6 +284,26 @@ class ProcessBlockCfgNode extends NamedBlockCfgNode {
|
||||
ScriptBlockCfgNode getScriptBlock() { result.getProcessBlock() = this }
|
||||
}
|
||||
|
||||
private class CatchClauseChildMapping extends NonExprChildMapping, CatchClause {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getBody() or child = this.getACatchType()
|
||||
}
|
||||
}
|
||||
|
||||
class CatchClauseCfgNode extends AstCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "CatchClauseCfgNode" }
|
||||
|
||||
CatchClauseChildMapping s;
|
||||
|
||||
CatchClause getCatchClause() { result = s }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
|
||||
TypeConstraint getCatchType(int i) { result = s.getCatchType(i) }
|
||||
|
||||
TypeConstraint getACatchType() { result = this.getCatchType(_) }
|
||||
}
|
||||
|
||||
module ExprNodes {
|
||||
private class ArrayExprChildMapping extends ExprChildMapping, ArrayExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
@@ -371,7 +391,7 @@ module ExprNodes {
|
||||
ExprCfgNode getOperand() { e.hasCfgChild(e.getOperand(), this, result) }
|
||||
}
|
||||
|
||||
class ConstExprChildMapping extends ExprChildMapping, ConstExpr {
|
||||
private class ConstExprChildMapping extends ExprChildMapping, ConstExpr {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -383,7 +403,7 @@ module ExprNodes {
|
||||
override ConstExpr getExpr() { result = e }
|
||||
}
|
||||
|
||||
class ConvertExprChildMapping extends ExprChildMapping, ConvertExpr {
|
||||
private class ConvertExprChildMapping extends ExprChildMapping, ConvertExpr {
|
||||
override predicate relevantChild(Ast child) { child = this.getExpr() }
|
||||
}
|
||||
|
||||
@@ -397,7 +417,7 @@ module ExprNodes {
|
||||
ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
|
||||
}
|
||||
|
||||
class IndexExprChildMapping extends ExprChildMapping, IndexExpr {
|
||||
private class IndexExprChildMapping extends ExprChildMapping, IndexExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getBase()
|
||||
or
|
||||
@@ -457,7 +477,7 @@ module ExprNodes {
|
||||
override IndexExprReadAccess getExpr() { result = e }
|
||||
}
|
||||
|
||||
class CallExprChildMapping extends ExprChildMapping, CallExpr {
|
||||
private class CallExprChildMapping extends ExprChildMapping, CallExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getQualifier()
|
||||
or
|
||||
@@ -503,7 +523,7 @@ module ExprNodes {
|
||||
predicate isStatic() { this.getExpr().isStatic() }
|
||||
}
|
||||
|
||||
class ObjectCreationChildMapping extends CallExprChildMapping instanceof ObjectCreation {
|
||||
private class ObjectCreationChildMapping extends CallExprChildMapping instanceof ObjectCreation {
|
||||
override predicate relevantChild(Ast child) { child = super.getConstructedTypeExpr() }
|
||||
}
|
||||
|
||||
@@ -522,7 +542,7 @@ module ExprNodes {
|
||||
}
|
||||
}
|
||||
|
||||
class CallOperatorChildMapping extends CallExprChildMapping instanceof CallOperator {
|
||||
private class CallOperatorChildMapping extends CallExprChildMapping instanceof CallOperator {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -536,7 +556,7 @@ module ExprNodes {
|
||||
ExprCfgNode getCommand() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
class MemberExprChildMapping extends ExprChildMapping, MemberExpr {
|
||||
private class MemberExprChildMapping extends ExprChildMapping, MemberExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getQualifier()
|
||||
or
|
||||
@@ -603,7 +623,7 @@ module ExprNodes {
|
||||
override MemberExprReadAccess getExpr() { result = e }
|
||||
}
|
||||
|
||||
class TypeNameExprChildMapping extends ExprChildMapping, TypeNameExpr {
|
||||
private class TypeNameExprChildMapping extends ExprChildMapping, TypeNameExpr {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -631,7 +651,7 @@ module ExprNodes {
|
||||
override QualifiedTypeNameExpr getExpr() { result = e }
|
||||
}
|
||||
|
||||
class ErrorExprChildMapping extends ExprChildMapping, ErrorExpr {
|
||||
private class ErrorExprChildMapping extends ExprChildMapping, ErrorExpr {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -643,7 +663,7 @@ module ExprNodes {
|
||||
override ErrorExpr getExpr() { result = e }
|
||||
}
|
||||
|
||||
class ScriptBlockExprChildMapping extends ExprChildMapping, ScriptBlockExpr {
|
||||
private class ScriptBlockExprChildMapping extends ExprChildMapping, ScriptBlockExpr {
|
||||
override predicate relevantChild(Ast child) { child = this.getBody() }
|
||||
}
|
||||
|
||||
@@ -657,7 +677,7 @@ module ExprNodes {
|
||||
ScriptBlockCfgNode getBody() { e.hasCfgChild(e.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class StringLiteralExprChildMapping extends ExprChildMapping, StringConstExpr {
|
||||
private class StringLiteralExprChildMapping extends ExprChildMapping, StringConstExpr {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -671,7 +691,7 @@ module ExprNodes {
|
||||
string getValueString() { result = e.getValueString() }
|
||||
}
|
||||
|
||||
class ExpandableStringExprChildMapping extends ExprChildMapping, ExpandableStringExpr {
|
||||
private class ExpandableStringExprChildMapping extends ExprChildMapping, ExpandableStringExpr {
|
||||
override predicate relevantChild(Ast child) { child = this.getAnExpr() }
|
||||
}
|
||||
|
||||
@@ -728,7 +748,7 @@ module ExprNodes {
|
||||
override VarReadAccess getExpr() { result = e }
|
||||
}
|
||||
|
||||
class HashTableExprChildMapping extends ExprChildMapping, HashTableExpr {
|
||||
private class HashTableExprChildMapping extends ExprChildMapping, HashTableExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getAKey()
|
||||
or
|
||||
@@ -747,7 +767,7 @@ module ExprNodes {
|
||||
|
||||
ExprCfgNode getAnKey() { result = this.getKey(_) }
|
||||
|
||||
ExprCfgNode getValue(int i) { e.hasCfgChild(e.getKey(i), this, result) }
|
||||
ExprCfgNode getValue(int i) { e.hasCfgChild(e.getValue(i), this, result) }
|
||||
|
||||
ExprCfgNode getValueFromKey(ExprCfgNode key) {
|
||||
exists(int i |
|
||||
@@ -759,7 +779,7 @@ module ExprNodes {
|
||||
ExprCfgNode getAValue() { result = this.getValue(_) }
|
||||
}
|
||||
|
||||
class PipelineChildMapping extends ExprChildMapping, Pipeline {
|
||||
private class PipelineChildMapping extends ExprChildMapping, Pipeline {
|
||||
override predicate relevantChild(Ast child) { child = this.getAComponent() }
|
||||
}
|
||||
|
||||
@@ -775,7 +795,7 @@ module ExprNodes {
|
||||
ExprCfgNode getAComponent() { result = this.getComponent(_) }
|
||||
}
|
||||
|
||||
class PipelineChainChildMapping extends ExprChildMapping, PipelineChain {
|
||||
private class PipelineChainChildMapping extends ExprChildMapping, PipelineChain {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getLeft() or child = this.getRight()
|
||||
}
|
||||
@@ -793,7 +813,7 @@ module ExprNodes {
|
||||
ExprCfgNode getRight() { e.hasCfgChild(e.getRight(), this, result) }
|
||||
}
|
||||
|
||||
class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
|
||||
private class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getCondition()
|
||||
or
|
||||
@@ -827,7 +847,7 @@ module ExprNodes {
|
||||
ExprCfgNode getABranch() { result = this.getBranch(_) }
|
||||
}
|
||||
|
||||
class ExpandableSubExprChildMapping extends ExprChildMapping, ExpandableSubExpr {
|
||||
private class ExpandableSubExprChildMapping extends ExprChildMapping, ExpandableSubExpr {
|
||||
override predicate relevantChild(Ast child) { child = this.getExpr() }
|
||||
}
|
||||
|
||||
@@ -841,7 +861,7 @@ module ExprNodes {
|
||||
ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
|
||||
}
|
||||
|
||||
class UsingExprChildMapping extends ExprChildMapping, UsingExpr {
|
||||
private class UsingExprChildMapping extends ExprChildMapping, UsingExpr {
|
||||
override predicate relevantChild(Ast child) { child = this.getExpr() }
|
||||
}
|
||||
|
||||
@@ -855,7 +875,7 @@ module ExprNodes {
|
||||
ExprCfgNode getSubExpr() { e.hasCfgChild(e.getExpr(), this, result) }
|
||||
}
|
||||
|
||||
class AttributedExprChildMapping extends ExprChildMapping, AttributedExpr {
|
||||
private class AttributedExprChildMapping extends ExprChildMapping, AttributedExpr {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getExpr() or
|
||||
child = this.getAttribute()
|
||||
@@ -874,7 +894,7 @@ module ExprNodes {
|
||||
ExprCfgNode getAttribute() { e.hasCfgChild(e.getAttribute(), this, result) }
|
||||
}
|
||||
|
||||
class IfChildMapping extends ExprChildMapping, If {
|
||||
private class IfChildMapping extends ExprChildMapping, If {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getACondition()
|
||||
or
|
||||
@@ -900,9 +920,19 @@ module ExprNodes {
|
||||
StmtCfgNode getAThen() { result = this.getThen(_) }
|
||||
|
||||
StmtCfgNode getElse() { e.hasCfgChild(e.getElse(), this, result) }
|
||||
|
||||
StmtCfgNode getABranch(boolean b) {
|
||||
b = true and
|
||||
result = this.getAThen()
|
||||
or
|
||||
b = false and
|
||||
result = this.getElse()
|
||||
}
|
||||
|
||||
StmtCfgNode getABranch() { result = this.getABranch(_) }
|
||||
}
|
||||
|
||||
class LiteralChildMapping extends ExprChildMapping, Literal {
|
||||
private class LiteralChildMapping extends ExprChildMapping, Literal {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -914,7 +944,7 @@ module ExprNodes {
|
||||
override Literal getExpr() { result = e }
|
||||
}
|
||||
|
||||
class BoolLiteralChildMapping extends ExprChildMapping, BoolLiteral {
|
||||
private class BoolLiteralChildMapping extends ExprChildMapping, BoolLiteral {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -926,7 +956,7 @@ module ExprNodes {
|
||||
override BoolLiteral getExpr() { result = e }
|
||||
}
|
||||
|
||||
class NullLiteralChildMapping extends ExprChildMapping, NullLiteral {
|
||||
private class NullLiteralChildMapping extends ExprChildMapping, NullLiteral {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1004,7 +1034,7 @@ module StmtNodes {
|
||||
ExprCfgNode getRightHandSide() { s.hasCfgChild(s.getRightHandSide(), this, result) }
|
||||
}
|
||||
|
||||
class BreakStmtChildMapping extends NonExprChildMapping, BreakStmt {
|
||||
private class BreakStmtChildMapping extends NonExprChildMapping, BreakStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1016,7 +1046,7 @@ module StmtNodes {
|
||||
override BreakStmt getStmt() { result = s }
|
||||
}
|
||||
|
||||
class ContinueStmtChildMapping extends NonExprChildMapping, ContinueStmt {
|
||||
private class ContinueStmtChildMapping extends NonExprChildMapping, ContinueStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1028,7 +1058,7 @@ module StmtNodes {
|
||||
override ContinueStmt getStmt() { result = s }
|
||||
}
|
||||
|
||||
class DataStmtChildMapping extends NonExprChildMapping, DataStmt {
|
||||
private class DataStmtChildMapping extends NonExprChildMapping, DataStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getACmdAllowed() or child = this.getBody()
|
||||
}
|
||||
@@ -1048,13 +1078,27 @@ module StmtNodes {
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class DoUntilStmtChildMapping extends NonExprChildMapping, DoUntilStmt {
|
||||
private class LoopStmtChildMapping extends NonExprChildMapping, LoopStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getBody() }
|
||||
}
|
||||
|
||||
class LoopStmtCfgNode extends StmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "LoopStmtCfgNode" }
|
||||
|
||||
override LoopStmtChildMapping s;
|
||||
|
||||
override LoopStmt getStmt() { result = s }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
private class DoUntilStmtChildMapping extends LoopStmtChildMapping, DoUntilStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getCondition() or child = this.getBody()
|
||||
child = this.getCondition() or super.relevantChild(child)
|
||||
}
|
||||
}
|
||||
|
||||
class DoUntilStmtCfgNode extends StmtCfgNode {
|
||||
class DoUntilStmtCfgNode extends LoopStmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "DoUntilStmtCfgNode" }
|
||||
|
||||
override DoUntilStmtChildMapping s;
|
||||
@@ -1062,17 +1106,15 @@ module StmtNodes {
|
||||
override DoUntilStmt getStmt() { result = s }
|
||||
|
||||
ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class DoWhileStmtChildMapping extends NonExprChildMapping, DoWhileStmt {
|
||||
private class DoWhileStmtChildMapping extends LoopStmtChildMapping, DoWhileStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getCondition() or child = this.getBody()
|
||||
child = this.getCondition() or super.relevantChild(child)
|
||||
}
|
||||
}
|
||||
|
||||
class DoWhileStmtCfgNode extends StmtCfgNode {
|
||||
class DoWhileStmtCfgNode extends LoopStmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "DoWhileStmtCfgNode" }
|
||||
|
||||
override DoWhileStmtChildMapping s;
|
||||
@@ -1080,11 +1122,9 @@ module StmtNodes {
|
||||
override DoWhileStmt getStmt() { result = s }
|
||||
|
||||
ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class ErrorStmtChildMapping extends NonExprChildMapping, ErrorStmt {
|
||||
private class ErrorStmtChildMapping extends NonExprChildMapping, ErrorStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1096,7 +1136,7 @@ module StmtNodes {
|
||||
override ErrorStmt getStmt() { result = s }
|
||||
}
|
||||
|
||||
class ExitStmtChildMapping extends NonExprChildMapping, ExitStmt {
|
||||
private class ExitStmtChildMapping extends NonExprChildMapping, ExitStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getPipeline() }
|
||||
}
|
||||
|
||||
@@ -1110,7 +1150,7 @@ module StmtNodes {
|
||||
ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
|
||||
}
|
||||
|
||||
class DynamicStmtChildMapping extends NonExprChildMapping, DynamicStmt {
|
||||
private class DynamicStmtChildMapping extends NonExprChildMapping, DynamicStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getName() or child = this.getScriptBlock() or child = this.getHashTableExpr()
|
||||
}
|
||||
@@ -1130,13 +1170,13 @@ module StmtNodes {
|
||||
ExprCfgNode getHashTableExpr() { s.hasCfgChild(s.getHashTableExpr(), this, result) }
|
||||
}
|
||||
|
||||
class ForEachStmtChildMapping extends NonExprChildMapping, ForEachStmt {
|
||||
private class ForEachStmtChildMapping extends LoopStmtChildMapping, ForEachStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getVarAccess() or child = this.getIterableExpr() or child = this.getBody()
|
||||
child = this.getVarAccess() or child = this.getIterableExpr() or super.relevantChild(child)
|
||||
}
|
||||
}
|
||||
|
||||
class ForEachStmtCfgNode extends StmtCfgNode {
|
||||
class ForEachStmtCfgNode extends LoopStmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "ForEachStmtCfgNode" }
|
||||
|
||||
override ForEachStmtChildMapping s;
|
||||
@@ -1146,20 +1186,18 @@ module StmtNodes {
|
||||
ExprCfgNode getVarAccess() { s.hasCfgChild(s.getVarAccess(), this, result) }
|
||||
|
||||
ExprCfgNode getIterableExpr() { s.hasCfgChild(s.getIterableExpr(), this, result) }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class ForStmtChildMapping extends NonExprChildMapping, ForStmt {
|
||||
private class ForStmtChildMapping extends LoopStmtChildMapping, ForStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getInitializer() or
|
||||
child = this.getCondition() or
|
||||
child = this.getIterator() or
|
||||
child = this.getBody()
|
||||
super.relevantChild(child)
|
||||
}
|
||||
}
|
||||
|
||||
class ForStmtCfgNode extends StmtCfgNode {
|
||||
class ForStmtCfgNode extends LoopStmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "ForStmtCfgNode" }
|
||||
|
||||
override ForStmtChildMapping s;
|
||||
@@ -1171,11 +1209,9 @@ module StmtNodes {
|
||||
ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
|
||||
|
||||
AstCfgNode getIterator() { s.hasCfgChild(s.getIterator(), this, result) }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class GotoStmtChildMapping extends NonExprChildMapping, GotoStmt {
|
||||
private class GotoStmtChildMapping extends NonExprChildMapping, GotoStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getLabel() }
|
||||
}
|
||||
|
||||
@@ -1189,7 +1225,7 @@ module StmtNodes {
|
||||
ExprCfgNode getLabel() { s.hasCfgChild(s.getLabel(), this, result) }
|
||||
}
|
||||
|
||||
class ReturnStmtChildMapping extends NonExprChildMapping, ReturnStmt {
|
||||
private class ReturnStmtChildMapping extends NonExprChildMapping, ReturnStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getPipeline() }
|
||||
}
|
||||
|
||||
@@ -1203,7 +1239,7 @@ module StmtNodes {
|
||||
ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
|
||||
}
|
||||
|
||||
class StmtBlockChildMapping extends NonExprChildMapping, StmtBlock {
|
||||
private class StmtBlockChildMapping extends NonExprChildMapping, StmtBlock {
|
||||
override predicate relevantChild(Ast child) { child = this.getAStmt() }
|
||||
}
|
||||
|
||||
@@ -1219,7 +1255,7 @@ module StmtNodes {
|
||||
StmtCfgNode getAStmt() { result = this.getStmt(_) }
|
||||
}
|
||||
|
||||
class SwitchStmtChildMapping extends NonExprChildMapping, SwitchStmt {
|
||||
private class SwitchStmtChildMapping extends NonExprChildMapping, SwitchStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getCondition() or
|
||||
child = this.getDefault() or
|
||||
@@ -1248,7 +1284,7 @@ module StmtNodes {
|
||||
ExprCfgNode getAPattern() { result = this.getPattern(_) }
|
||||
}
|
||||
|
||||
class ThrowStmtChildMapping extends NonExprChildMapping, ThrowStmt {
|
||||
private class ThrowStmtChildMapping extends NonExprChildMapping, ThrowStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getPipeline() }
|
||||
}
|
||||
|
||||
@@ -1262,7 +1298,7 @@ module StmtNodes {
|
||||
ExprCfgNode getPipeline() { s.hasCfgChild(s.getPipeline(), this, result) }
|
||||
}
|
||||
|
||||
class TrapStmtChildMapping extends NonExprChildMapping, TrapStmt {
|
||||
private class TrapStmtChildMapping extends NonExprChildMapping, TrapStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getBody() }
|
||||
}
|
||||
|
||||
@@ -1276,7 +1312,7 @@ module StmtNodes {
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class TryStmtChildMapping extends NonExprChildMapping, TryStmt {
|
||||
private class TryStmtChildMapping extends NonExprChildMapping, TryStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getBody() or
|
||||
child = this.getFinally() or
|
||||
@@ -1298,7 +1334,7 @@ module StmtNodes {
|
||||
StmtCfgNode getCatchClause(int i) { s.hasCfgChild(s.getCatchClause(i), this, result) }
|
||||
}
|
||||
|
||||
class UsingStmtChildMapping extends NonExprChildMapping, UsingStmt {
|
||||
private class UsingStmtChildMapping extends NonExprChildMapping, UsingStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1310,14 +1346,14 @@ module StmtNodes {
|
||||
override UsingStmt getStmt() { result = s }
|
||||
}
|
||||
|
||||
class WhileStmtChildMapping extends NonExprChildMapping, WhileStmt {
|
||||
private class WhileStmtChildMapping extends LoopStmtChildMapping, WhileStmt {
|
||||
override predicate relevantChild(Ast child) {
|
||||
child = this.getCondition() or
|
||||
child = this.getBody()
|
||||
super.relevantChild(child)
|
||||
}
|
||||
}
|
||||
|
||||
class WhileStmtCfgNode extends StmtCfgNode {
|
||||
class WhileStmtCfgNode extends LoopStmtCfgNode {
|
||||
override string getAPrimaryQlClass() { result = "WhileStmtCfgNode" }
|
||||
|
||||
override WhileStmtChildMapping s;
|
||||
@@ -1325,11 +1361,9 @@ module StmtNodes {
|
||||
override WhileStmt getStmt() { result = s }
|
||||
|
||||
ExprCfgNode getCondition() { s.hasCfgChild(s.getCondition(), this, result) }
|
||||
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class ConfigurationChildMapping extends NonExprChildMapping, Configuration {
|
||||
private class ConfigurationChildMapping extends NonExprChildMapping, Configuration {
|
||||
override predicate relevantChild(Ast child) { child = this.getName() or child = this.getBody() }
|
||||
}
|
||||
|
||||
@@ -1345,7 +1379,7 @@ module StmtNodes {
|
||||
StmtCfgNode getBody() { s.hasCfgChild(s.getBody(), this, result) }
|
||||
}
|
||||
|
||||
class TypeStmtChildMapping extends NonExprChildMapping, TypeDefinitionStmt {
|
||||
private class TypeStmtChildMapping extends NonExprChildMapping, TypeDefinitionStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1369,7 +1403,7 @@ module StmtNodes {
|
||||
string getName() { result = s.getName() }
|
||||
}
|
||||
|
||||
class FunctionDefinitionChildMapping extends NonExprChildMapping, FunctionDefinitionStmt {
|
||||
private class FunctionDefinitionChildMapping extends NonExprChildMapping, FunctionDefinitionStmt {
|
||||
override predicate relevantChild(Ast child) { none() }
|
||||
}
|
||||
|
||||
@@ -1383,7 +1417,7 @@ module StmtNodes {
|
||||
FunctionBase getFunction() { result = s.getFunction() }
|
||||
}
|
||||
|
||||
class ExprStmtChildMapping extends NonExprChildMapping, ExprStmt {
|
||||
private class ExprStmtChildMapping extends NonExprChildMapping, ExprStmt {
|
||||
override predicate relevantChild(Ast child) { child = this.getExpr() }
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,30 @@ module Trees {
|
||||
|
||||
override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
this.succEntry(pred, c) and
|
||||
(
|
||||
first(super.getThisParameter(), succ)
|
||||
or
|
||||
not exists(super.getThisParameter()) and
|
||||
first(super.getParameter(0), succ)
|
||||
or
|
||||
not exists(super.getThisParameter()) and
|
||||
not exists(super.getAParameter()) and
|
||||
first(super.getBeginBlock(), succ)
|
||||
or
|
||||
not exists(super.getThisParameter()) and
|
||||
not exists(super.getAParameter()) and
|
||||
not exists(super.getBeginBlock()) and
|
||||
first(super.getProcessBlock(), succ)
|
||||
or
|
||||
not exists(super.getThisParameter()) and
|
||||
not exists(super.getAParameter()) and
|
||||
not exists(super.getBeginBlock()) and
|
||||
not exists(super.getProcessBlock()) and
|
||||
first(super.getEndBlock(), succ)
|
||||
)
|
||||
or
|
||||
last(super.getThisParameter(), pred, c) and
|
||||
completionIsNormal(c) and
|
||||
(
|
||||
first(super.getParameter(0), succ)
|
||||
or
|
||||
|
||||
@@ -113,7 +113,7 @@ module Ssa {
|
||||
|
||||
override ThisParameter getSourceVariable() { result = v }
|
||||
|
||||
final override string toString() { result = "self (" + v.getDeclaringScope() + ")" }
|
||||
final override string toString() { result = "this (" + v.getDeclaringScope() + ")" }
|
||||
|
||||
final override Location getLocation() { result = this.getControlFlowNode().getLocation() }
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ private import DataFlowDispatch
|
||||
private import SsaImpl as SsaImpl
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.powershell.frameworks.data.ModelsAsData
|
||||
private import PipelineReturns as PipelineReturns
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.(NodeImpl).getEnclosingCallable() }
|
||||
@@ -61,6 +62,8 @@ module SsaFlow {
|
||||
|
||||
private ParameterNodeImpl toParameterNode(SsaImpl::ParameterExt p) {
|
||||
result = TNormalParameterNode(p.asParameter())
|
||||
or
|
||||
result = TThisParameterNode(p.asThis())
|
||||
}
|
||||
|
||||
Impl::Node asNode(Node n) {
|
||||
@@ -85,6 +88,16 @@ module SsaFlow {
|
||||
}
|
||||
}
|
||||
|
||||
private module ArrayExprFlow {
|
||||
private module Input implements PipelineReturns::InputSig {
|
||||
predicate isSource(CfgNodes::AstCfgNode source) {
|
||||
source = any(CfgNodes::ExprNodes::ArrayExprCfgNode ae).getStmtBlock()
|
||||
}
|
||||
}
|
||||
|
||||
import PipelineReturns::Make<Input>
|
||||
}
|
||||
|
||||
/** Provides predicates related to local data flow. */
|
||||
module LocalFlow {
|
||||
pragma[nomagic]
|
||||
@@ -97,16 +110,13 @@ module LocalFlow {
|
||||
or
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ParenExprCfgNode).getSubExpr()
|
||||
or
|
||||
exists(
|
||||
CfgNodes::ExprNodes::ArrayExprCfgNode arrayExpr, EscapeContainer::EscapeContainer container
|
||||
|
|
||||
nodeTo.asExpr() = arrayExpr and
|
||||
container = arrayExpr.getStmtBlock().getAstNode() and
|
||||
nodeFrom.(AstNode).getCfgNode() = container.getAnEscapingElement() and
|
||||
not container.mayBeMultiReturned(_)
|
||||
)
|
||||
nodeFrom.asExpr() = nodeTo.asExpr().(CfgNodes::ExprNodes::ArrayExprCfgNode)
|
||||
or
|
||||
nodeFrom.(AstNode).getCfgNode() = nodeTo.(PreReturNodeImpl).getReturnedNode()
|
||||
exists(CfgNodes::ExprCfgNode e |
|
||||
e = nodeFrom.(AstNode).getCfgNode() and
|
||||
isReturned(e) and
|
||||
e.getScope() = nodeTo.(PreReturNodeImpl).getCfgScope()
|
||||
)
|
||||
or
|
||||
exists(CfgNode cfgNode |
|
||||
nodeFrom = TPreReturnNodeImpl(cfgNode, true) and
|
||||
@@ -118,10 +128,12 @@ module LocalFlow {
|
||||
nodeTo = TReturnNodeImpl(cfgNode.getScope())
|
||||
)
|
||||
or
|
||||
exists(CfgNode cfgNode |
|
||||
cfgNode = nodeFrom.(AstNode).getCfgNode() and
|
||||
isUniqueReturned(cfgNode) and
|
||||
nodeTo.(ReturnNodeImpl).getCfgScope() = cfgNode.getScope()
|
||||
exists(CfgNodes::ExprCfgNode e, CfgNodes::ScriptBlockCfgNode scriptBlock |
|
||||
e = nodeFrom.(AstNode).getCfgNode() and
|
||||
isReturned(e) and
|
||||
e.getScope() = scriptBlock.getAstNode() and
|
||||
not blockMayReturnMultipleValues(scriptBlock) and
|
||||
nodeTo.(ReturnNodeImpl).getCfgScope() = scriptBlock.getAstNode()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -164,7 +176,6 @@ private module Cached {
|
||||
cached
|
||||
newtype TNode =
|
||||
TExprNode(CfgNodes::ExprCfgNode n) or
|
||||
TStmtNode(CfgNodes::StmtCfgNode n) or
|
||||
TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
|
||||
TNormalParameterNode(SsaImpl::NormalParameter p) or
|
||||
TThisParameterNode(Method m) or
|
||||
@@ -183,8 +194,12 @@ private module Cached {
|
||||
n = any(CfgNodes::ExprNodes::IndexExprCfgNode index).getBase()
|
||||
} or
|
||||
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
|
||||
TPreReturnNodeImpl(CfgNodes::AstCfgNode n, Boolean isArray) { isMultiReturned(n) } or
|
||||
TImplicitWrapNode(CfgNodes::AstCfgNode n, Boolean shouldWrap) { isMultiReturned(n) } or
|
||||
TPreReturnNodeImpl(CfgNodes::ScriptBlockCfgNode scriptBlock, Boolean isArray) {
|
||||
blockMayReturnMultipleValues(scriptBlock)
|
||||
} or
|
||||
TImplicitWrapNode(CfgNodes::ScriptBlockCfgNode scriptBlock, Boolean shouldWrap) {
|
||||
blockMayReturnMultipleValues(scriptBlock)
|
||||
} or
|
||||
TReturnNodeImpl(CfgScope scope) or
|
||||
TProcessNode(ProcessBlock process) or
|
||||
TProcessPropertyByNameNode(PipelineByPropertyNameIteratorVariable iter) {
|
||||
@@ -549,7 +564,7 @@ private module ParameterNodes {
|
||||
|
||||
ThisParameterNode() { this = TThisParameterNode(m) }
|
||||
|
||||
override Parameter getParameter() { none() }
|
||||
override Parameter getParameter() { result = m.getThisParameter() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
m.getBody() = c.asCfgScope() and
|
||||
@@ -751,64 +766,41 @@ abstract class ReturnNode extends Node {
|
||||
abstract ReturnKind getKind();
|
||||
}
|
||||
|
||||
private module EscapeContainer {
|
||||
private import semmle.code.powershell.internal.AstEscape::Private
|
||||
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
|
||||
private ReturnKind rk;
|
||||
|
||||
private module ReturnContainerInterpreter implements InterpretAstInputSig {
|
||||
class T = CfgNodes::AstCfgNode;
|
||||
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
|
||||
|
||||
T interpret(Ast a) { result.(CfgNodes::ExprCfgNode).getExpr() = a } // TODO: Recutse into expr-to-stmt conversions
|
||||
}
|
||||
|
||||
class EscapeContainer extends AstEscape<ReturnContainerInterpreter>::Element {
|
||||
/** Holds if `n` may be returned multiples times. */
|
||||
predicate mayBeMultiReturned(CfgNode n) {
|
||||
n = this.getANode() and
|
||||
n.getASuccessor+() = n
|
||||
or
|
||||
this.getAChild().(EscapeContainer).mayBeMultiReturned(n)
|
||||
}
|
||||
}
|
||||
|
||||
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
|
||||
private ReturnKind rk;
|
||||
|
||||
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
|
||||
|
||||
override ReturnKind getKind() { result = rk }
|
||||
}
|
||||
override ReturnKind getKind() { result = rk }
|
||||
}
|
||||
|
||||
private module ReturnNodes {
|
||||
private import EscapeContainer
|
||||
|
||||
private predicate isReturnedImpl(CfgNodes::AstCfgNode n, EscapeContainer container) {
|
||||
container = n.getScope() and
|
||||
n = container.getAnEscapingElement()
|
||||
private CfgNodes::NamedBlockCfgNode getAReturnBlock(CfgNodes::ScriptBlockCfgNode sb) {
|
||||
result = sb.getBeginBlock()
|
||||
or
|
||||
result = sb.getEndBlock()
|
||||
or
|
||||
result = sb.getProcessBlock()
|
||||
}
|
||||
|
||||
private module CfgScopeReturn implements PipelineReturns::InputSig {
|
||||
predicate isSource(CfgNodes::AstCfgNode source) { source = getAReturnBlock(_) }
|
||||
}
|
||||
|
||||
private module P = PipelineReturns::Make<CfgScopeReturn>;
|
||||
|
||||
/**
|
||||
* Holds if `n` may be returned, and there are possibly
|
||||
* more than one return value from the function.
|
||||
*/
|
||||
predicate isMultiReturned(CfgNodes::AstCfgNode n) {
|
||||
exists(EscapeContainer container | isReturnedImpl(n, container) |
|
||||
strictcount(container.getAnEscapingElement()) > 1
|
||||
or
|
||||
container.mayBeMultiReturned(n)
|
||||
)
|
||||
predicate blockMayReturnMultipleValues(CfgNodes::ScriptBlockCfgNode scriptBlock) {
|
||||
P::mayReturnMultipleValues(getAReturnBlock(scriptBlock))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` may be returned.
|
||||
*/
|
||||
predicate isReturned(CfgNodes::AstCfgNode n) { isReturnedImpl(n, _) }
|
||||
|
||||
/**
|
||||
* Holds if `n` may be returned, and this is the only value that may be
|
||||
* returned from the function.
|
||||
*/
|
||||
predicate isUniqueReturned(CfgNodes::AstCfgNode n) { isReturned(n) and not isMultiReturned(n) }
|
||||
predicate isReturned(CfgNodes::AstCfgNode n) { n = P::getAReturn(_) }
|
||||
|
||||
class NormalReturnNode extends ReturnNode instanceof ReturnNodeImpl {
|
||||
final override NormalReturnKind getKind() { any() }
|
||||
@@ -851,6 +843,24 @@ predicate jumpStep(Node pred, Node succ) {
|
||||
succ.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
private predicate arrayExprStore(Node node1, ContentSet cs, Node node2, CfgNodes::ExprCfgNode e) {
|
||||
exists(CfgNodes::ExprNodes::ArrayExprCfgNode ae, CfgNodes::StmtNodes::StmtBlockCfgNode block |
|
||||
e = node1.(AstNode).getCfgNode() and
|
||||
ae = node2.asExpr() and
|
||||
block = ae.getStmtBlock()
|
||||
|
|
||||
exists(Content::KnownElementContent ec, int index |
|
||||
e = ArrayExprFlow::getReturn(block, index) and
|
||||
cs.isKnownOrUnknownElement(ec) and
|
||||
index = ec.getIndex().asInt()
|
||||
)
|
||||
or
|
||||
not ArrayExprFlow::eachValueIsReturnedOnce(block) and
|
||||
e = ArrayExprFlow::getAReturn(block) and
|
||||
cs.isAnyElement()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to
|
||||
* content `c`.
|
||||
@@ -877,8 +887,10 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
c.isAnyElement()
|
||||
)
|
||||
or
|
||||
exists(Content::KnownElementContent ec, int index |
|
||||
node2.asExpr().(CfgNodes::ExprNodes::ArrayLiteralCfgNode).getExpr(index) = node1.asExpr() and
|
||||
exists(Content::KnownElementContent ec, int index, CfgNodes::ExprCfgNode e |
|
||||
e = node1.asExpr() and
|
||||
not arrayExprStore(node1, _, _, e) and
|
||||
node2.asExpr().(CfgNodes::ExprNodes::ArrayLiteralCfgNode).getExpr(index) = e and
|
||||
c.isKnownOrUnknownElement(ec) and
|
||||
index = ec.getIndex().asInt()
|
||||
)
|
||||
@@ -895,15 +907,7 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
c.isAnyElement()
|
||||
)
|
||||
or
|
||||
c.isAnyElement() and
|
||||
exists(
|
||||
CfgNodes::ExprNodes::ArrayExprCfgNode arrayExpr, EscapeContainer::EscapeContainer container
|
||||
|
|
||||
node2.asExpr() = arrayExpr and
|
||||
container = arrayExpr.getStmtBlock().getAstNode() and
|
||||
node1.(AstNode).getCfgNode() = container.getAnEscapingElement() and
|
||||
container.mayBeMultiReturned(_)
|
||||
)
|
||||
arrayExprStore(node1, c, node2, _)
|
||||
or
|
||||
c.isAnyElement() and
|
||||
exists(CfgNode cfgNode |
|
||||
@@ -1089,12 +1093,12 @@ private import PostUpdateNodes
|
||||
* (or statement) is being returned from a function.
|
||||
*/
|
||||
private class ImplicitWrapNode extends TImplicitWrapNode, NodeImpl {
|
||||
private CfgNodes::AstCfgNode n;
|
||||
private CfgNodes::ScriptBlockCfgNode n;
|
||||
private boolean shouldWrap;
|
||||
|
||||
ImplicitWrapNode() { this = TImplicitWrapNode(n, shouldWrap) }
|
||||
|
||||
CfgNodes::AstCfgNode getReturnedNode() { result = n }
|
||||
CfgNodes::ScriptBlockCfgNode getScriptBlock() { result = n }
|
||||
|
||||
predicate shouldWrap() { shouldWrap = true }
|
||||
|
||||
@@ -1112,12 +1116,12 @@ private class ImplicitWrapNode extends TImplicitWrapNode, NodeImpl {
|
||||
* has been performed.
|
||||
*/
|
||||
private class PreReturNodeImpl extends TPreReturnNodeImpl, NodeImpl {
|
||||
private CfgNodes::AstCfgNode n;
|
||||
private CfgNodes::ScriptBlockCfgNode n;
|
||||
private boolean isArray;
|
||||
|
||||
PreReturNodeImpl() { this = TPreReturnNodeImpl(n, isArray) }
|
||||
|
||||
CfgNodes::AstCfgNode getReturnedNode() { result = n }
|
||||
CfgNodes::AstCfgNode getScriptBlock() { result = n }
|
||||
|
||||
override CfgScope getCfgScope() { result = n.getScope() }
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
private import semmle.code.powershell.controlflow.CfgNodes
|
||||
|
||||
/**
|
||||
* The input module which defines the set of sources for which to calculate
|
||||
* "escaping expressions".
|
||||
*/
|
||||
signature module InputSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant AST element that we want to compute
|
||||
* which expressions are returned from.
|
||||
*/
|
||||
predicate isSource(AstCfgNode source);
|
||||
}
|
||||
|
||||
/** The output signature from the "escape analysis". */
|
||||
signature module OutputSig<InputSig Input> {
|
||||
/** Gets an expression that escapes from `source` */
|
||||
ExprCfgNode getAReturn(AstCfgNode source);
|
||||
|
||||
/**
|
||||
* Gets the `i`'th expression that escapes from `source`, if an ordering can
|
||||
* be determined statically.
|
||||
*/
|
||||
ExprCfgNode getReturn(AstCfgNode source, int i);
|
||||
|
||||
/** Holds multiple value may escape from `source`. */
|
||||
predicate mayReturnMultipleValues(AstCfgNode source);
|
||||
|
||||
/**
|
||||
* Holds if each value escaping from `source` is guarenteed to only escape
|
||||
* once. In particular, if `count(getAReturn(source)) = 1` and this predicate
|
||||
* holds, then only one value can escape from `source`.
|
||||
*
|
||||
* If `count(getAReturn(source)) > 1` and this predicate holds,
|
||||
* it means that a sequence of values may escape from `source`.
|
||||
*/
|
||||
predicate eachValueIsReturnedOnce(AstCfgNode source);
|
||||
}
|
||||
|
||||
module Make<InputSig Input> implements OutputSig<Input> {
|
||||
private import Input
|
||||
|
||||
private predicate step0(AstCfgNode pred, AstCfgNode succ) {
|
||||
exists(NamedBlockCfgNode nb |
|
||||
pred = nb and
|
||||
succ = nb.getAStmt()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::StmtBlockCfgNode sb |
|
||||
pred = sb and
|
||||
succ = sb.getAStmt()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::ExprStmtCfgNode es |
|
||||
pred = es and
|
||||
succ = es.getExpr()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::ReturnStmtCfgNode es |
|
||||
pred = es and
|
||||
succ = es.getPipeline()
|
||||
)
|
||||
or
|
||||
exists(ExprNodes::ArrayLiteralCfgNode al |
|
||||
pred = al and
|
||||
succ = al.getAnExpr()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::LoopStmtCfgNode loop |
|
||||
pred = loop and
|
||||
succ = loop.getBody()
|
||||
)
|
||||
or
|
||||
exists(ExprNodes::IfCfgNode if_ |
|
||||
pred = if_ and
|
||||
succ = if_.getABranch()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::SwitchStmtCfgNode switch |
|
||||
pred = switch and
|
||||
succ = switch.getACase()
|
||||
)
|
||||
or
|
||||
exists(CatchClauseCfgNode catch |
|
||||
pred = catch and
|
||||
succ = catch.getBody()
|
||||
)
|
||||
or
|
||||
exists(StmtNodes::TryStmtCfgNode try |
|
||||
pred = try and
|
||||
succ = [try.getBody(), try.getFinally()]
|
||||
)
|
||||
}
|
||||
|
||||
private predicate fwd(AstCfgNode n) {
|
||||
isSource(n)
|
||||
or
|
||||
exists(AstCfgNode pred |
|
||||
fwd(pred) and
|
||||
step0(pred, n)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isSink(AstCfgNode sink) {
|
||||
fwd(sink) and
|
||||
(
|
||||
sink instanceof ExprCfgNode and
|
||||
// If is not really an expression
|
||||
not sink instanceof ExprNodes::IfCfgNode and
|
||||
// When `a, b, c` is returned it is flattened to returning a, and b, and c.
|
||||
not sink instanceof ExprNodes::ArrayLiteralCfgNode
|
||||
)
|
||||
}
|
||||
|
||||
private predicate rev(AstCfgNode n) {
|
||||
fwd(n) and
|
||||
(
|
||||
isSink(n)
|
||||
or
|
||||
exists(AstCfgNode succ |
|
||||
rev(succ) and
|
||||
step0(n, succ)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate step(AstCfgNode n1, AstCfgNode n2) {
|
||||
rev(n1) and
|
||||
rev(n2) and
|
||||
step0(n1, n2)
|
||||
}
|
||||
|
||||
private predicate stepPlus(AstCfgNode n1, AstCfgNode n2) =
|
||||
doublyBoundedFastTC(step/2, isSource/1, isSink/1)(n1, n2)
|
||||
|
||||
/** Gets a value that may be returned from `source`. */
|
||||
private ExprCfgNode getAReturn0(AstCfgNode source) {
|
||||
isSource(source) and
|
||||
isSink(result) and
|
||||
stepPlus(source, result)
|
||||
}
|
||||
|
||||
private predicate inScopeOfSource(AstCfgNode n, AstCfgNode source) {
|
||||
isSource(source) and
|
||||
n.getAstNode().getParent*() = source.getAstNode()
|
||||
}
|
||||
|
||||
private predicate getASuccessor(AstCfgNode pred, AstCfgNode succ) {
|
||||
exists(AstCfgNode source |
|
||||
inScopeOfSource(pred, source) and
|
||||
pred.getASuccessor() = succ and
|
||||
inScopeOfSource(succ, source)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `e` may be returned multiple times from `source`. */
|
||||
private predicate mayBeReturnedMoreThanOnce(ExprCfgNode e, AstCfgNode source) {
|
||||
e = getAReturn0(source) and getASuccessor+(e, e)
|
||||
}
|
||||
|
||||
predicate eachValueIsReturnedOnce(AstCfgNode source) {
|
||||
isSource(source) and
|
||||
not mayBeReturnedMoreThanOnce(_, source)
|
||||
}
|
||||
|
||||
private predicate isSourceForSingularReturn(AstCfgNode source) {
|
||||
isSource(source) and
|
||||
eachValueIsReturnedOnce(source)
|
||||
}
|
||||
|
||||
private predicate hasReturnOrderImpl0(int dist, ExprCfgNode e, AstCfgNode source) =
|
||||
shortestDistances(isSourceForSingularReturn/1, getASuccessor/2)(source, e, dist)
|
||||
|
||||
private predicate hasReturnOrderImpl(int dist, ExprCfgNode e) {
|
||||
hasReturnOrderImpl0(dist, e, _) and
|
||||
e = getAReturn0(_)
|
||||
}
|
||||
|
||||
private predicate hasReturnOrder(int i, ExprCfgNode e) {
|
||||
e = rank[i + 1](ExprCfgNode e0, int i0 | hasReturnOrderImpl(i0, e0) | e0 order by i0)
|
||||
}
|
||||
|
||||
ExprCfgNode getReturn(AstCfgNode source, int i) {
|
||||
result = getAReturn0(source) and
|
||||
eachValueIsReturnedOnce(source) and
|
||||
hasReturnOrder(i, result)
|
||||
}
|
||||
|
||||
ExprCfgNode getAReturn(AstCfgNode source) { result = getAReturn0(source) }
|
||||
|
||||
/**
|
||||
* Holds if `source` may return multiple values, and `n` is one of the values.
|
||||
*/
|
||||
predicate mayReturnMultipleValues(AstCfgNode source) {
|
||||
strictcount(getAReturn0(source)) > 1
|
||||
or
|
||||
mayBeReturnedMoreThanOnce(_, source)
|
||||
}
|
||||
}
|
||||
@@ -27,12 +27,6 @@ module SsaInput implements SsaImplCommon::InputSig<Location> {
|
||||
*/
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
(
|
||||
exists(Scope scope | scope = v.(ThisParameter).getDeclaringScope() |
|
||||
// We consider the `this` variable to have a single write at the entry to a method block
|
||||
scope = bb.(BasicBlocks::EntryBasicBlock).getScope() and
|
||||
i = 0
|
||||
)
|
||||
or
|
||||
uninitializedWrite(bb, i, v)
|
||||
or
|
||||
variableWriteActual(bb, i, v, _)
|
||||
@@ -138,9 +132,7 @@ private module Cached {
|
||||
* AST write access is `write`.
|
||||
*/
|
||||
cached
|
||||
predicate variableWriteActual(
|
||||
Cfg::BasicBlock bb, int i, Variable v, VarWriteAccessCfgNode write
|
||||
) {
|
||||
predicate variableWriteActual(Cfg::BasicBlock bb, int i, Variable v, VarWriteAccessCfgNode write) {
|
||||
exists(Cfg::CfgNode n |
|
||||
write.getVariable() = v and
|
||||
n = bb.getNode(i)
|
||||
@@ -277,7 +269,8 @@ private Parameter getANonPipelineParameter(FunctionBase f) {
|
||||
class NormalParameter extends Parameter {
|
||||
NormalParameter() {
|
||||
not this instanceof PipelineParameter and
|
||||
not this instanceof PipelineByPropertyNameParameter
|
||||
not this instanceof PipelineByPropertyNameParameter and
|
||||
not this instanceof ThisParameter
|
||||
}
|
||||
|
||||
int getIndexExcludingPipelines() {
|
||||
@@ -295,18 +288,18 @@ class NormalParameter extends Parameter {
|
||||
|
||||
private newtype TParameterExt =
|
||||
TNormalParameter(NormalParameter p) or
|
||||
TSelfMethodParameter(Method m)
|
||||
TThisMethodParameter(Method m)
|
||||
|
||||
/** A normal parameter or an implicit `self` parameter. */
|
||||
/** A normal parameter or an implicit `this` parameter. */
|
||||
class ParameterExt extends TParameterExt {
|
||||
NormalParameter asParameter() { this = TNormalParameter(result) }
|
||||
|
||||
Method asThis() { this = TSelfMethodParameter(result) }
|
||||
Method asThis() { this = TThisMethodParameter(result) }
|
||||
|
||||
predicate isInitializedBy(WriteDefinition def) {
|
||||
def = getParameterDef(this.asParameter())
|
||||
or
|
||||
def.(Ssa::ThisDefinition).getSourceVariable().getDeclaringScope() = this.asThis().(Scope)
|
||||
def.(Ssa::ThisDefinition).getSourceVariable().getDeclaringScope() = this.asThis().getBody()
|
||||
}
|
||||
|
||||
string toString() { result = [this.asParameter().toString(), this.asThis().toString()] }
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
private import powershell as PS
|
||||
|
||||
/**
|
||||
* TODO: This whole computation cab be sped up by providing a set of "root"s and doing
|
||||
* a forward/backwards traversal first.
|
||||
*/
|
||||
module Private {
|
||||
signature module InterpretAstInputSig {
|
||||
/** The type on which to translate `Ast` elements during escape calculations */
|
||||
class T;
|
||||
|
||||
/** Interpret `a` into a `T` */
|
||||
T interpret(PS::Ast a);
|
||||
}
|
||||
|
||||
module AstEscape<InterpretAstInputSig Interpret> {
|
||||
private import Interpret
|
||||
|
||||
/** An AST element that may produce a value which can escape from this `Ast` when evaluated. */
|
||||
abstract private class ElementImpl instanceof PS::Ast {
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/** Gets a direct node that will may escape when evaluating this element. */
|
||||
T getANode() { none() }
|
||||
|
||||
/** Gets a child that may produce more elements that may escape. */
|
||||
abstract Element getAChild();
|
||||
|
||||
/**
|
||||
* Gets a (possibly transitive) element that may escape when evaluating
|
||||
* this element.
|
||||
*/
|
||||
final T getAnEscapingElement() {
|
||||
result = this.getANode()
|
||||
or
|
||||
result = this.getAChild().getAnEscapingElement()
|
||||
}
|
||||
}
|
||||
|
||||
final class Element = ElementImpl;
|
||||
|
||||
private class ScriptBlockElement extends ElementImpl instanceof PS::ScriptBlock {
|
||||
final override Element getAChild() { result = super.getEndBlock() }
|
||||
}
|
||||
|
||||
private class NamedBlockElement extends ElementImpl instanceof PS::NamedBlock {
|
||||
final override Element getAChild() { result = super.getAStmt() }
|
||||
}
|
||||
|
||||
private class ExprStmtElement extends ElementImpl instanceof PS::ExprStmt {
|
||||
final override T getANode() { result = interpret(super.getExpr()) }
|
||||
|
||||
final override Element getAChild() { none() }
|
||||
}
|
||||
|
||||
private class LoopStmtElement extends ElementImpl instanceof PS::LoopStmt {
|
||||
final override Element getAChild() { result = super.getBody() }
|
||||
}
|
||||
|
||||
private class StmtBlockElement extends ElementImpl instanceof PS::StmtBlock {
|
||||
final override Element getAChild() { result = super.getAStmt() }
|
||||
}
|
||||
|
||||
private class TryStmtElement extends ElementImpl instanceof PS::TryStmt {
|
||||
final override Element getAChild() {
|
||||
result = super.getBody() or result = super.getACatchClause() or result = super.getFinally()
|
||||
}
|
||||
}
|
||||
|
||||
private class ReturnStmtElement extends ElementImpl instanceof PS::ReturnStmt {
|
||||
final override Element getAChild() { result = super.getPipeline() }
|
||||
}
|
||||
|
||||
private class CatchClausElement extends ElementImpl instanceof PS::CatchClause {
|
||||
final override Element getAChild() { result = super.getBody() }
|
||||
}
|
||||
|
||||
private class SwitchStmtElement extends ElementImpl instanceof PS::SwitchStmt {
|
||||
final override Element getAChild() { result = super.getACase() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Public { }
|
||||
@@ -247,7 +247,9 @@
|
||||
| functions.ps1:13:28:20:1 | enter {...} | functions.ps1:13:28:20:1 | {...} | |
|
||||
| functions.ps1:13:28:20:1 | exit {...} (normal) | functions.ps1:13:28:20:1 | exit {...} | |
|
||||
| functions.ps1:13:28:20:1 | name0 | functions.ps1:13:28:20:1 | name1 | |
|
||||
| functions.ps1:13:28:20:1 | name1 | functions.ps1:13:28:20:1 | name2 | |
|
||||
| functions.ps1:13:28:20:1 | name1 | functions.ps1:16:24:16:24 | 0 | |
|
||||
| functions.ps1:13:28:20:1 | name2 | functions.ps1:13:28:20:1 | [synth] pipeline | |
|
||||
| functions.ps1:13:28:20:1 | name2 | functions.ps1:17:24:17:29 | name1 | |
|
||||
| functions.ps1:13:28:20:1 | {...} | functions.ps1:16:24:16:24 | 0 | |
|
||||
| functions.ps1:14:5:19:18 | {...} | functions.ps1:19:5:19:18 | [Stmt] ...+... | |
|
||||
|
||||
@@ -8,6 +8,10 @@ multipleSuccessors
|
||||
| functions.ps1:8:5:8:23 | [Stmt] ...+... | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
|
||||
| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | successor | functions.ps1:8:5:8:12 | number1 |
|
||||
| functions.ps1:8:5:8:23 | [Stmt] __pipeline_iterator | successor | functions.ps1:46:17:46:18 | __pipeline_iterator |
|
||||
| functions.ps1:13:28:20:1 | name1 | successor | functions.ps1:13:28:20:1 | name2 |
|
||||
| functions.ps1:13:28:20:1 | name1 | successor | functions.ps1:16:24:16:24 | 0 |
|
||||
| functions.ps1:13:28:20:1 | name2 | successor | functions.ps1:13:28:20:1 | [synth] pipeline |
|
||||
| functions.ps1:13:28:20:1 | name2 | successor | functions.ps1:17:24:17:29 | name1 |
|
||||
| functions.ps1:16:24:16:24 | 0 | successor | functions.ps1:13:28:20:1 | name2 |
|
||||
| functions.ps1:16:24:16:24 | 0 | successor | functions.ps1:17:24:17:29 | name1 |
|
||||
| functions.ps1:17:24:17:33 | ...+... | successor | functions.ps1:13:28:20:1 | [synth] pipeline |
|
||||
|
||||
@@ -40,11 +40,33 @@ edges
|
||||
| test.ps1:40:6:40:10 | arr8 [element 2] | test.ps1:40:6:40:13 | ...[...] | provenance | |
|
||||
| test.ps1:41:6:41:10 | arr8 [element 2] | test.ps1:41:6:41:20 | ...[...] | provenance | |
|
||||
| test.ps1:43:6:43:16 | Call to Source | test.ps1:45:17:45:18 | y | provenance | |
|
||||
| test.ps1:45:11:45:18 | ...,... [element 2] | test.ps1:48:6:48:10 | arr9 [element 2] | provenance | |
|
||||
| test.ps1:45:11:45:18 | ...,... [element 2] | test.ps1:49:6:49:10 | arr9 [element 2] | provenance | |
|
||||
| test.ps1:45:17:45:18 | y | test.ps1:45:11:45:18 | ...,... [element 2] | provenance | |
|
||||
| test.ps1:45:9:45:19 | @(...) [element 2] | test.ps1:48:6:48:10 | arr9 [element 2] | provenance | |
|
||||
| test.ps1:45:9:45:19 | @(...) [element 2] | test.ps1:49:6:49:10 | arr9 [element 2] | provenance | |
|
||||
| test.ps1:45:17:45:18 | y | test.ps1:45:9:45:19 | @(...) [element 2] | provenance | |
|
||||
| test.ps1:48:6:48:10 | arr9 [element 2] | test.ps1:48:6:48:13 | ...[...] | provenance | |
|
||||
| test.ps1:49:6:49:10 | arr9 [element 2] | test.ps1:49:6:49:20 | ...[...] | provenance | |
|
||||
| test.ps1:54:5:56:5 | this [field] | test.ps1:55:14:55:24 | this [field] | provenance | |
|
||||
| test.ps1:55:14:55:24 | this [field] | test.ps1:55:14:55:24 | field | provenance | |
|
||||
| test.ps1:61:1:61:8 | [post] myClass [field] | test.ps1:63:1:63:8 | myClass [field] | provenance | |
|
||||
| test.ps1:61:18:61:28 | Call to Source | test.ps1:61:1:61:8 | [post] myClass [field] | provenance | |
|
||||
| test.ps1:63:1:63:8 | myClass [field] | test.ps1:54:5:56:5 | this [field] | provenance | |
|
||||
| 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: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 | |
|
||||
| test.ps1:83:6:83:10 | hash [element a] | test.ps1:83:6:83:15 | ...[...] | provenance | |
|
||||
| test.ps1:87:6:87:10 | hash [element a] | test.ps1:87:6:87:15 | ...[...] | provenance | |
|
||||
| test.ps1:88:1:88:5 | [post] hash [b] | test.ps1:89:6:89:10 | hash [b] | provenance | |
|
||||
| test.ps1:88:11:88:21 | Call to Source | test.ps1:88:1:88:5 | [post] hash [b] | provenance | |
|
||||
| test.ps1:89:6:89:10 | hash [b] | test.ps1:89:6:89:12 | b | provenance | |
|
||||
@@ -98,30 +120,43 @@ nodes
|
||||
| test.ps1:41:6:41:10 | arr8 [element 2] | semmle.label | arr8 [element 2] |
|
||||
| test.ps1:41:6:41:20 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:43:6:43:16 | Call to Source | semmle.label | Call to Source |
|
||||
| test.ps1:45:11:45:18 | ...,... [element 2] | semmle.label | ...,... [element 2] |
|
||||
| test.ps1:45:9:45:19 | @(...) [element 2] | semmle.label | @(...) [element 2] |
|
||||
| test.ps1:45:17:45:18 | y | semmle.label | y |
|
||||
| test.ps1:48:6:48:10 | arr9 [element 2] | semmle.label | arr9 [element 2] |
|
||||
| test.ps1:48:6:48:13 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:49:6:49:10 | arr9 [element 2] | semmle.label | arr9 [element 2] |
|
||||
| test.ps1:49:6:49:20 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:54:5:56:5 | this [field] | semmle.label | this [field] |
|
||||
| test.ps1:55:14:55:24 | field | semmle.label | field |
|
||||
| test.ps1:55:14:55:24 | this [field] | semmle.label | this [field] |
|
||||
| test.ps1:61:1:61:8 | [post] myClass [field] | semmle.label | [post] myClass [field] |
|
||||
| test.ps1:61:18:61:28 | Call to Source | semmle.label | Call to Source |
|
||||
| test.ps1:63:1:63:8 | myClass [field] | semmle.label | myClass [field] |
|
||||
| test.ps1:66:10:66:20 | Call to Source | semmle.label | Call to Source |
|
||||
| test.ps1:67:10:67:20 | Call to Source | semmle.label | Call to Source |
|
||||
| test.ps1:68:10:68:20 | Call to Source | semmle.label | Call to Source |
|
||||
| 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:74:6:74:10 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:75:6:75:7 | x [element] | semmle.label | x [element] |
|
||||
| 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: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 |
|
||||
| test.ps1:83:6:83:10 | hash [element a] | semmle.label | hash [element a] |
|
||||
| test.ps1:83:6:83:15 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:87:6:87:10 | hash [element a] | semmle.label | hash [element a] |
|
||||
| test.ps1:87:6:87:15 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:88:1:88:5 | [post] hash [b] | semmle.label | [post] hash [b] |
|
||||
| test.ps1:88:11:88:21 | Call to Source | semmle.label | Call to Source |
|
||||
| test.ps1:89:6:89:10 | hash [b] | semmle.label | hash [b] |
|
||||
| test.ps1:89:6:89:12 | b | semmle.label | b |
|
||||
subpaths
|
||||
testFailures
|
||||
| test.ps1:55:26:55:44 | # $ hasValueFlow=12 | Missing result: hasValueFlow=12 |
|
||||
| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
|
||||
| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
|
||||
| test.ps1:74:12:74:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
|
||||
| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
|
||||
| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
|
||||
| test.ps1:75:12:75:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
|
||||
| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=13 |
|
||||
| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=14 |
|
||||
| test.ps1:76:12:76:62 | # $ hasValueFlow=13 hasValueFlow=14 hasValueFlow=15 | Missing result: hasValueFlow=15 |
|
||||
| test.ps1:83:17:83:35 | # $ hasValueFlow=16 | Missing result: hasValueFlow=16 |
|
||||
| test.ps1:87:17:87:45 | # $ SPURIOUS: hasValueFlow=16 | Fixed spurious result: hasValueFlow=16 |
|
||||
#select
|
||||
| test.ps1:4:6:4:9 | f | test.ps1:3:8:3:17 | Call to Source | test.ps1:4:6:4:9 | f | $@ | test.ps1:3:8:3:17 | Call to Source | Call to Source |
|
||||
| test.ps1:11:6:11:13 | ...[...] | test.ps1:10:12:10:21 | Call to Source | test.ps1:11:6:11:13 | ...[...] | $@ | test.ps1:10:12:10:21 | Call to Source | Call to Source |
|
||||
@@ -136,4 +171,16 @@ testFailures
|
||||
| test.ps1:41:6:41:20 | ...[...] | test.ps1:35:6:35:16 | Call to Source | test.ps1:41:6:41:20 | ...[...] | $@ | test.ps1:35:6:35:16 | Call to Source | Call to Source |
|
||||
| test.ps1:48:6:48:13 | ...[...] | test.ps1:43:6:43:16 | Call to Source | test.ps1:48:6:48:13 | ...[...] | $@ | test.ps1:43:6:43:16 | Call to Source | Call to Source |
|
||||
| test.ps1:49:6:49:20 | ...[...] | test.ps1:43:6:43:16 | Call to Source | test.ps1:49:6:49:20 | ...[...] | $@ | test.ps1:43:6:43:16 | Call to Source | Call to Source |
|
||||
| test.ps1:55:14:55:24 | field | test.ps1:61:18:61:28 | Call to Source | test.ps1:55:14:55:24 | field | $@ | test.ps1:61:18:61:28 | Call to Source | Call to Source |
|
||||
| test.ps1:74:6:74:10 | ...[...] | test.ps1:66:10:66:20 | Call to Source | test.ps1:74:6:74:10 | ...[...] | $@ | test.ps1:66:10:66:20 | Call to Source | Call to Source |
|
||||
| test.ps1:74:6:74:10 | ...[...] | test.ps1:67:10:67:20 | Call to Source | test.ps1:74:6:74:10 | ...[...] | $@ | test.ps1:67:10:67:20 | Call to Source | Call to Source |
|
||||
| test.ps1:74:6:74:10 | ...[...] | test.ps1:68:10:68:20 | Call to Source | test.ps1:74:6:74:10 | ...[...] | $@ | test.ps1:68:10:68:20 | Call to Source | Call to Source |
|
||||
| test.ps1:75:6:75:10 | ...[...] | test.ps1:66:10:66:20 | Call to Source | test.ps1:75:6:75:10 | ...[...] | $@ | test.ps1:66:10:66:20 | Call to Source | Call to Source |
|
||||
| test.ps1:75:6:75:10 | ...[...] | test.ps1:67:10:67:20 | Call to Source | test.ps1:75:6:75:10 | ...[...] | $@ | test.ps1:67:10:67:20 | Call to Source | Call to Source |
|
||||
| test.ps1:75:6:75:10 | ...[...] | test.ps1:68:10:68:20 | Call to Source | test.ps1:75:6:75:10 | ...[...] | $@ | test.ps1:68:10:68:20 | Call to Source | Call to Source |
|
||||
| test.ps1:76:6:76:10 | ...[...] | test.ps1:66:10:66:20 | Call to Source | test.ps1:76:6:76:10 | ...[...] | $@ | test.ps1:66:10:66:20 | Call to Source | Call to Source |
|
||||
| test.ps1:76:6:76:10 | ...[...] | test.ps1:67:10:67:20 | Call to Source | test.ps1:76:6:76:10 | ...[...] | $@ | test.ps1:67:10:67:20 | Call to Source | Call to Source |
|
||||
| test.ps1:76:6:76:10 | ...[...] | test.ps1:68:10:68:20 | Call to Source | test.ps1:76:6:76:10 | ...[...] | $@ | test.ps1:68:10:68:20 | Call to Source | Call to Source |
|
||||
| test.ps1:83:6:83:15 | ...[...] | test.ps1:79:7:79:17 | Call to Source | test.ps1:83:6:83:15 | ...[...] | $@ | test.ps1:79:7:79:17 | Call to Source | Call to Source |
|
||||
| test.ps1:87:6:87:15 | ...[...] | test.ps1:79:7:79:17 | Call to Source | test.ps1:87:6:87:15 | ...[...] | $@ | test.ps1:79:7:79:17 | Call to Source | Call to Source |
|
||||
| test.ps1:89:6:89:12 | b | test.ps1:88:11:88:21 | Call to Source | test.ps1:89:6:89:12 | b | $@ | test.ps1:88:11:88:21 | Call to Source | Call to Source |
|
||||
|
||||
@@ -1,51 +1,37 @@
|
||||
| test.ps1:1:1:1:3 | a1 | test.ps1:2:6:2:8 | a1 |
|
||||
| test.ps1:1:1:21:27 | implicit unwrapping of {...} | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:1:1:21:27 | pre-return value for {...} | test.ps1:1:1:21:27 | implicit unwrapping of {...} |
|
||||
| test.ps1:1:7:1:12 | Call to Source | test.ps1:1:1:1:3 | a1 |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:21:27 | 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 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
|
||||
| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
|
||||
| test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
|
||||
| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
|
||||
| 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: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:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |
|
||||
| test.ps1:10:6:10:15 | [...]... | test.ps1:10:1:10:2 | c |
|
||||
| test.ps1:10:14:10:15 | b | test.ps1:10:6:10:15 | [...]... |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:11:6:11:7 | [post] c | test.ps1:13:7:13:8 | c |
|
||||
| test.ps1:11:6:11:7 | c | test.ps1:13:7:13:8 | c |
|
||||
| test.ps1:13:1:13:2 | d | test.ps1:14:6:14:7 | d |
|
||||
| test.ps1:13:6:13:9 | (...) | test.ps1:13:1:13:2 | d |
|
||||
| test.ps1:13:7:13:8 | c | test.ps1:13:6:13:9 | (...) |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:14:6:14:7 | [post] d | test.ps1:16:6:16:7 | d |
|
||||
| test.ps1:14:6:14:7 | d | test.ps1:16:6:16:7 | d |
|
||||
| test.ps1:16:1:16:2 | e | test.ps1:17:6:17:7 | e |
|
||||
| test.ps1:16:6:16:11 | ...+... | test.ps1:16:1:16:2 | e |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:19:1:19:2 | f | test.ps1:21:25:21:26 | f |
|
||||
| test.ps1:19:6:19:11 | Call to Source | test.ps1:19:1:19:2 | f |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
|
||||
| test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
|
||||
@@ -1,61 +1,41 @@
|
||||
| test.ps1:1:1:1:3 | a1 | test.ps1:2:6:2:8 | a1 |
|
||||
| test.ps1:1:1:21:27 | implicit unwrapping of {...} | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:1:1:21:27 | pre-return value for {...} | test.ps1:1:1:21:27 | implicit unwrapping of {...} |
|
||||
| test.ps1:1:1:21:27 | pre-return value for {...} | test.ps1:1:1:21:27 | implicit unwrapping of {...} |
|
||||
| test.ps1:1:7:1:12 | Call to Source | test.ps1:1:1:1:3 | a1 |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:2:1:2:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:2:1:2:8 | pre-return value for Call to Sink | test.ps1:2:1:2:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:2:1:2:8 | Call to Sink | test.ps1:1:1:21:27 | 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 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
|
||||
| test.ps1:5:1:7:1 | if (...) {...} | test.ps1:5:1:7:1 | pre-return value for if (...) {...} |
|
||||
| test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:5:1:7:1 | phi | test.ps1:8:6:8:8 | a2 |
|
||||
| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
|
||||
| test.ps1:5:1:7:1 | pre-return value for if (...) {...} | test.ps1:5:1:7:1 | implicit unwrapping of if (...) {...} |
|
||||
| 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: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:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:8:1:8:8 | pre-return value for Call to Sink |
|
||||
| test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:8:1:8:8 | pre-return value for Call to Sink | test.ps1:8:1:8:8 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:8:1:8:8 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:10:1:10:2 | c | test.ps1:11:6:11:7 | c |
|
||||
| test.ps1:10:6:10:15 | [...]... | test.ps1:10:1:10:2 | c |
|
||||
| test.ps1:10:14:10:15 | b | test.ps1:10:6:10:15 | [...]... |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:11:1:11:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:11:1:11:7 | pre-return value for Call to Sink | test.ps1:11:1:11:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:11:1:11:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:11:6:11:7 | [post] c | test.ps1:13:7:13:8 | c |
|
||||
| test.ps1:11:6:11:7 | c | test.ps1:13:7:13:8 | c |
|
||||
| test.ps1:13:1:13:2 | d | test.ps1:14:6:14:7 | d |
|
||||
| test.ps1:13:6:13:9 | (...) | test.ps1:13:1:13:2 | d |
|
||||
| test.ps1:13:7:13:8 | c | test.ps1:13:6:13:9 | (...) |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:14:1:14:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:14:1:14:7 | pre-return value for Call to Sink | test.ps1:14:1:14:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:14:1:14:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:14:6:14:7 | [post] d | test.ps1:16:6:16:7 | d |
|
||||
| test.ps1:14:6:14:7 | d | test.ps1:16:6:16:7 | d |
|
||||
| test.ps1:16:1:16:2 | e | test.ps1:17:6:17:7 | e |
|
||||
| test.ps1:16:6:16:7 | d | test.ps1:16:6:16:11 | ...+... |
|
||||
| test.ps1:16:6:16:11 | ...+... | test.ps1:16:1:16:2 | e |
|
||||
| test.ps1:16:11:16:11 | 1 | test.ps1:16:6:16:11 | ...+... |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:17:1:17:7 | pre-return value for Call to Sink |
|
||||
| test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:17:1:17:7 | pre-return value for Call to Sink | test.ps1:17:1:17:7 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:17:1:17:7 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:19:1:19:2 | f | test.ps1:21:25:21:26 | f |
|
||||
| test.ps1:19:6:19:11 | Call to Source | test.ps1:19:1:19:2 | f |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:21:1:21:27 | pre-return value for Call to Sink |
|
||||
| test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink | test.ps1:1:1:21:27 | return value for {...} |
|
||||
| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:21:1:21:27 | pre-return value for Call to Sink | test.ps1:21:1:21:27 | implicit unwrapping of Call to Sink |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:21:1:21:27 | Call to Sink | test.ps1:1:1:21:27 | pre-return value for {...} |
|
||||
| test.ps1:21:25:21:26 | f | test.ps1:21:6:21:27 | here is a string: $f |
|
||||
|
||||
@@ -8,6 +8,16 @@ edges
|
||||
| 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: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: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 | |
|
||||
@@ -24,6 +34,18 @@ nodes
|
||||
| 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: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 |
|
||||
| test.ps1:23:6:23:7 | x | semmle.label | x |
|
||||
| test.ps1:26:10:26:19 | Call to Source | semmle.label | Call to Source |
|
||||
| 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:33:6:33:10 | ...[...] | semmle.label | ...[...] |
|
||||
| test.ps1:34:6:34:7 | x [element] | semmle.label | x [element] |
|
||||
| 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] |
|
||||
@@ -32,16 +54,16 @@ nodes
|
||||
| test.ps1:44:6:44:10 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
testFailures
|
||||
| test.ps1:23:9:23:26 | # $ hasValueFlow=4 | Missing result: hasValueFlow=4 |
|
||||
| test.ps1:33:12:33:54 | # $ hasValueFlow=5 SPURIOUS: hasValueFlow=6 | Fixed spurious result: hasValueFlow=6 |
|
||||
| test.ps1:33:12:33:54 | # $ hasValueFlow=5 SPURIOUS: hasValueFlow=6 | Missing result: hasValueFlow=5 |
|
||||
| test.ps1:34:12:34:54 | # $ hasValueFlow=6 SPURIOUS: hasValueFlow=5 | Fixed spurious result: hasValueFlow=5 |
|
||||
| test.ps1:34:12:34:54 | # $ hasValueFlow=6 SPURIOUS: hasValueFlow=5 | Missing result: hasValueFlow=6 |
|
||||
#select
|
||||
| test.ps1:6:6:6:7 | x | test.ps1:2:5:2:14 | Call to Source | test.ps1:6:6:6:7 | x | $@ | test.ps1:2:5:2:14 | Call to Source | Call to Source |
|
||||
| test.ps1:15:6:15:10 | ...[...] | test.ps1:9:5:9:14 | Call to Source | test.ps1:15:6:15:10 | ...[...] | $@ | test.ps1:9:5:9:14 | Call to Source | Call to Source |
|
||||
| test.ps1:15:6:15:10 | ...[...] | test.ps1:10:5:10:14 | Call to Source | test.ps1:15:6:15:10 | ...[...] | $@ | test.ps1:10:5:10:14 | Call to Source | Call to Source |
|
||||
| test.ps1:16:6:16:10 | ...[...] | test.ps1:9:5:9:14 | Call to Source | test.ps1:16:6:16:10 | ...[...] | $@ | test.ps1:9:5:9:14 | Call to Source | Call to Source |
|
||||
| test.ps1:16:6:16:10 | ...[...] | test.ps1:10:5:10:14 | Call to Source | test.ps1:16:6:16:10 | ...[...] | $@ | test.ps1:10:5:10:14 | Call to Source | Call to Source |
|
||||
| test.ps1:23:6:23:7 | x | test.ps1:19:12:19:21 | Call to Source | test.ps1:23:6:23:7 | x | $@ | test.ps1:19:12:19:21 | Call to Source | Call to Source |
|
||||
| test.ps1:33:6:33:10 | ...[...] | test.ps1:26:10:26:19 | Call to Source | test.ps1:33:6:33:10 | ...[...] | $@ | test.ps1:26:10:26:19 | Call to Source | Call to Source |
|
||||
| test.ps1:33:6:33:10 | ...[...] | test.ps1:28:10:28:19 | Call to Source | test.ps1:33:6:33:10 | ...[...] | $@ | test.ps1:28:10:28:19 | Call to Source | Call to Source |
|
||||
| test.ps1:34:6:34:10 | ...[...] | test.ps1:26:10:26:19 | Call to Source | test.ps1:34:6:34:10 | ...[...] | $@ | test.ps1:26:10:26:19 | Call to Source | Call to Source |
|
||||
| test.ps1:34:6:34:10 | ...[...] | test.ps1:28:10:28:19 | Call to Source | test.ps1:34:6:34:10 | ...[...] | $@ | test.ps1:28:10:28:19 | Call to Source | Call to Source |
|
||||
| test.ps1:43:6:43:10 | ...[...] | test.ps1:38:9:38:18 | Call to Source | test.ps1:43:6:43:10 | ...[...] | $@ | test.ps1:38:9:38:18 | Call to Source | Call to Source |
|
||||
| test.ps1:44:6:44:10 | ...[...] | test.ps1:38:9:38:18 | Call to Source | test.ps1:44:6:44:10 | ...[...] | $@ | test.ps1:38:9:38:18 | Call to Source | Call to Source |
|
||||
|
||||
Reference in New Issue
Block a user