C#: Adopt shared SSA data-flow integration

This commit is contained in:
Tom Hvitved
2024-07-03 10:41:40 +02:00
parent fbcb4498fe
commit 89a2381165
11 changed files with 1718 additions and 937 deletions

View File

@@ -29,7 +29,7 @@ module BaseSsa {
) { ) {
exists(ControlFlow::ControlFlow::BasicBlocks::EntryBlock entry | exists(ControlFlow::ControlFlow::BasicBlocks::EntryBlock entry |
c = entry.getCallable() and c = entry.getCallable() and
// In case `c` has multiple bodies, we want each body to gets its own implicit // In case `c` has multiple bodies, we want each body to get its own implicit
// entry definition. In case `c` doesn't have multiple bodies, the line below // entry definition. In case `c` doesn't have multiple bodies, the line below
// is simply the same as `bb = entry`, because `entry.getFirstNode().getASuccessor()` // is simply the same as `bb = entry`, because `entry.getFirstNode().getASuccessor()`
// will be in the entry block. // will be in the entry block.

View File

@@ -267,8 +267,9 @@ module VariableCapture {
private predicate closureFlowStep(ControlFlow::Nodes::ExprNode e1, ControlFlow::Nodes::ExprNode e2) { private predicate closureFlowStep(ControlFlow::Nodes::ExprNode e1, ControlFlow::Nodes::ExprNode e2) {
e1 = LocalFlow::getALastEvalNode(e2) e1 = LocalFlow::getALastEvalNode(e2)
or or
exists(Ssa::Definition def | exists(Ssa::Definition def, AssignableDefinition adef |
LocalFlow::ssaDefAssigns(def.getAnUltimateDefinition(), e1) and LocalFlow::defAssigns(adef, _, e1) and
def.getAnUltimateDefinition().(Ssa::ExplicitDefinition).getADefinition() = adef and
exists(def.getAReadAtNode(e2)) exists(def.getAReadAtNode(e2))
) )
} }
@@ -492,6 +493,30 @@ module VariableCapture {
} }
} }
/** Provides logic related to SSA. */
module SsaFlow {
private module Impl = SsaImpl::DataFlowIntegration;
Impl::Node asNode(Node n) {
n = TSsaNode(result)
or
result.(Impl::ExprNode).getExpr() = n.(ExprNode).getControlFlowNode()
or
result.(Impl::ExprPostUpdateNode).getExpr() =
n.(PostUpdateNode).getPreUpdateNode().(ExprNode).getControlFlowNode()
or
result.(Impl::ParameterNode).getParameter() = n.(ExplicitParameterNode).getSsaDefinition()
}
predicate localFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
Impl::localFlowStep(def, asNode(nodeFrom), asNode(nodeTo), isUseStep)
}
predicate localMustFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
Impl::localMustFlowStep(def, asNode(nodeFrom), asNode(nodeTo))
}
}
/** Provides predicates related to local data flow. */ /** Provides predicates related to local data flow. */
module LocalFlow { module LocalFlow {
class LocalExprStepConfiguration extends ControlFlowReachabilityConfiguration { class LocalExprStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -617,105 +642,6 @@ module LocalFlow {
any(LocalExprStepConfiguration x).hasDefPath(_, value, def, cfnDef) any(LocalExprStepConfiguration x).hasDefPath(_, value, def, cfnDef)
} }
predicate ssaDefAssigns(Ssa::ExplicitDefinition ssaDef, ControlFlow::Nodes::ExprNode value) {
exists(AssignableDefinition def, ControlFlow::Node cfnDef |
any(LocalExprStepConfiguration conf).hasDefPath(_, value, def, cfnDef) and
ssaDef.getADefinition() = def and
ssaDef.getControlFlowNode() = cfnDef
)
}
/**
* An uncertain SSA definition. Either an uncertain explicit definition or an
* uncertain qualifier definition.
*
* Restricts `Ssa::UncertainDefinition` by excluding implicit call definitions,
* as we---conservatively---consider such definitions to be certain.
*/
class UncertainExplicitSsaDefinition extends Ssa::UncertainDefinition {
UncertainExplicitSsaDefinition() {
this instanceof Ssa::ExplicitDefinition
or
this =
any(Ssa::ImplicitQualifierDefinition qdef |
qdef.getQualifierDefinition() instanceof UncertainExplicitSsaDefinition
)
}
}
/** An SSA definition into which another SSA definition may flow. */
private class SsaInputDefinitionExtNode extends SsaDefinitionExtNode {
SsaInputDefinitionExtNode() {
def instanceof Ssa::PhiNode
or
def instanceof SsaImpl::PhiReadNode
or
def instanceof LocalFlow::UncertainExplicitSsaDefinition
}
}
/**
* Holds if `nodeFrom` is a last node referencing SSA definition `def`, which
* can reach `next`.
*/
private predicate localFlowSsaInputFromDef(
Node nodeFrom, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
) {
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
def.definesAt(_, bb, i, _) and
def = getSsaDefinitionExt(nodeFrom) and
nodeFrom != next
)
}
/**
* Holds if `read` is a last node reading SSA definition `def`, which
* can reach `next`.
*/
predicate localFlowSsaInputFromRead(
Node read, SsaImpl::DefinitionExt def, SsaInputDefinitionExtNode next
) {
exists(ControlFlow::BasicBlock bb, int i |
SsaImpl::lastRefBeforeRedefExt(def, bb, i, next.getDefinitionExt()) and
read.asExprAtNode(bb.getNode(i)) instanceof AssignableRead
)
}
private SsaImpl::DefinitionExt getSsaDefinitionExt(Node n) {
result = n.(SsaDefinitionExtNode).getDefinitionExt()
or
result = n.(ExplicitParameterNode).getSsaDefinition()
}
/**
* Holds if there is a local use-use flow step from `nodeFrom` to `nodeTo`
* involving SSA definition `def`.
*/
predicate localSsaFlowStepUseUse(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
exists(ControlFlow::Node cfnFrom, ControlFlow::Node cfnTo |
SsaImpl::adjacentReadPairSameVarExt(def, cfnFrom, cfnTo) and
nodeTo = TExprNode(cfnTo) and
nodeFrom = TExprNode(cfnFrom)
)
}
/**
* Holds if there is a local flow step from `nodeFrom` to `nodeTo` involving
* SSA definition `def`.
*/
predicate localSsaFlowStep(SsaImpl::DefinitionExt def, Node nodeFrom, Node nodeTo) {
// Flow from SSA definition/parameter to first read
def = getSsaDefinitionExt(nodeFrom) and
SsaImpl::firstReadSameVarExt(def, nodeTo.(ExprNode).getControlFlowNode())
or
// Flow from read to next read
localSsaFlowStepUseUse(def, nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
or
// Flow into phi (read)/uncertain SSA definition node from def
localFlowSsaInputFromDef(nodeFrom, def, nodeTo)
}
/** /**
* Holds if the source variable of SSA definition `def` is an instance field. * Holds if the source variable of SSA definition `def` is an instance field.
*/ */
@@ -800,10 +726,7 @@ module LocalFlow {
node2.asExpr() instanceof AssignExpr node2.asExpr() instanceof AssignExpr
) )
or or
exists(SsaImpl::Definition def | SsaFlow::localMustFlowStep(_, node1, node2)
def = getSsaDefinitionExt(node1) and
exists(SsaImpl::getAReadAtNode(def, node2.(ExprNode).getControlFlowNode()))
)
or or
node2 = node1.(LocalFunctionCreationNode).getAnAccess(true) node2 = node1.(LocalFunctionCreationNode).getAnAccess(true)
or or
@@ -827,23 +750,14 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
( (
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo) LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or or
exists(SsaImpl::DefinitionExt def | exists(SsaImpl::DefinitionExt def, boolean isUseStep |
SsaFlow::localFlowStep(def, nodeFrom, nodeTo, isUseStep) and
not LocalFlow::usesInstanceField(def) and not LocalFlow::usesInstanceField(def) and
not def instanceof VariableCapture::CapturedSsaDefinitionExt not def instanceof VariableCapture::CapturedSsaDefinitionExt
| |
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) isUseStep = false
or or
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _) and
nodeFrom != nodeTo
or
// Flow into phi (read)/uncertain SSA definition node from read
exists(Node read | LocalFlow::localFlowSsaInputFromRead(read, def, nodeTo) |
nodeFrom = read and
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
or
nodeFrom.(PostUpdateNode).getPreUpdateNode() = read
)
) )
or or
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode) nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
@@ -1113,11 +1027,7 @@ private module Cached {
cached cached
newtype TNode = newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof Expr } or TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getAstNode() instanceof Expr } or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) { TSsaNode(SsaImpl::DataFlowIntegration::SsaNode node) or
// Handled by `TExplicitParameterNode` below
not def instanceof Ssa::ImplicitParameterDefinition and
def.getBasicBlock() = any(DataFlowCallable c).getAControlFlowNode().getBasicBlock()
} or
TAssignableDefinitionNode(AssignableDefinition def, ControlFlow::Node cfn) { TAssignableDefinitionNode(AssignableDefinition def, ControlFlow::Node cfn) {
cfn = def.getExpr().getAControlFlowNode() cfn = def.getExpr().getAControlFlowNode()
} or } or
@@ -1180,17 +1090,7 @@ private module Cached {
predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) { predicate localFlowStepImpl(Node nodeFrom, Node nodeTo) {
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo) LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
or or
LocalFlow::localSsaFlowStepUseUse(_, nodeFrom, nodeTo) and SsaFlow::localFlowStep(_, nodeFrom, nodeTo, _)
nodeFrom != nodeTo
or
LocalFlow::localSsaFlowStep(_, nodeFrom, nodeTo)
or
// Flow into phi (read)/uncertain SSA definition node from read
exists(Node read | LocalFlow::localFlowSsaInputFromRead(read, _, nodeTo) |
nodeFrom = read
or
nodeFrom.(PostUpdateNode).getPreUpdateNode() = read
)
or or
// Simple flow through library code is included in the exposed local // Simple flow through library code is included in the exposed local
// step relation, even though flow is technically inter-procedural // step relation, even though flow is technically inter-procedural
@@ -1254,7 +1154,7 @@ import Cached
/** Holds if `n` should be hidden from path explanations. */ /** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { predicate nodeIsHidden(Node n) {
n instanceof SsaDefinitionExtNode n instanceof SsaNode
or or
exists(Parameter p | p = n.(ParameterNode).getParameter() | not p.fromSource()) exists(Parameter p | p = n.(ParameterNode).getParameter() | not p.fromSource())
or or
@@ -1288,13 +1188,16 @@ predicate nodeIsHidden(Node n) {
n instanceof CaptureNode n instanceof CaptureNode
} }
/** An SSA definition, viewed as a node in a data flow graph. */ /** An SSA node. */
class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode { abstract class SsaNode extends NodeImpl, TSsaNode {
SsaImpl::DataFlowIntegration::SsaNode node;
SsaImpl::DefinitionExt def; SsaImpl::DefinitionExt def;
SsaDefinitionExtNode() { this = TSsaDefinitionExtNode(def) } SsaNode() {
this = TSsaNode(node) and
def = node.getDefinitionExt()
}
/** Gets the underlying SSA definition. */
SsaImpl::DefinitionExt getDefinitionExt() { result = def } SsaImpl::DefinitionExt getDefinitionExt() { result = def }
override DataFlowCallable getEnclosingCallableImpl() { override DataFlowCallable getEnclosingCallableImpl() {
@@ -1307,9 +1210,57 @@ class SsaDefinitionExtNode extends NodeImpl, TSsaDefinitionExtNode {
result = def.(Ssa::Definition).getControlFlowNode() result = def.(Ssa::Definition).getControlFlowNode()
} }
override Location getLocationImpl() { result = def.getLocation() } override Location getLocationImpl() { result = node.getLocation() }
override string toStringImpl() { result = def.toString() } override string toStringImpl() { result = node.toString() }
}
/** An (extended) SSA definition, viewed as a node in a data flow graph. */
class SsaDefinitionExtNode extends SsaNode {
override SsaImpl::DataFlowIntegration::SsaDefinitionExtNode node;
}
/**
* A node that represents an input to an SSA phi (read) definition.
*
* This allows for barrier guards to filter input to phi nodes. For example, in
*
* ```csharp
* var x = taint;
* if (x != "safe")
* {
* x = "safe";
* }
* sink(x);
* ```
*
* the `false` edge out of `x != "safe"` guards the input from `x = taint` into the
* `phi` node after the condition.
*
* It is also relevant to filter input into phi read nodes:
*
* ```csharp
* var x = taint;
* if (b)
* {
* if (x != "safe1")
* {
* return;
* }
* } else {
* if (x != "safe2")
* {
* return;
* }
* }
*
* sink(x);
* ```
*
* both inputs into the phi read node after the outer condition are guarded.
*/
class SsaInputNode extends SsaNode {
override SsaImpl::DataFlowIntegration::SsaInputNode node;
} }
/** A definition, viewed as a node in a data flow graph. */ /** A definition, viewed as a node in a data flow graph. */
@@ -2907,7 +2858,7 @@ private predicate delegateCreationStep(Node nodeFrom, Node nodeTo) {
/** Extra data-flow steps needed for lambda flow analysis. */ /** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) {
exists(SsaImpl::DefinitionExt def | exists(SsaImpl::DefinitionExt def |
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo) and SsaFlow::localFlowStep(def, nodeFrom, nodeTo, _) and
preservesValue = true preservesValue = true
| |
LocalFlow::usesInstanceField(def) LocalFlow::usesInstanceField(def)

View File

@@ -171,8 +171,14 @@ signature predicate guardChecksSig(Guard g, Expr e, AbstractValue v);
* in data flow and taint tracking. * in data flow and taint tracking.
*/ */
module BarrierGuard<guardChecksSig/3 guardChecks> { module BarrierGuard<guardChecksSig/3 guardChecks> {
private import SsaImpl as SsaImpl
/** Gets a node that is safely guarded by the given guard check. */ /** Gets a node that is safely guarded by the given guard check. */
ExprNode getABarrierNode() { pragma[nomagic]
Node getABarrierNode() {
SsaFlow::asNode(result) =
SsaImpl::DataFlowIntegration::BarrierGuard<guardChecks/3>::getABarrierNode()
or
exists(Guard g, Expr e, AbstractValue v | exists(Guard g, Expr e, AbstractValue v |
guardChecks(g, e, v) and guardChecks(g, e, v) and
g.controlsNode(result.getControlFlowNode(), e, v) g.controlsNode(result.getControlFlowNode(), e, v)

View File

@@ -6,6 +6,7 @@ import csharp
private import codeql.ssa.Ssa as SsaImplCommon private import codeql.ssa.Ssa as SsaImplCommon
private import AssignableDefinitions private import AssignableDefinitions
private import semmle.code.csharp.controlflow.internal.PreSsa private import semmle.code.csharp.controlflow.internal.PreSsa
private import semmle.code.csharp.controlflow.Guards as Guards
private module SsaInput implements SsaImplCommon::InputSig<Location> { private module SsaInput implements SsaImplCommon::InputSig<Location> {
class BasicBlock = ControlFlow::BasicBlock; class BasicBlock = ControlFlow::BasicBlock;
@@ -49,7 +50,7 @@ private module SsaInput implements SsaImplCommon::InputSig<Location> {
} }
} }
private import SsaImplCommon::Make<Location, SsaInput> as Impl import SsaImplCommon::Make<Location, SsaInput> as Impl
class Definition = Impl::Definition; class Definition = Impl::Definition;
@@ -757,24 +758,6 @@ private predicate adjacentDefReachesRead(
) )
} }
private predicate adjacentDefReachesReadExt(
DefinitionExt def, SsaInput::SourceVariable v, SsaInput::BasicBlock bb1, int i1,
SsaInput::BasicBlock bb2, int i2
) {
Impl::adjacentDefReadExt(def, v, bb1, i1, bb2, i2) and
(
def.definesAt(v, bb1, i1, _)
or
SsaInput::variableRead(bb1, i1, v, true)
)
or
exists(SsaInput::BasicBlock bb3, int i3 |
adjacentDefReachesReadExt(def, v, bb1, i1, bb3, i3) and
SsaInput::variableRead(bb3, i3, v, false) and
Impl::adjacentDefReadExt(def, v, bb3, i3, bb2, i2)
)
}
/** Same as `adjacentDefRead`, but skips uncertain reads. */ /** Same as `adjacentDefRead`, but skips uncertain reads. */
pragma[nomagic] pragma[nomagic]
private predicate adjacentDefSkipUncertainReads( private predicate adjacentDefSkipUncertainReads(
@@ -786,17 +769,6 @@ private predicate adjacentDefSkipUncertainReads(
) )
} }
/** Same as `adjacentDefReadExt`, but skips uncertain reads. */
pragma[nomagic]
private predicate adjacentDefSkipUncertainReadsExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
exists(SsaInput::SourceVariable v |
adjacentDefReachesReadExt(def, v, bb1, i1, bb2, i2) and
SsaInput::variableRead(bb2, i2, v, true)
)
}
private predicate adjacentDefReachesUncertainRead( private predicate adjacentDefReachesUncertainRead(
Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2 Definition def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) { ) {
@@ -806,16 +778,6 @@ private predicate adjacentDefReachesUncertainRead(
) )
} }
pragma[nomagic]
private predicate adjacentDefReachesUncertainReadExt(
DefinitionExt def, SsaInput::BasicBlock bb1, int i1, SsaInput::BasicBlock bb2, int i2
) {
exists(SsaInput::SourceVariable v |
adjacentDefReachesReadExt(def, v, bb1, i1, bb2, i2) and
SsaInput::variableRead(bb2, i2, v, false)
)
}
/** Same as `lastRefRedef`, but skips uncertain reads. */ /** Same as `lastRefRedef`, but skips uncertain reads. */
pragma[nomagic] pragma[nomagic]
private predicate lastRefSkipUncertainReads(Definition def, SsaInput::BasicBlock bb, int i) { private predicate lastRefSkipUncertainReads(Definition def, SsaInput::BasicBlock bb, int i) {
@@ -870,7 +832,7 @@ private module Cached {
predicate implicitEntryDefinition(ControlFlow::ControlFlow::BasicBlock bb, Ssa::SourceVariable v) { predicate implicitEntryDefinition(ControlFlow::ControlFlow::BasicBlock bb, Ssa::SourceVariable v) {
exists(ControlFlow::ControlFlow::BasicBlocks::EntryBlock entry, Callable c | exists(ControlFlow::ControlFlow::BasicBlocks::EntryBlock entry, Callable c |
c = entry.getCallable() and c = entry.getCallable() and
// In case `c` has multiple bodies, we want each body to gets its own implicit // In case `c` has multiple bodies, we want each body to get its own implicit
// entry definition. In case `c` doesn't have multiple bodies, the line below // entry definition. In case `c` doesn't have multiple bodies, the line below
// is simply the same as `bb = entry`, because `entry.getFirstNode().getASuccessor()` // is simply the same as `bb = entry`, because `entry.getFirstNode().getASuccessor()`
// will be in the entry block. // will be in the entry block.
@@ -965,19 +927,6 @@ private module Cached {
) )
} }
/**
* Holds if the value defined at SSA definition `def` can reach a read at `cfn`,
* without passing through any other read.
*/
cached
predicate firstReadSameVarExt(DefinitionExt def, ControlFlow::Node cfn) {
exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 |
def.definesAt(_, bb1, i1, _) and
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
cfn = bb2.getNode(i2)
)
}
/** /**
* Holds if the read at `cfn2` is a read of the same SSA definition `def` * Holds if the read at `cfn2` is a read of the same SSA definition `def`
* as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without * as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without
@@ -993,23 +942,6 @@ private module Cached {
) )
} }
/**
* Holds if the read at `cfn2` is a read of the same SSA definition `def`
* as the read at `cfn1`, and `cfn2` can be reached from `cfn1` without
* passing through another read.
*/
cached
predicate adjacentReadPairSameVarExt(
DefinitionExt def, ControlFlow::Node cfn1, ControlFlow::Node cfn2
) {
exists(ControlFlow::BasicBlock bb1, int i1, ControlFlow::BasicBlock bb2, int i2 |
cfn1 = bb1.getNode(i1) and
variableReadActual(bb1, i1, _) and
adjacentDefSkipUncertainReadsExt(def, bb1, i1, bb2, i2) and
cfn2 = bb2.getNode(i2)
)
}
cached cached
predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) { predicate lastRefBeforeRedef(Definition def, ControlFlow::BasicBlock bb, int i, Definition next) {
Impl::lastRefRedef(def, bb, i, next) and Impl::lastRefRedef(def, bb, i, next) and
@@ -1021,21 +953,6 @@ private module Cached {
) )
} }
cached
predicate lastRefBeforeRedefExt(
DefinitionExt def, ControlFlow::BasicBlock bb, int i, DefinitionExt next
) {
exists(SsaInput::SourceVariable v |
Impl::lastRefRedefExt(def, v, bb, i, next) and
not SsaInput::variableRead(bb, i, v, false)
)
or
exists(SsaInput::BasicBlock bb0, int i0 |
Impl::lastRefRedefExt(def, _, bb0, i0, next) and
adjacentDefReachesUncertainReadExt(def, bb, i, bb0, i0)
)
}
cached cached
predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) { predicate lastReadSameVar(Definition def, ControlFlow::Node cfn) {
exists(ControlFlow::BasicBlock bb, int i | exists(ControlFlow::BasicBlock bb, int i |
@@ -1061,6 +978,41 @@ private module Cached {
outRefExitRead(bb, i, v) outRefExitRead(bb, i, v)
) )
} }
cached
module DataFlowIntegration {
import DataFlowIntegrationImpl
cached
predicate localFlowStep(DefinitionExt def, Node nodeFrom, Node nodeTo, boolean isUseStep) {
DataFlowIntegrationImpl::localFlowStep(def, nodeFrom, nodeTo, isUseStep)
}
cached
predicate localMustFlowStep(DefinitionExt def, Node nodeFrom, Node nodeTo) {
DataFlowIntegrationImpl::localMustFlowStep(def, nodeFrom, nodeTo)
}
signature predicate guardChecksSig(Guards::Guard g, Expr e, Guards::AbstractValue v);
cached // nothing is actually cached
module BarrierGuard<guardChecksSig/3 guardChecks> {
private predicate guardChecksAdjTypes(
DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, boolean branch
) {
exists(Guards::AbstractValues::BooleanValue v |
guardChecks(g, e.getAstNode(), v) and
branch = v.getValue()
)
}
private Node getABarrierNodeImpl() {
result = DataFlowIntegrationImpl::BarrierGuard<guardChecksAdjTypes/3>::getABarrierNode()
}
predicate getABarrierNode = getABarrierNodeImpl/0;
}
}
} }
import Cached import Cached
@@ -1118,3 +1070,64 @@ class PhiReadNode extends DefinitionExt, Impl::PhiReadNode {
result = this.getSourceVariable().getEnclosingCallable() result = this.getSourceVariable().getEnclosingCallable()
} }
} }
private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInputSig {
private import csharp as Cs
private import semmle.code.csharp.controlflow.BasicBlocks
class Expr extends ControlFlow::Node {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) { this = bb.getNode(i) }
}
Expr getARead(Definition def) { exists(getAReadAtNode(def, result)) }
predicate ssaDefAssigns(WriteDefinition def, Expr value) {
// exclude flow directly from RHS to SSA definition, as we instead want to
// go from RHS to matching assingnable definition, and from there to SSA definition
none()
}
class Parameter = Ssa::ImplicitParameterDefinition;
predicate ssaDefInitializesParam(WriteDefinition def, Parameter p) { def = p }
/**
* Allows for flow into uncertain defintions that are not call definitions,
* as we, conservatively, consider such definitions to be certain.
*/
predicate allowFlowIntoUncertainDef(UncertainWriteDefinition def) {
def instanceof Ssa::ExplicitDefinition
or
def =
any(Ssa::ImplicitQualifierDefinition qdef |
allowFlowIntoUncertainDef(qdef.getQualifierDefinition())
)
}
class Guard extends Guards::Guard {
predicate hasCfgNode(ControlFlow::BasicBlock bb, int i) {
this.getAControlFlowNode() = bb.getNode(i)
}
}
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardControlsBlock(Guard guard, ControlFlow::BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, ControlFlow::SuccessorTypes::ConditionalSuccessor s |
guard.getAControlFlowNode() = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)
)
}
/** Gets an immediate conditional successor of basic block `bb`, if any. */
ControlFlow::BasicBlock getAConditionalBasicBlockSuccessor(
ControlFlow::BasicBlock bb, boolean branch
) {
exists(ControlFlow::SuccessorTypes::ConditionalSuccessor s |
result = bb.getASuccessorByType(s) and
s.getValue() = branch
)
}
}
private module DataFlowIntegrationImpl = Impl::DataFlowIntegration<DataFlowIntegrationInput>;

View File

@@ -12,18 +12,21 @@
| CSharp7.cs:15:9:15:11 | SSA entry def(this.field) | CSharp7.cs:15:18:15:22 | access to field field | | CSharp7.cs:15:9:15:11 | SSA entry def(this.field) | CSharp7.cs:15:18:15:22 | access to field field |
| CSharp7.cs:15:9:15:11 | this | CSharp7.cs:15:18:15:22 | this access | | CSharp7.cs:15:9:15:11 | this | CSharp7.cs:15:18:15:22 | this access |
| CSharp7.cs:19:9:19:11 | this | CSharp7.cs:19:16:19:20 | this access | | CSharp7.cs:19:9:19:11 | this | CSharp7.cs:19:16:19:20 | this access |
| CSharp7.cs:20:9:20:11 | SSA param(value) | CSharp7.cs:20:24:20:28 | access to parameter value |
| CSharp7.cs:20:9:20:11 | this | CSharp7.cs:20:16:20:20 | this access | | CSharp7.cs:20:9:20:11 | this | CSharp7.cs:20:16:20:20 | this access |
| CSharp7.cs:20:9:20:11 | value | CSharp7.cs:20:24:20:28 | access to parameter value | | CSharp7.cs:20:9:20:11 | value | CSharp7.cs:20:9:20:11 | SSA param(value) |
| CSharp7.cs:20:24:20:28 | access to parameter value | CSharp7.cs:20:16:20:20 | access to field field | | CSharp7.cs:20:24:20:28 | access to parameter value | CSharp7.cs:20:16:20:20 | access to field field |
| CSharp7.cs:23:5:23:27 | this | CSharp7.cs:14:9:14:13 | this access | | CSharp7.cs:23:5:23:27 | this | CSharp7.cs:14:9:14:13 | this access |
| CSharp7.cs:24:6:24:28 | this | CSharp7.cs:24:35:24:39 | this access | | CSharp7.cs:24:6:24:28 | this | CSharp7.cs:24:35:24:39 | this access |
| CSharp7.cs:29:19:29:19 | i | CSharp7.cs:31:16:31:16 | access to parameter i | | CSharp7.cs:29:19:29:19 | SSA param(i) | CSharp7.cs:31:16:31:16 | access to parameter i |
| CSharp7.cs:29:19:29:19 | i | CSharp7.cs:29:19:29:19 | SSA param(i) |
| CSharp7.cs:31:16:31:16 | access to parameter i | CSharp7.cs:31:16:31:20 | ... > ... | | CSharp7.cs:31:16:31:16 | access to parameter i | CSharp7.cs:31:16:31:20 | ... > ... |
| CSharp7.cs:31:16:31:16 | access to parameter i | CSharp7.cs:31:24:31:24 | access to parameter i | | CSharp7.cs:31:16:31:16 | access to parameter i | CSharp7.cs:31:24:31:24 | access to parameter i |
| CSharp7.cs:31:24:31:24 | access to parameter i | CSharp7.cs:31:16:31:59 | ... ? ... : ... | | CSharp7.cs:31:24:31:24 | access to parameter i | CSharp7.cs:31:16:31:59 | ... ? ... : ... |
| CSharp7.cs:39:9:39:9 | access to parameter x | CSharp7.cs:39:9:39:21 | SSA def(x) | | CSharp7.cs:39:9:39:9 | access to parameter x | CSharp7.cs:39:9:39:21 | SSA def(x) |
| CSharp7.cs:39:13:39:21 | "tainted" | CSharp7.cs:39:9:39:9 | access to parameter x | | CSharp7.cs:39:13:39:21 | "tainted" | CSharp7.cs:39:9:39:9 | access to parameter x |
| CSharp7.cs:42:19:42:19 | x | CSharp7.cs:44:13:44:13 | access to parameter x | | CSharp7.cs:42:19:42:19 | SSA param(x) | CSharp7.cs:44:13:44:13 | access to parameter x |
| CSharp7.cs:42:19:42:19 | x | CSharp7.cs:42:19:42:19 | SSA param(x) |
| CSharp7.cs:44:9:44:9 | access to parameter y | CSharp7.cs:44:9:44:13 | SSA def(y) | | CSharp7.cs:44:9:44:9 | access to parameter y | CSharp7.cs:44:9:44:13 | SSA def(y) |
| CSharp7.cs:44:13:44:13 | access to parameter x | CSharp7.cs:44:9:44:9 | access to parameter y | | CSharp7.cs:44:13:44:13 | access to parameter x | CSharp7.cs:44:9:44:9 | access to parameter y |
| CSharp7.cs:47:10:47:10 | this | CSharp7.cs:49:9:49:24 | this access | | CSharp7.cs:47:10:47:10 | this | CSharp7.cs:49:9:49:24 | this access |
@@ -86,7 +89,8 @@
| CSharp7.cs:77:22:77:28 | (..., ...) | CSharp7.cs:77:9:77:18 | (..., ...) | | CSharp7.cs:77:22:77:28 | (..., ...) | CSharp7.cs:77:9:77:18 | (..., ...) |
| CSharp7.cs:77:23:77:24 | "" | CSharp7.cs:77:9:77:28 | ... = ... | | CSharp7.cs:77:23:77:24 | "" | CSharp7.cs:77:9:77:28 | ... = ... |
| CSharp7.cs:77:27:77:27 | access to local variable x | CSharp7.cs:77:9:77:28 | ... = ... | | CSharp7.cs:77:27:77:27 | access to local variable x | CSharp7.cs:77:9:77:28 | ... = ... |
| CSharp7.cs:80:21:80:21 | x | CSharp7.cs:82:20:82:20 | access to parameter x | | CSharp7.cs:80:21:80:21 | SSA param(x) | CSharp7.cs:82:20:82:20 | access to parameter x |
| CSharp7.cs:80:21:80:21 | x | CSharp7.cs:80:21:80:21 | SSA param(x) |
| CSharp7.cs:85:10:85:18 | this | CSharp7.cs:90:18:90:28 | this access | | CSharp7.cs:85:10:85:18 | this | CSharp7.cs:90:18:90:28 | this access |
| CSharp7.cs:87:13:87:14 | access to local variable t1 | CSharp7.cs:87:13:87:34 | SSA def(t1) | | CSharp7.cs:87:13:87:14 | access to local variable t1 | CSharp7.cs:87:13:87:34 | SSA def(t1) |
| CSharp7.cs:87:13:87:34 | SSA def(t1) | CSharp7.cs:88:28:88:29 | access to local variable t1 | | CSharp7.cs:87:13:87:34 | SSA def(t1) | CSharp7.cs:88:28:88:29 | access to local variable t1 |
@@ -133,40 +137,51 @@
| CSharp7.cs:121:28:121:36 | "DefUse3" | CSharp7.cs:121:22:121:24 | access to local variable m12 | | CSharp7.cs:121:28:121:36 | "DefUse3" | CSharp7.cs:121:22:121:24 | access to local variable m12 |
| CSharp7.cs:121:28:121:36 | "DefUse3" | CSharp7.cs:121:22:121:36 | ... = ... | | CSharp7.cs:121:28:121:36 | "DefUse3" | CSharp7.cs:121:22:121:36 | ... = ... |
| CSharp7.cs:127:9:127:12 | this | CSharp7.cs:133:24:133:25 | this access | | CSharp7.cs:127:9:127:12 | this | CSharp7.cs:133:24:133:25 | this access |
| CSharp7.cs:129:20:129:20 | x | CSharp7.cs:129:32:129:32 | access to parameter x | | CSharp7.cs:129:20:129:20 | SSA param(x) | CSharp7.cs:129:32:129:32 | access to parameter x |
| CSharp7.cs:129:20:129:20 | x | CSharp7.cs:129:20:129:20 | SSA param(x) |
| CSharp7.cs:129:32:129:32 | access to parameter x | CSharp7.cs:129:32:129:36 | ... + ... | | CSharp7.cs:129:32:129:32 | access to parameter x | CSharp7.cs:129:32:129:36 | ... + ... |
| CSharp7.cs:129:36:129:36 | 1 | CSharp7.cs:129:32:129:36 | ... + ... | | CSharp7.cs:129:36:129:36 | 1 | CSharp7.cs:129:32:129:36 | ... + ... |
| CSharp7.cs:131:22:131:22 | t | CSharp7.cs:131:39:131:39 | access to parameter t | | CSharp7.cs:131:22:131:22 | SSA param(t) | CSharp7.cs:131:39:131:39 | access to parameter t |
| CSharp7.cs:131:22:131:22 | t | CSharp7.cs:131:22:131:22 | SSA param(t) |
| CSharp7.cs:133:24:133:25 | delegate creation of type Func<Int32> | CSharp7.cs:133:19:133:20 | access to local variable f4 | | CSharp7.cs:133:24:133:25 | delegate creation of type Func<Int32> | CSharp7.cs:133:19:133:20 | access to local variable f4 |
| CSharp7.cs:133:24:133:25 | this access | CSharp7.cs:154:16:154:17 | this access | | CSharp7.cs:133:24:133:25 | this access | CSharp7.cs:154:16:154:17 | this access |
| CSharp7.cs:137:29:137:29 | x | CSharp7.cs:137:34:137:34 | access to parameter x | | CSharp7.cs:137:29:137:29 | SSA param(x) | CSharp7.cs:137:34:137:34 | access to parameter x |
| CSharp7.cs:137:29:137:29 | x | CSharp7.cs:137:29:137:29 | SSA param(x) |
| CSharp7.cs:137:29:137:38 | (...) => ... | CSharp7.cs:137:24:137:25 | access to local variable f5 | | CSharp7.cs:137:29:137:38 | (...) => ... | CSharp7.cs:137:24:137:25 | access to local variable f5 |
| CSharp7.cs:137:34:137:34 | access to parameter x | CSharp7.cs:137:34:137:38 | ... + ... | | CSharp7.cs:137:34:137:34 | access to parameter x | CSharp7.cs:137:34:137:38 | ... + ... |
| CSharp7.cs:137:38:137:38 | 1 | CSharp7.cs:137:34:137:38 | ... + ... | | CSharp7.cs:137:38:137:38 | 1 | CSharp7.cs:137:34:137:38 | ... + ... |
| CSharp7.cs:139:20:139:20 | x | CSharp7.cs:139:26:139:26 | access to parameter x | | CSharp7.cs:139:20:139:20 | SSA param(x) | CSharp7.cs:139:26:139:26 | access to parameter x |
| CSharp7.cs:139:20:139:20 | x | CSharp7.cs:139:20:139:20 | SSA param(x) |
| CSharp7.cs:139:26:139:26 | access to parameter x | CSharp7.cs:139:26:139:30 | ... > ... | | CSharp7.cs:139:26:139:26 | access to parameter x | CSharp7.cs:139:26:139:30 | ... > ... |
| CSharp7.cs:139:26:139:26 | access to parameter x | CSharp7.cs:139:41:139:41 | access to parameter x | | CSharp7.cs:139:26:139:26 | access to parameter x | CSharp7.cs:139:41:139:41 | access to parameter x |
| CSharp7.cs:139:34:139:34 | 1 | CSharp7.cs:139:34:139:46 | ... + ... | | CSharp7.cs:139:34:139:34 | 1 | CSharp7.cs:139:34:139:46 | ... + ... |
| CSharp7.cs:139:34:139:46 | ... + ... | CSharp7.cs:139:26:139:50 | ... ? ... : ... | | CSharp7.cs:139:34:139:46 | ... + ... | CSharp7.cs:139:26:139:50 | ... ? ... : ... |
| CSharp7.cs:139:38:139:46 | call to local function f7 | CSharp7.cs:139:34:139:46 | ... + ... | | CSharp7.cs:139:38:139:46 | call to local function f7 | CSharp7.cs:139:34:139:46 | ... + ... |
| CSharp7.cs:139:50:139:50 | 0 | CSharp7.cs:139:26:139:50 | ... ? ... : ... | | CSharp7.cs:139:50:139:50 | 0 | CSharp7.cs:139:26:139:50 | ... ? ... : ... |
| CSharp7.cs:141:20:141:20 | x | CSharp7.cs:141:29:141:29 | access to parameter x | | CSharp7.cs:141:20:141:20 | SSA param(x) | CSharp7.cs:141:29:141:29 | access to parameter x |
| CSharp7.cs:145:24:145:24 | x | CSharp7.cs:145:33:145:33 | access to parameter x | | CSharp7.cs:141:20:141:20 | x | CSharp7.cs:141:20:141:20 | SSA param(x) |
| CSharp7.cs:145:24:145:24 | SSA param(x) | CSharp7.cs:145:33:145:33 | access to parameter x |
| CSharp7.cs:145:24:145:24 | x | CSharp7.cs:145:24:145:24 | SSA param(x) |
| CSharp7.cs:149:20:152:9 | (...) => ... | CSharp7.cs:149:16:149:16 | access to local variable a | | CSharp7.cs:149:20:152:9 | (...) => ... | CSharp7.cs:149:16:149:16 | access to local variable a |
| CSharp7.cs:157:10:157:17 | this | CSharp7.cs:169:9:169:9 | this access | | CSharp7.cs:157:10:157:17 | this | CSharp7.cs:169:9:169:9 | this access |
| CSharp7.cs:160:18:160:18 | t | CSharp7.cs:160:24:160:24 | access to parameter t | | CSharp7.cs:160:18:160:18 | SSA param(t) | CSharp7.cs:160:24:160:24 | access to parameter t |
| CSharp7.cs:162:26:162:26 | u | CSharp7.cs:166:22:166:22 | access to parameter u | | CSharp7.cs:160:18:160:18 | t | CSharp7.cs:160:18:160:18 | SSA param(t) |
| CSharp7.cs:162:26:162:26 | SSA param(u) | CSharp7.cs:166:22:166:22 | access to parameter u |
| CSharp7.cs:162:26:162:26 | u | CSharp7.cs:162:26:162:26 | SSA param(u) |
| CSharp7.cs:165:13:165:16 | this access | CSharp7.cs:166:20:166:20 | this access | | CSharp7.cs:165:13:165:16 | this access | CSharp7.cs:166:20:166:20 | this access |
| CSharp7.cs:169:9:169:9 | this access | CSharp7.cs:170:9:170:9 | this access | | CSharp7.cs:169:9:169:9 | this access | CSharp7.cs:170:9:170:9 | this access |
| CSharp7.cs:173:10:173:19 | this | CSharp7.cs:180:21:180:21 | this access | | CSharp7.cs:173:10:173:19 | this | CSharp7.cs:180:21:180:21 | this access |
| CSharp7.cs:175:16:175:18 | access to local variable src | CSharp7.cs:175:16:175:30 | SSA def(src) | | CSharp7.cs:175:16:175:18 | access to local variable src | CSharp7.cs:175:16:175:30 | SSA def(src) |
| CSharp7.cs:175:16:175:30 | SSA def(src) | CSharp7.cs:180:23:180:25 | access to local variable src | | CSharp7.cs:175:16:175:30 | SSA def(src) | CSharp7.cs:180:23:180:25 | access to local variable src |
| CSharp7.cs:175:22:175:30 | "tainted" | CSharp7.cs:175:16:175:18 | access to local variable src | | CSharp7.cs:175:22:175:30 | "tainted" | CSharp7.cs:175:16:175:18 | access to local variable src |
| CSharp7.cs:176:25:176:25 | s | CSharp7.cs:176:33:176:33 | access to parameter s | | CSharp7.cs:176:25:176:25 | SSA param(s) | CSharp7.cs:176:33:176:33 | access to parameter s |
| CSharp7.cs:176:25:176:25 | s | CSharp7.cs:176:25:176:25 | SSA param(s) |
| CSharp7.cs:176:31:176:34 | call to local function g | CSharp7.cs:176:31:176:39 | ... + ... | | CSharp7.cs:176:31:176:34 | call to local function g | CSharp7.cs:176:31:176:39 | ... + ... |
| CSharp7.cs:176:38:176:39 | "" | CSharp7.cs:176:31:176:39 | ... + ... | | CSharp7.cs:176:38:176:39 | "" | CSharp7.cs:176:31:176:39 | ... + ... |
| CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:31:177:31 | access to parameter s | | CSharp7.cs:177:25:177:25 | SSA param(s) | CSharp7.cs:177:31:177:31 | access to parameter s |
| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:37:178:37 | access to parameter s | | CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:25:177:25 | SSA param(s) |
| CSharp7.cs:178:25:178:25 | SSA param(s) | CSharp7.cs:178:37:178:37 | access to parameter s |
| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:25:178:25 | SSA param(s) |
| CSharp7.cs:180:21:180:21 | this access | CSharp7.cs:181:21:181:21 | this access | | CSharp7.cs:180:21:180:21 | this access | CSharp7.cs:181:21:181:21 | this access |
| CSharp7.cs:180:21:180:26 | call to local function f | CSharp7.cs:180:13:180:17 | access to local variable sink1 | | CSharp7.cs:180:21:180:26 | call to local function f | CSharp7.cs:180:13:180:17 | access to local variable sink1 |
| CSharp7.cs:180:23:180:25 | [post] access to local variable src | CSharp7.cs:181:23:181:25 | access to local variable src | | CSharp7.cs:180:23:180:25 | [post] access to local variable src | CSharp7.cs:181:23:181:25 | access to local variable src |
@@ -205,8 +220,10 @@
| CSharp7.cs:198:26:198:35 | this access | CSharp7.cs:199:9:199:18 | this access | | CSharp7.cs:198:26:198:35 | this access | CSharp7.cs:199:9:199:18 | this access |
| CSharp7.cs:198:33:198:34 | access to local variable r1 | CSharp7.cs:199:16:199:17 | access to local variable r1 | | CSharp7.cs:198:33:198:34 | access to local variable r1 | CSharp7.cs:199:16:199:17 | access to local variable r1 |
| CSharp7.cs:199:22:199:22 | 3 | CSharp7.cs:199:9:199:22 | ... = ... | | CSharp7.cs:199:22:199:22 | 3 | CSharp7.cs:199:9:199:22 | ... = ... |
| CSharp7.cs:202:24:202:24 | p | CSharp7.cs:205:20:205:20 | access to parameter p | | CSharp7.cs:202:24:202:24 | SSA param(p) | CSharp7.cs:205:20:205:20 | access to parameter p |
| CSharp7.cs:204:28:204:28 | q | CSharp7.cs:204:44:204:44 | access to parameter q | | CSharp7.cs:202:24:202:24 | p | CSharp7.cs:202:24:202:24 | SSA param(p) |
| CSharp7.cs:204:28:204:28 | SSA param(q) | CSharp7.cs:204:44:204:44 | access to parameter q |
| CSharp7.cs:204:28:204:28 | q | CSharp7.cs:204:28:204:28 | SSA param(q) |
| CSharp7.cs:215:9:215:9 | access to parameter x | CSharp7.cs:215:9:215:17 | SSA def(x) | | CSharp7.cs:215:9:215:9 | access to parameter x | CSharp7.cs:215:9:215:17 | SSA def(x) |
| CSharp7.cs:215:13:215:17 | false | CSharp7.cs:215:9:215:9 | access to parameter x | | CSharp7.cs:215:13:215:17 | false | CSharp7.cs:215:9:215:9 | access to parameter x |
| CSharp7.cs:219:10:219:13 | this | CSharp7.cs:221:13:221:20 | this access | | CSharp7.cs:219:10:219:13 | this | CSharp7.cs:221:13:221:20 | this access |
@@ -224,8 +241,8 @@
| CSharp7.cs:232:16:232:23 | SSA def(o) | CSharp7.cs:233:13:233:13 | access to local variable o | | CSharp7.cs:232:16:232:23 | SSA def(o) | CSharp7.cs:233:13:233:13 | access to local variable o |
| CSharp7.cs:232:20:232:23 | null | CSharp7.cs:232:16:232:16 | access to local variable o | | CSharp7.cs:232:20:232:23 | null | CSharp7.cs:232:16:232:16 | access to local variable o |
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:233:18:233:23 | Int32 i1 | | CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:233:18:233:23 | Int32 i1 |
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:235:13:235:42 | [input] SSA phi read(o) |
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:237:18:237:18 | access to local variable o | | CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:237:18:237:18 | access to local variable o |
| CSharp7.cs:233:13:233:13 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:233:13:233:23 | [false] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... | | CSharp7.cs:233:13:233:23 | [false] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... |
| CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... | | CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [false] ... && ... |
| CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [true] ... && ... | | CSharp7.cs:233:13:233:23 | [true] ... is ... | CSharp7.cs:233:13:233:33 | [true] ... && ... |
@@ -235,19 +252,25 @@
| CSharp7.cs:233:28:233:29 | access to local variable i1 | CSharp7.cs:235:38:235:39 | access to local variable i1 | | CSharp7.cs:233:28:233:29 | access to local variable i1 | CSharp7.cs:235:38:235:39 | access to local variable i1 |
| CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [false] ... && ... | | CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [false] ... && ... |
| CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [true] ... && ... | | CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [true] ... && ... |
| CSharp7.cs:235:13:235:42 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:235:33:235:36 | "int " | CSharp7.cs:235:31:235:41 | $"..." | | CSharp7.cs:235:33:235:36 | "int " | CSharp7.cs:235:31:235:41 | $"..." |
| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." | | CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | String s1 | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | String s1 |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o |
| CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:237:23:237:31 | SSA def(s1) | CSharp7.cs:239:41:239:42 | access to local variable s1 | | CSharp7.cs:237:23:237:31 | SSA def(s1) | CSharp7.cs:239:41:239:42 | access to local variable s1 |
| CSharp7.cs:237:23:237:31 | String s1 | CSharp7.cs:237:23:237:31 | SSA def(s1) | | CSharp7.cs:237:23:237:31 | String s1 | CSharp7.cs:237:23:237:31 | SSA def(s1) |
| CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:239:33:239:39 | "string " | CSharp7.cs:239:31:239:44 | $"..." | | CSharp7.cs:239:33:239:39 | "string " | CSharp7.cs:239:31:239:44 | $"..." |
| CSharp7.cs:239:41:239:42 | access to local variable s1 | CSharp7.cs:239:31:239:44 | $"..." | | CSharp7.cs:239:41:239:42 | access to local variable s1 | CSharp7.cs:239:31:239:44 | $"..." |
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:242:9:243:9 | [input] SSA phi read(o) |
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:244:18:244:18 | access to local variable o | | CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:244:18:244:18 | access to local variable o |
| CSharp7.cs:241:18:241:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) | | CSharp7.cs:242:9:243:9 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:244:18:244:28 | [input] SSA phi read(o) |
| CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:244:23:244:28 | Object v1 | | CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:244:23:244:28 | Object v1 |
| CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:248:9:274:9 | SSA phi read(o) | | CSharp7.cs:244:18:244:18 | access to local variable o | CSharp7.cs:245:9:246:9 | [input] SSA phi read(o) |
| CSharp7.cs:244:18:244:28 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:245:9:246:9 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) |
| CSharp7.cs:248:9:274:9 | SSA phi read(o) | CSharp7.cs:248:17:248:17 | access to local variable o | | CSharp7.cs:248:9:274:9 | SSA phi read(o) | CSharp7.cs:248:17:248:17 | access to local variable o |
| CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:254:27:254:27 | access to local variable o | | CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:254:27:254:27 | access to local variable o |
| CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:257:18:257:23 | Int32 i2 | | CSharp7.cs:248:17:248:17 | access to local variable o | CSharp7.cs:257:18:257:23 | Int32 i2 |
@@ -281,14 +304,16 @@
| CSharp7.cs:283:13:283:16 | access to local variable list | CSharp7.cs:283:13:283:62 | SSA def(list) | | CSharp7.cs:283:13:283:16 | access to local variable list | CSharp7.cs:283:13:283:62 | SSA def(list) |
| CSharp7.cs:283:13:283:62 | SSA def(list) | CSharp7.cs:285:39:285:42 | access to local variable list | | CSharp7.cs:283:13:283:62 | SSA def(list) | CSharp7.cs:285:39:285:42 | access to local variable list |
| CSharp7.cs:283:20:283:62 | call to method Select<KeyValuePair<Int32,String>,(Int32,String)> | CSharp7.cs:283:13:283:16 | access to local variable list | | CSharp7.cs:283:20:283:62 | call to method Select<KeyValuePair<Int32,String>,(Int32,String)> | CSharp7.cs:283:13:283:16 | access to local variable list |
| CSharp7.cs:283:32:283:35 | item | CSharp7.cs:283:41:283:44 | access to parameter item | | CSharp7.cs:283:32:283:35 | SSA param(item) | CSharp7.cs:283:41:283:44 | access to parameter item |
| CSharp7.cs:283:32:283:35 | item | CSharp7.cs:283:32:283:35 | SSA param(item) |
| CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:41:283:48 | access to property Key | | CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:41:283:48 | access to property Key |
| CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item | | CSharp7.cs:283:41:283:44 | access to parameter item | CSharp7.cs:283:51:283:54 | access to parameter item |
| CSharp7.cs:283:51:283:54 | access to parameter item | CSharp7.cs:283:51:283:60 | access to property Value | | CSharp7.cs:283:51:283:54 | access to parameter item | CSharp7.cs:283:51:283:60 | access to property Value |
| CSharp7.cs:285:39:285:42 | access to local variable list | CSharp7.cs:287:36:287:39 | access to local variable list | | CSharp7.cs:285:39:285:42 | access to local variable list | CSharp7.cs:287:36:287:39 | access to local variable list |
| CSharp7.cs:287:36:287:39 | access to local variable list | CSharp7.cs:289:32:289:35 | access to local variable list | | CSharp7.cs:287:36:287:39 | access to local variable list | CSharp7.cs:289:32:289:35 | access to local variable list |
| CSharp7.cs:297:18:297:18 | access to local variable x | CSharp7.cs:297:18:297:22 | SSA def(x) | | CSharp7.cs:297:18:297:18 | access to local variable x | CSharp7.cs:297:18:297:22 | SSA def(x) |
| CSharp7.cs:297:18:297:22 | SSA def(x) | CSharp7.cs:297:25:297:25 | SSA phi(x) | | CSharp7.cs:297:18:297:22 | SSA def(x) | CSharp7.cs:297:18:297:22 | [input] SSA phi(x) |
| CSharp7.cs:297:18:297:22 | [input] SSA phi(x) | CSharp7.cs:297:25:297:25 | SSA phi(x) |
| CSharp7.cs:297:22:297:22 | 0 | CSharp7.cs:297:18:297:18 | access to local variable x | | CSharp7.cs:297:22:297:22 | 0 | CSharp7.cs:297:18:297:18 | access to local variable x |
| CSharp7.cs:297:25:297:25 | SSA phi(x) | CSharp7.cs:297:25:297:25 | access to local variable x | | CSharp7.cs:297:25:297:25 | SSA phi(x) | CSharp7.cs:297:25:297:25 | access to local variable x |
| CSharp7.cs:297:25:297:25 | access to local variable x | CSharp7.cs:297:25:297:30 | ... < ... | | CSharp7.cs:297:25:297:25 | access to local variable x | CSharp7.cs:297:25:297:30 | ... < ... |
@@ -301,5 +326,6 @@
| CSharp7.cs:297:35:297:44 | [true] ... is ... | CSharp7.cs:297:25:297:44 | [true] ... && ... | | CSharp7.cs:297:35:297:44 | [true] ... is ... | CSharp7.cs:297:25:297:44 | [true] ... && ... |
| CSharp7.cs:297:40:297:44 | Int32 y | CSharp7.cs:297:40:297:44 | SSA def(y) | | CSharp7.cs:297:40:297:44 | Int32 y | CSharp7.cs:297:40:297:44 | SSA def(y) |
| CSharp7.cs:297:40:297:44 | SSA def(y) | CSharp7.cs:299:31:299:31 | access to local variable y | | CSharp7.cs:297:40:297:44 | SSA def(y) | CSharp7.cs:299:31:299:31 | access to local variable y |
| CSharp7.cs:297:47:297:49 | SSA def(x) | CSharp7.cs:297:25:297:25 | SSA phi(x) | | CSharp7.cs:297:47:297:49 | SSA def(x) | CSharp7.cs:297:47:297:49 | [input] SSA phi(x) |
| CSharp7.cs:297:47:297:49 | [input] SSA phi(x) | CSharp7.cs:297:25:297:25 | SSA phi(x) |
| CSharp7.cs:297:49:297:49 | access to local variable x | CSharp7.cs:297:47:297:49 | SSA def(x) | | CSharp7.cs:297:49:297:49 | access to local variable x | CSharp7.cs:297:47:297:49 | SSA def(x) |

View File

@@ -0,0 +1,83 @@
class BarrierFlow
{
static object Source(object source) => throw null;
public static void Sink(object o) { }
void M1()
{
var x = Source(1);
Sink(x); // $ hasValueFlow=1
}
void M2()
{
var x = Source(2);
if (x != "safe")
{
Sink(x); // $ hasValueFlow=2
}
}
void M3()
{
var x = Source(3);
if (x == "safe")
{
Sink(x);
}
}
void M4()
{
var x = Source(4);
if (x != "safe")
{
x = "safe";
}
Sink(x);
}
void M5()
{
var x = Source(5);
if (x == "safe")
{
}
else
{
x = "safe";
}
Sink(x);
}
void M6(bool b)
{
var x = Source(6);
if (b)
{
if (x != "safe1")
{
return;
}
}
else
{
if (x != "safe2")
{
return;
}
}
Sink(x);
}
}

View File

@@ -0,0 +1,18 @@
models
edges
| BarrierFlow.cs:10:13:10:13 | access to local variable x : Object | BarrierFlow.cs:12:14:12:14 | access to local variable x | provenance | |
| BarrierFlow.cs:10:17:10:25 | call to method Source : Object | BarrierFlow.cs:10:13:10:13 | access to local variable x : Object | provenance | |
| BarrierFlow.cs:17:13:17:13 | access to local variable x : Object | BarrierFlow.cs:21:18:21:18 | access to local variable x | provenance | |
| BarrierFlow.cs:17:17:17:25 | call to method Source : Object | BarrierFlow.cs:17:13:17:13 | access to local variable x : Object | provenance | |
nodes
| BarrierFlow.cs:10:13:10:13 | access to local variable x : Object | semmle.label | access to local variable x : Object |
| BarrierFlow.cs:10:17:10:25 | call to method Source : Object | semmle.label | call to method Source : Object |
| BarrierFlow.cs:12:14:12:14 | access to local variable x | semmle.label | access to local variable x |
| BarrierFlow.cs:17:13:17:13 | access to local variable x : Object | semmle.label | access to local variable x : Object |
| BarrierFlow.cs:17:17:17:25 | call to method Source : Object | semmle.label | call to method Source : Object |
| BarrierFlow.cs:21:18:21:18 | access to local variable x | semmle.label | access to local variable x |
subpaths
testFailures
#select
| BarrierFlow.cs:12:14:12:14 | access to local variable x | BarrierFlow.cs:10:17:10:25 | call to method Source : Object | BarrierFlow.cs:12:14:12:14 | access to local variable x | $@ | BarrierFlow.cs:10:17:10:25 | call to method Source : Object | call to method Source : Object |
| BarrierFlow.cs:21:18:21:18 | access to local variable x | BarrierFlow.cs:17:17:17:25 | call to method Source : Object | BarrierFlow.cs:21:18:21:18 | access to local variable x | $@ | BarrierFlow.cs:17:17:17:25 | call to method Source : Object | call to method Source : Object |

View File

@@ -0,0 +1,35 @@
/**
* @kind path-problem
*/
import csharp
import semmle.code.csharp.controlflow.Guards
private predicate stringConstCompare(Guard guard, Expr testedNode, AbstractValue value) {
guard
.isEquality(any(StringLiteral lit), testedNode,
value.(AbstractValues::BooleanValue).getValue())
}
class StringConstCompareBarrier extends DataFlow::Node {
StringConstCompareBarrier() {
this = DataFlow::BarrierGuard<stringConstCompare/3>::getABarrierNode()
}
}
import TestUtilities.InlineFlowTest
import PathGraph
module FlowConfig implements DataFlow::ConfigSig {
predicate isSource = DefaultFlowConfig::isSource/1;
predicate isSink = DefaultFlowConfig::isSink/1;
predicate isBarrier(DataFlow::Node n) { n instanceof StringConstCompareBarrier }
}
import ValueFlowTest<FlowConfig>
from PathNode source, PathNode sink
where flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -92,7 +92,8 @@
| Tuples.cs:51:14:51:14 | [post] access to local variable y | Tuples.cs:52:14:52:14 | access to local variable y | | Tuples.cs:51:14:51:14 | [post] access to local variable y | Tuples.cs:52:14:52:14 | access to local variable y |
| Tuples.cs:51:14:51:14 | access to local variable y | Tuples.cs:52:14:52:14 | access to local variable y | | Tuples.cs:51:14:51:14 | access to local variable y | Tuples.cs:52:14:52:14 | access to local variable y |
| Tuples.cs:52:14:52:20 | access to field Item2 | Tuples.cs:52:14:52:20 | (...) ... | | Tuples.cs:52:14:52:20 | access to field Item2 | Tuples.cs:52:14:52:20 | (...) ... |
| Tuples.cs:55:27:55:27 | s | Tuples.cs:75:18:75:18 | access to parameter s | | Tuples.cs:55:27:55:27 | SSA param(s) | Tuples.cs:75:18:75:18 | access to parameter s |
| Tuples.cs:55:27:55:27 | s | Tuples.cs:55:27:55:27 | SSA param(s) |
| Tuples.cs:57:13:57:14 | access to local variable o1 | Tuples.cs:57:13:57:34 | SSA def(o1) | | Tuples.cs:57:13:57:14 | access to local variable o1 | Tuples.cs:57:13:57:34 | SSA def(o1) |
| Tuples.cs:57:13:57:34 | SSA def(o1) | Tuples.cs:59:18:59:19 | access to local variable o1 | | Tuples.cs:57:13:57:34 | SSA def(o1) | Tuples.cs:59:18:59:19 | access to local variable o1 |
| Tuples.cs:57:18:57:34 | call to method Source<String> | Tuples.cs:57:13:57:14 | access to local variable o1 | | Tuples.cs:57:18:57:34 | call to method Source<String> | Tuples.cs:57:13:57:14 | access to local variable o1 |