Merge branch 'rc/1.20' into merge-rc

This commit is contained in:
Tom Hvitved
2019-03-12 09:14:38 +01:00
127 changed files with 2817 additions and 664 deletions

View File

@@ -17,7 +17,7 @@ import semmle.code.csharp.commons.StructuralComparison
class DoubleCheckedLock extends StructuralComparisonConfiguration {
DoubleCheckedLock() { this = "double checked lock" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(IfStmt unlockedIf, IfStmt lockedIf, LockStmt lock |
x = unlockedIf.getCondition() and
y = lockedIf.getCondition() and

View File

@@ -15,7 +15,7 @@ import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { this = "MissedTernaryOpportunity" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(IfStmt is, AssignExpr ae1 |
ae1 = is.getThen().stripSingletonBlocks().(ExprStmt).getExpr()
|

View File

@@ -16,7 +16,7 @@ import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { this = "UselessIsBeforeAs" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(IfStmt is, AsExpr ae, IsTypeExpr ie |
ie = is.getCondition().getAChild*() and
ae.getTargetType() = ie.getCheckedType() and

View File

@@ -17,7 +17,7 @@ import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { this = "UselessNullCoalescingExpression" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(NullCoalescingExpr nce |
x.(Access) = nce.getLeftOperand() and
y.(Access) = nce.getRightOperand().getAChildExpr*()

View File

@@ -19,7 +19,7 @@ import semmle.code.csharp.commons.StructuralComparison as SC
class NestedForConditions extends SC::StructuralComparisonConfiguration {
NestedForConditions() { this = "Compare nested for conditions" }
override predicate candidate(Element e1, Element e2) {
override predicate candidate(ControlFlowElement e1, ControlFlowElement e2) {
exists(NestedForLoopSameVariable nested |
e1 = nested.getInnerForStmt().getCondition() and
e2 = nested.getOuterForStmt().getCondition()

View File

@@ -16,7 +16,7 @@ import semmle.code.csharp.commons.StructuralComparison
class StructuralComparisonConfig extends StructuralComparisonConfiguration {
StructuralComparisonConfig() { this = "SelfAssignment" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(AssignExpr ae |
// Member initializers are never self-assignments, in particular
// not initializers such as `new C { F = F };`

View File

@@ -16,7 +16,7 @@ import semmle.code.csharp.controlflow.Guards as G
class SameElement extends StructuralComparisonConfiguration {
SameElement() { this = "Same element" }
override predicate candidate(Element e1, Element e2) {
override predicate candidate(ControlFlowElement e1, ControlFlowElement e2) {
exists(MethodCall mc, IndexerRead access |
mc.getTarget().hasName("ContainsKey") and
access.getQualifier().(G::GuardedExpr).isGuardedBy(mc, mc.getQualifier(), _) and

View File

@@ -7,7 +7,7 @@ public class HttpHandler : IHttpHandler
public void ProcessRequest(HttpContext ctx)
{
string format = ctx.Request.QueryString["nameformat"];
// BAD: Uncontrolled format string.
FormattedName = string.Format(format, Surname, Forenames);
}

View File

@@ -108,7 +108,7 @@ private module ConstantComparisonOperation {
private class StructuralComparisonConfig extends StructuralComparison::StructuralComparisonConfiguration {
StructuralComparisonConfig() { this = "CompareIdenticalValues" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(ComparisonTest ct |
x = ct.getFirstArgument() and
y = ct.getSecondArgument()

View File

@@ -15,13 +15,13 @@ private Declaration referenceAttribute(Expr e) {
}
/** Gets the AST node kind element `e`. */
private int elementKind(Element e) {
private int elementKind(ControlFlowElement e) {
expressions(e, result, _)
or
exists(int k | statements(e, k) | result = -k)
}
private int getNumberOfActualChildren(Element e) {
private int getNumberOfActualChildren(ControlFlowElement e) {
if e.(MemberAccess).targetIsThisInstance()
then result = e.getNumberOfChildren() - 1
else result = e.getNumberOfChildren()
@@ -55,21 +55,25 @@ abstract class StructuralComparisonConfiguration extends string {
* In fact, not including the symmetrically implied fact will save
* half the computation time on the structural comparison.
*/
abstract predicate candidate(Element x, Element y);
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
private predicate candidateInternal(Element x, Element y) {
(
candidate(x, y)
or
exists(Element xParent, Element yParent, int i | candidateInternal(xParent, yParent) |
hasChild(xParent, i, x) and
hasChild(yParent, i, y)
)
private predicate candidateInternal(ControlFlowElement x, ControlFlowElement y) {
candidate(x, y)
or
exists(ControlFlowElement xParent, ControlFlowElement yParent, int i |
candidateInternalChild(xParent, i, x, yParent)
|
y = yParent.getChild(i)
)
}
pragma[noinline]
private predicate hasChild(Element e, int i, Element child) { child = e.getChild(i) }
private predicate candidateInternalChild(
ControlFlowElement x, int i, ControlFlowElement xChild, ControlFlowElement y
) {
candidateInternal(x, y) and
xChild = x.getChild(i)
}
private predicate sameByValue(Expr x, Expr y) { sameByValueAux(x, y, y.getValue()) }
@@ -79,28 +83,20 @@ abstract class StructuralComparisonConfiguration extends string {
value = x.getValue()
}
pragma[nomagic]
private predicate sameByStructure(Element x, Element y) {
// At least one of `x` and `y` must not have a value, they must have
// the same kind, and the same number of children
sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) and
// If one of them has a reference attribute, they should both reference
// the same node
(exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and
// x is a member access on `this` iff y is
(x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and
(y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance()) and
// All of their corresponding children must be structurally equal
forall(int i, Element xc |
xc = x.getChild(i) and
// exclude `this` qualifier, which has been checked above
not (i = -1 and x.(MemberAccess).targetIsThisInstance())
|
sameInternal(xc, y.getChild(i))
)
private ControlFlowElement getRankedChild(ControlFlowElement cfe, int rnk, int i) {
(candidateInternal(cfe, _) or candidateInternal(_, cfe)) and
i = rank[rnk](int j |
exists(ControlFlowElement child | child = cfe.getChild(j) |
not (j = -1 and cfe.(MemberAccess).targetIsThisInstance())
)
) and
result = cfe.getChild(i)
}
private predicate sameByStructureCandidate(Element x, Element y, int elementKind, int children) {
pragma[nomagic]
private predicate sameByStructure0(
ControlFlowElement x, ControlFlowElement y, int elementKind, int children
) {
candidateInternal(x, y) and
elementKind = elementKind(x) and
children = getNumberOfActualChildren(x) and
@@ -108,10 +104,28 @@ abstract class StructuralComparisonConfiguration extends string {
}
pragma[nomagic]
private predicate sameInternal(Element x, Element y) {
private predicate sameByStructure(ControlFlowElement x, ControlFlowElement y, int i) {
i = 0 and
// At least one of `x` and `y` must not have a value, they must have
// the same kind, and the same number of children
sameByStructure0(x, y, elementKind(y), getNumberOfActualChildren(y)) and
// If one of them has a reference attribute, they should both reference
// the same node
(exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and
// x is a member access on `this` iff y is
(x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and
(y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance())
or
exists(int j | sameByStructure(x, y, i - 1) |
sameInternal(getRankedChild(x, i, j), getRankedChild(y, i, j))
)
}
pragma[nomagic]
private predicate sameInternal(ControlFlowElement x, ControlFlowElement y) {
sameByValue(x, y)
or
sameByStructure(x, y)
sameByStructure(x, y, getNumberOfActualChildren(x))
}
/**
@@ -119,7 +133,7 @@ abstract class StructuralComparisonConfiguration extends string {
* flagged as candidates for structural equality, that is,
* `candidate(x, y)` must hold.
*/
predicate same(Element x, Element y) {
predicate same(ControlFlowElement x, ControlFlowElement y) {
candidate(x, y) and
sameInternal(x, y)
}
@@ -166,21 +180,25 @@ module Internal {
* In fact, not including the symmetrically implied fact will save
* half the computation time on the structural comparison.
*/
abstract predicate candidate(Element x, Element y);
abstract predicate candidate(ControlFlowElement x, ControlFlowElement y);
private predicate candidateInternal(Element x, Element y) {
(
candidate(x, y)
or
exists(Element xParent, Element yParent, int i | candidateInternal(xParent, yParent) |
hasChild(xParent, i, x) and
hasChild(yParent, i, y)
)
private predicate candidateInternal(ControlFlowElement x, ControlFlowElement y) {
candidate(x, y)
or
exists(ControlFlowElement xParent, ControlFlowElement yParent, int i |
candidateInternalChild(xParent, i, x, yParent)
|
y = yParent.getChild(i)
)
}
pragma[noinline]
private predicate hasChild(Element e, int i, Element child) { child = e.getChild(i) }
private predicate candidateInternalChild(
ControlFlowElement x, int i, ControlFlowElement xChild, ControlFlowElement y
) {
candidateInternal(x, y) and
xChild = x.getChild(i)
}
private predicate sameByValue(Expr x, Expr y) { sameByValueAux(x, y, y.getValue()) }
@@ -190,28 +208,20 @@ module Internal {
value = x.getValue()
}
pragma[nomagic]
private predicate sameByStructure(Element x, Element y) {
// At least one of `x` and `y` must not have a value, they must have
// the same kind, and the same number of children
sameByStructureCandidate(x, y, elementKind(y), getNumberOfActualChildren(y)) and
// If one of them has a reference attribute, they should both reference
// the same node
(exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and
// x is a member access on `this` iff y is
(x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and
(y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance()) and
// All of their corresponding children must be structurally equal
forall(int i, Element xc |
xc = x.getChild(i) and
// exclude `this` qualifier, which has been checked above
not (i = -1 and x.(MemberAccess).targetIsThisInstance())
|
sameInternal(xc, y.getChild(i))
)
private ControlFlowElement getRankedChild(ControlFlowElement cfe, int rnk, int i) {
(candidateInternal(cfe, _) or candidateInternal(_, cfe)) and
i = rank[rnk](int j |
exists(ControlFlowElement child | child = cfe.getChild(j) |
not (j = -1 and cfe.(MemberAccess).targetIsThisInstance())
)
) and
result = cfe.getChild(i)
}
private predicate sameByStructureCandidate(Element x, Element y, int elementKind, int children) {
pragma[nomagic]
private predicate sameByStructure0(
ControlFlowElement x, ControlFlowElement y, int elementKind, int children
) {
candidateInternal(x, y) and
elementKind = elementKind(x) and
children = getNumberOfActualChildren(x) and
@@ -219,10 +229,28 @@ module Internal {
}
pragma[nomagic]
private predicate sameInternal(Element x, Element y) {
private predicate sameByStructure(ControlFlowElement x, ControlFlowElement y, int i) {
i = 0 and
// At least one of `x` and `y` must not have a value, they must have
// the same kind, and the same number of children
sameByStructure0(x, y, elementKind(y), getNumberOfActualChildren(y)) and
// If one of them has a reference attribute, they should both reference
// the same node
(exists(referenceAttribute(x)) implies referenceAttribute(x) = referenceAttribute(y)) and
// x is a member access on `this` iff y is
(x.(MemberAccess).targetIsThisInstance() implies y.(MemberAccess).targetIsThisInstance()) and
(y.(MemberAccess).targetIsThisInstance() implies x.(MemberAccess).targetIsThisInstance())
or
exists(int j | sameByStructure(x, y, i - 1) |
sameInternal(getRankedChild(x, i, j), getRankedChild(y, i, j))
)
}
pragma[nomagic]
private predicate sameInternal(ControlFlowElement x, ControlFlowElement y) {
sameByValue(x, y)
or
sameByStructure(x, y)
sameByStructure(x, y, getNumberOfActualChildren(x))
}
/**
@@ -230,7 +258,7 @@ module Internal {
* flagged as candidates for structural equality, that is,
* `candidate(x, y)` must hold.
*/
predicate same(Element x, Element y) {
predicate same(ControlFlowElement x, ControlFlowElement y) {
candidate(x, y) and
sameInternal(x, y)
}

View File

@@ -19,6 +19,11 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
/** Gets the enclosing callable of this element, if any. */
Callable getEnclosingCallable() { none() }
/** Gets the assembly that this element was compiled into. */
Assembly getAssembly() {
result = this.getEnclosingCallable().getDeclaringType().getALocation()
}
/**
* Gets a control flow node for this element. That is, a node in the
* control flow graph that corresponds to this element.

View File

@@ -1200,7 +1200,7 @@ module Internal {
private class ConditionOnExprComparisonConfig extends InternalStructuralComparisonConfiguration {
ConditionOnExprComparisonConfig() { this = "ConditionOnExprComparisonConfig" }
override predicate candidate(Element x, Element y) {
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
exists(BasicBlock bb, Declaration d |
candidateAux(x, d, bb) and
y = any(AccessOrCallExpr e |
@@ -1221,7 +1221,7 @@ module Internal {
exists(Guard g | e = g.getAChildExpr*() |
g.controls(bb, _)
or
g.assertionControlsElement(bb.getANode().getElement(), _)
g.assertionControlsNode(bb.getANode(), _)
)
}
}

View File

@@ -185,14 +185,28 @@ private class Overflowable extends UnaryOperation {
}
}
private class CoreLib extends Assembly {
CoreLib() { this = any(SystemExceptionClass c).getALocation() }
}
/**
* Holds if assembly `a` was definitely compiled with core library `core`.
*/
pragma[noinline]
private predicate assemblyCompiledWithCoreLib(Assembly a, CoreLib core) {
a.getAnAttribute().getType().getBaseClass*().(SystemAttributeClass).getALocation() = core
}
/** A control flow element that is inside a `try` block. */
private class TriedControlFlowElement extends ControlFlowElement {
TriedControlFlowElement() { this = any(TryStmt try).getATriedElement() }
TryStmt try;
TriedControlFlowElement() { this = try.getATriedElement() }
/**
* Gets an exception class that is potentially thrown by this element, if any.
*/
Class getAThrownException() {
private Class getAThrownException0() {
this instanceof Overflowable and
result instanceof SystemOverflowExceptionClass
or
@@ -249,6 +263,40 @@ private class TriedControlFlowElement extends ControlFlowElement {
this instanceof StringLiteral and
result instanceof SystemOutOfMemoryExceptionClass
}
private CoreLib getCoreLibFromACatchClause() {
exists(SpecificCatchClause scc | scc = try.getACatchClause() |
result = scc.getCaughtExceptionType().getBaseClass*().(SystemExceptionClass).getALocation()
)
}
private CoreLib getCoreLib() {
result = this.getCoreLibFromACatchClause()
or
not exists(this.getCoreLibFromACatchClause()) and
assemblyCompiledWithCoreLib(this.getAssembly(), result)
}
pragma[noinline]
private Class getAThrownExceptionFromPlausibleCoreLib(string name) {
result = this.getAThrownException0() and
name = result.getQualifiedName() and
(
not exists(this.getCoreLib())
or
this.getCoreLib() = result.getALocation()
)
}
Class getAThrownException() {
exists(string name | result = this.getAThrownExceptionFromPlausibleCoreLib(name) |
result = min(Class c |
c = this.getAThrownExceptionFromPlausibleCoreLib(name)
|
c order by c.getLocation().(Assembly).getFullName()
)
)
}
}
pragma[noinline]

View File

@@ -9,6 +9,8 @@ module DataFlow {
private import semmle.code.csharp.dataflow.CallContext
private import semmle.code.csharp.dataflow.DelegateDataFlow
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
private import semmle.code.csharp.frameworks.EntityFramework
private import semmle.code.csharp.frameworks.NHibernate
private import Internal::Cached
private import dotnet
private import cil
@@ -34,14 +36,13 @@ module DataFlow {
DotNet::Type getType() { none() }
/** Gets the enclosing callable of this node. */
cached
DotNet::Callable getEnclosingCallable() { none() }
final DotNet::Callable getEnclosingCallable() { result = getEnclosingCallable(this) }
/** Gets a textual representation of this node. */
string toString() { none() }
/** Gets the location of this node. */
Location getLocation() { none() }
final Location getLocation() { result = getLocation(this) }
}
/**
@@ -65,25 +66,12 @@ module DataFlow {
override DotNet::Type getType() { result = this.getExpr().getType() }
override DotNet::Callable getEnclosingCallable() {
result = this.getExpr().getEnclosingCallable()
}
override string toString() {
exists(ControlFlow::Nodes::ElementNode cfn | this = TExprNode(cfn) | result = cfn.toString())
or
this = TCilExprNode(_) and
result = "CIL expression"
}
override Location getLocation() {
exists(ControlFlow::Nodes::ElementNode cfn | this = TExprNode(cfn) |
result = cfn.getLocation()
)
or
result.getFile().isPdbSourceFile() and
exists(CIL::Expr e | this = TCilExprNode(e) | result = e.getALocation())
}
}
/**
@@ -117,6 +105,15 @@ module DataFlow {
predicate localFlowStep = Internal::LocalFlow::step/2;
/**
* A dataflow node that jumps between callables. This can be extended in framework code
* to add additional dataflow steps.
*/
abstract class NonLocalJumpNode extends Node {
/** Gets a successor node that is potentially in another callable. */
abstract Node getAJumpSuccessor(boolean preservesValue);
}
/**
* A data flow node augmented with a call context and a configuration. Only
* nodes that are reachable from a source, and which can reach a sink, are
@@ -246,17 +243,6 @@ module DataFlow {
none()
}
/**
* INTERNAL: Do not use.
*
* Holds if the additional flow step from `ret` to `out` out of the call
* `call` must be taken into account in the analysis, but only in call
* context `cc`.
*/
predicate isAdditionalFlowStepOutOfCall(Node call, Node ret, Node out, CallContext cc) {
none()
}
/**
* Holds if data may flow from `source` to `sink` for this configuration.
*/
@@ -289,16 +275,10 @@ module DataFlow {
override Type getType() { result = def.getSourceVariable().getType() }
override Callable getEnclosingCallable() {
result = def.getSourceVariable().getEnclosingCallable()
}
override string toString() {
result = def.toString() and
not this instanceof ExplicitParameterNode
}
override Location getLocation() { result = def.getLocation() }
}
/**
@@ -329,11 +309,7 @@ module DataFlow {
override DotNet::Type getType() { result = parameter.getType() }
override DotNet::Callable getEnclosingCallable() { result = parameter.getCallable() }
override string toString() { result = parameter.toString() }
override Location getLocation() { result = parameter.getLocation() }
}
/**
@@ -420,11 +396,7 @@ module DataFlow {
override Type getType() { result = arg.getType() }
override Callable getEnclosingCallable() { result = arg.getEnclosingCallable() }
override string toString() { result = "[implicit call] " + arg.toString() }
override Location getLocation() { result = arg.getLocation() }
}
/** A data flow node that represents the output of a call. */
@@ -486,6 +458,7 @@ module DataFlow {
abstract ArgumentContext getContext(Configuration config);
/** Holds if this argument node does not have an associated control flow node. */
cached
abstract predicate hasNoControlFlowNode();
}
@@ -503,8 +476,10 @@ module DataFlow {
/**
* Holds if this argument occurs at position `pos` in call `call`.
*/
predicate isArgumentOf(CallNode call, int pos, Configuration config) {
exists(ExplicitParameterNode p | flowIntoCallableStep(call, this, p, _, config) |
private predicate isArgumentOf(CallNode call, int pos, Configuration config) {
exists(ExplicitParameterNode p |
Pruning::flowIntoCallableStepCand(call, this, p, _, config)
|
pos = p.getParameter().getPosition()
)
}
@@ -518,7 +493,6 @@ module DataFlow {
)
}
bindingset[config]
override ExplicitArgumentContext getContext(Configuration config) {
result.getCallContext() = this.getArgumentCallContext(config)
}
@@ -578,11 +552,7 @@ module DataFlow {
override Type getType() { result = v.getType() }
override Callable getEnclosingCallable() { result = c.getEnclosingCallable() }
override string toString() { result = v + " [implicit argument]" }
override Location getLocation() { result = c.getLocation() }
}
/**
@@ -591,18 +561,35 @@ module DataFlow {
abstract private class ReturnNode extends Node { }
/**
* A data flow node that represents an expression returned explicitly by a callable.
* Either an argument of `return`/`yield return` or an expression assigned to an
* `out`/`ref` parameter.
* A data flow node that represents an expression returned by a callable,
* using an ordinary `return` or a method expression.
*/
private class ExplicitReturnNode extends ReturnNode, ExprNode {
ExplicitReturnNode() {
exists(DotNet::Callable c, DotNet::Expr e | e = this.getExpr() |
c.canReturn(e) or
c.(Callable).canYieldReturn(e) or
callableReturnsOutOrRef(c, _, e)
)
}
class NormalReturnNode extends ReturnNode, TNormalReturnNode {
override Type getType() { result = this.getEnclosingCallable().getReturnType() }
override string toString() { result = "return " + this.getEnclosingCallable() }
}
/**
* A data flow node that represents an expression returned by a callable,
* using `yield return`.
*/
class YieldReturnNode extends ReturnNode, TYieldReturnNode {
override Type getType() { result = this.getEnclosingCallable().getReturnType() }
override string toString() { result = "yield return " + this.getEnclosingCallable() }
}
/**
* A data flow node that represents an expression returned by a callable,
* using an `out`/`ref` parameter.
*/
private class OutRefReturnNode extends ReturnNode, TOutRefReturnNode {
Parameter getParameter() { this = TOutRefReturnNode(result) }
override Type getType() { result = this.getParameter().getType() }
override string toString() { result = "return (out/ref) " + this.getEnclosingCallable() }
}
/**
@@ -700,7 +687,7 @@ module DataFlow {
CilCall() {
call = this and
// No need to include calls that are compiled from source
not call.getImplementation().getMethod().compiledFromSource()
cilCallWithoutSource(call)
}
override DotNet::Callable getARuntimeTarget() {
@@ -879,6 +866,16 @@ module DataFlow {
}
}
// noopt is needed to force scan of `config.isAdditionalFlowStep` followed
// by join on `getEnclosingCallable()`, instead of the other way around
pragma[noopt]
private predicate isAdditionalFlowStep(
Node pred, Node succ, Configuration config, DotNet::Callable c
) {
config.isAdditionalFlowStep(pred, succ) and
pred.getEnclosingCallable() = c
}
/** Provides predicates related to local data flow. */
module LocalFlow {
private class LocalExprStepConfiguration extends ExprStepConfiguration {
@@ -996,6 +993,14 @@ module DataFlow {
or
Internal::flowOutOfDelegateLibraryCall(nodeFrom, nodeTo, true)
or
flowThroughCallableLibraryOutRef(_, nodeFrom, nodeTo, true)
or
exists(DotNet::Callable c | c.canReturn(nodeFrom.asExpr()) | nodeTo = TNormalReturnNode(c))
or
exists(Parameter p | callableReturnsOutOrRef(_, p, nodeFrom.asExpr()) |
nodeTo = TOutRefReturnNode(p)
)
or
localFlowStepCil(nodeFrom, nodeTo)
}
@@ -1079,18 +1084,14 @@ module DataFlow {
(isSuccessor = true or isSuccessor = false)
}
predicate localFlowStepNoConfig(Node pred, Node succ) {
localFlowStep(pred, succ) or
flowThroughCallableLibraryOutRef(_, pred, succ, true)
}
/**
* Holds if data may flow in one local step from `pred` to `succ`.
*/
bindingset[config]
predicate localFlowStep(Node pred, Node succ, Configuration config) {
localFlowStepNoConfig(pred, succ) or
config.isAdditionalFlowStep(pred, succ)
localFlowStep(pred, succ)
or
isAdditionalFlowStep(pred, succ, config, succ.getEnclosingCallable())
}
/**
@@ -1101,9 +1102,10 @@ module DataFlow {
Pruning::nodeCand(node, config) and
(
config.isSource(node) or
jumpStep(_, node) or
jumpStep(_, node, config) or
node instanceof ParameterNode or
node instanceof OutNode
node instanceof OutNode or
node instanceof ReturnNode
)
}
@@ -1114,9 +1116,14 @@ module DataFlow {
predicate localFlowExit(Node node, Configuration config) {
Pruning::nodeCand(node, config) and
(
jumpStep(node, _) or
node instanceof ArgumentNode or
node instanceof ReturnNode or
jumpStep(node, _, config)
or
node instanceof ArgumentNode
or
node instanceof ReturnNode
or
localFlowStep(node, any(ReturnNode rn), config)
or
config.isSink(node)
)
}
@@ -1155,6 +1162,27 @@ module DataFlow {
}
}
/**
* Holds if the additional step from `node1` to `node2` jumps between callables.
*/
pragma[noinline]
private predicate additionalJumpStep(Node node1, Node node2, Configuration config) {
exists(DotNet::Callable c1 | isAdditionalFlowStep(node1, node2, config, c1) |
c1 != node2.getEnclosingCallable()
)
}
/**
* Holds if `pred` can flow to `succ`, by jumping from one callable to
* another.
*/
bindingset[config]
private predicate jumpStep(Node node1, Node node2, Configuration config) {
additionalJumpStep(node1, node2, config)
or
jumpStepNoConfig(node1, node2)
}
/**
* Provides predicates for pruning the data flow graph, by only including
* nodes that may potentially be reached in flow from some source to some
@@ -1172,15 +1200,13 @@ module DataFlow {
or
exists(Node mid | nodeCandFwd1(mid, config) | LocalFlow::localFlowStep(mid, node, config))
or
exists(Node mid | nodeCandFwd1(mid, config) | jumpStep(mid, node))
exists(Node mid | nodeCandFwd1(mid, config) | jumpStep(mid, node, config))
or
exists(ArgumentNode arg | nodeCandFwd1(arg, config) |
flowIntoCallableStep(_, arg, node, _, config)
)
or
exists(Node mid | nodeCandFwd1(mid, config) |
flowOutOfCallableStep(_, mid, node, _, config)
)
exists(Node mid | nodeCandFwd1(mid, config) | flowOutOfCallableStep(mid, _, node, _))
)
}
@@ -1195,13 +1221,13 @@ module DataFlow {
or
exists(Node mid | nodeCand1(mid, config) | LocalFlow::localFlowStep(node, mid, config))
or
exists(Node mid | nodeCand1(mid, config) | jumpStep(node, mid))
exists(Node mid | nodeCand1(mid, config) | jumpStep(node, mid, config))
or
exists(ParameterNode p | nodeCand1(p, config) |
flowIntoCallableStep(_, node, p, _, config)
)
or
exists(Node mid | nodeCand1(mid, config) | flowOutOfCallableStep(_, node, mid, _, config))
exists(Node mid | nodeCand1(mid, config) | flowOutOfCallableStep(node, _, mid, _))
)
}
@@ -1250,7 +1276,7 @@ module DataFlow {
pragma[noinline]
private predicate jumpStepCand1(Node pred, Node succ, Configuration config) {
nodeCand1(succ, config) and
jumpStep(pred, succ)
jumpStep(pred, succ, config)
}
pragma[noinline]
@@ -1261,12 +1287,15 @@ module DataFlow {
flowIntoCallableStep(call, arg, p, _, config)
}
pragma[noinline]
// noopt is needed to force scan of `nodeCand1()` followed by join on
// `flowOutOfCallableStep()`, instead of the other way around
pragma[noopt]
private predicate flowOutOfCallableStepCand1(
CallNode call, ReturnNode ret, OutNode out, Configuration config
) {
nodeCand1(out, config) and
flowOutOfCallableStep(call, ret, out, _, config)
nodeCand1(ret, _) and
nodeCand1(ret, config) and
flowOutOfCallableStep(ret, call, out, _)
}
/**
@@ -1316,12 +1345,15 @@ module DataFlow {
flowIntoCallableStep(_, arg, p, _, config)
}
pragma[noinline]
// noopt is needed to force scan of `nodeCandFwd2()` followed by join on
// `flowOutOfCallableStep()`, instead of the other way around
pragma[noopt]
private predicate flowOutOfCallableStepCandFwd2(
CallNode call, ReturnNode ret, OutNode out, CallContext cc, Configuration config
ReturnNode ret, OutNode out, Configuration config
) {
nodeCandFwd2(ret, _, _) and
nodeCandFwd2(ret, _, config) and
flowOutOfCallableStep(call, ret, out, cc, config)
flowOutOfCallableStep(ret, _, out, _)
}
/**
@@ -1339,7 +1371,7 @@ module DataFlow {
or
nodeCandFwd2(node, _, config) and
exists(Node mid | nodeCand2(mid, _, config) |
jumpStep(node, mid) and
jumpStep(node, mid, config) and
isReturned = false
)
or
@@ -1349,7 +1381,7 @@ module DataFlow {
)
or
exists(OutNode out | nodeCand2(out, _, config) |
flowOutOfCallableStepCandFwd2(_, node, out, _, config) and
flowOutOfCallableStepCandFwd2(node, out, config) and
isReturned = true
)
or
@@ -1363,7 +1395,27 @@ module DataFlow {
* Holds if `node` is part of a path from a source to a sink in the
* configuration `config`, taking simple call contexts into consideration.
*/
pragma[noinline]
predicate nodeCand(Node node, Configuration config) { nodeCand2(node, _, config) }
pragma[noinline]
predicate flowIntoCallableStepCand(
CallNode call, ArgumentNode arg, ParameterNode p, CallContext cc, Configuration config
) {
nodeCand(p, config) and
flowIntoCallableStep(call, arg, p, cc, config)
}
// noopt is needed to force scan of `nodeCand()` followed by join on
// `flowOutOfCallableStep()`, instead of the other way around
pragma[noopt]
predicate flowOutOfCallableStepCand(
CallNode call, ReturnNode ret, OutNode out, CallContext cc, Configuration config
) {
nodeCand(ret, _) and
nodeCand(ret, config) and
flowOutOfCallableStep(ret, call, out, cc)
}
}
// A workaround to avoid eager joining on configurations
@@ -1390,20 +1442,82 @@ module DataFlow {
exists(Ssa::ExplicitDefinition def | def.isCapturedVariableDefinitionFlowIn(_, c) |
v = def.getSourceVariable().getAssignable()
)
}
} or
TNormalReturnNode(DotNet::Callable c) { c.canReturn(_) } or
TYieldReturnNode(Callable c) { c.canYieldReturn(_) } or
TOutRefReturnNode(Parameter p) { callableReturnsOutOrRef(_, p, _) }
cached
DotNet::Callable getEnclosingCallable(Node node) {
result = node.(ExprNode).getExpr().getEnclosingCallable()
or
result = node.(SsaDefinitionNode).getDefinition().getSourceVariable().getEnclosingCallable()
or
result = node.(ExplicitParameterNode).getParameter().getCallable()
or
result = node.(ImplicitDelegateCallNode).getArgument().getEnclosingCallable()
or
result = node.(ImplicitCapturedArgumentNode).getCall().getEnclosingCallable()
or
node = TNormalReturnNode(result)
or
node = TYieldReturnNode(result)
or
result = node.(OutRefReturnNode).getParameter().getCallable()
}
cached
Location getLocation(Node node) {
exists(ControlFlow::Nodes::ElementNode cfn | node = TExprNode(cfn) |
result = cfn.getLocation()
)
or
result.getFile().isPdbSourceFile() and
exists(CIL::Expr e | node = TCilExprNode(e) | result = e.getALocation())
or
result = node.(SsaDefinitionNode).getDefinition().getLocation()
or
result = node.(ExplicitParameterNode).getParameter().getLocation()
or
result = node.(ImplicitDelegateCallNode).getArgument().getLocation()
or
result = node.(ImplicitCapturedArgumentNode).getCall().getLocation()
or
result = node.(NormalReturnNode).getEnclosingCallable().getLocation()
or
result = node.(YieldReturnNode).getEnclosingCallable().getLocation()
or
result = node.(OutRefReturnNode).getParameter().getLocation()
}
/**
* Holds if `pred` can flow to `succ`, by jumping from one callable to
* another.
* another. Additional steps specified by the configuration are *not* taken into account.
*/
cached
predicate jumpStep(ExprNode pred, ExprNode succ) {
exists(FieldLike fl, FieldLikeRead flr | fl.isStatic() |
fl.getAnAssignedValue() = pred.getExpr() and
predicate jumpStepNoConfig(ExprNode pred, ExprNode succ) {
pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
}
/** A dataflow node that has field-like dataflow. */
private class FieldLikeJumpNode extends NonLocalJumpNode, ExprNode {
FieldLike fl;
FieldLikeRead flr;
ExprNode succ;
FieldLikeJumpNode() {
fl.isStatic() and
fl.getAnAssignedValue() = this.getExpr() and
fl.getAnAccess() = flr and
flr = succ.getExpr() and
hasNonlocalValue(flr)
)
}
override ExprNode getAJumpSuccessor(boolean preservesValue) {
result = succ and preservesValue = true
}
}
/**
@@ -1456,25 +1570,17 @@ module DataFlow {
* account.
*/
cached
predicate flowOutOfCallableStepNoConfig(
CallNode call, ReturnNode ret, OutNode out, CallContext cc
) {
flowOutOfCallableExplicitStep(call, ret, out, cc)
predicate flowOutOfCallableStep(ReturnNode ret, CallNode call, OutNode out, CallContext cc) {
flowOutOfCallableNonDelegateCall(call.asExpr(), ret, out) and
cc instanceof EmptyCallContext
or
flowOutOfCallableDelegateCall(call, ret, cc) and
out = call
or
flowOutOfCallableCapturedVarStep(call, ret, out) and
cc instanceof EmptyCallContext
}
private predicate flowOutOfCallableExplicitStep(
CallNode call, ReturnNode ret, OutNode out, CallContext cc
) {
flowOutOfCallableNonDelegateCall(call.asExpr(), ret.asExpr(), out) and
cc instanceof EmptyCallContext
or
flowOutOfCallableDelegateCall(call, ret.asExpr(), cc) and
out = call
}
/**
* Holds if `ret` is an expression returned implicitly by a callable, from
* `call` using zero or more additional calls, and `out` is the corresponding
@@ -1486,6 +1592,11 @@ module DataFlow {
ret.flowsOut(out.getDefinition()) and
call.asExpr() = out.getCall()
}
cached
predicate cilCallWithoutSource(CIL::Call call) {
not call.getImplementation().getMethod().compiledFromSource()
}
}
private newtype TContext =
@@ -1499,9 +1610,9 @@ module DataFlow {
Pruning::nodeCand(arg, _)
} or
TReturnContext(CallNode call, DotNet::Callable callable) {
exists(ReturnNode ret, Configuration config | Pruning::nodeCand(ret, config) |
exists(ReturnNode ret |
callable = ret.getEnclosingCallable() and
flowOutOfCallableStep(call, ret, _, _, config)
Pruning::flowOutOfCallableStepCand(call, ret, _, _, _)
)
}
@@ -1519,8 +1630,8 @@ module DataFlow {
* Holds if flow out of a callable is allowed to go via the call
* `call` in this context.
*/
bindingset[call, config]
predicate flowOutAllowedToCall(DotNet::Expr call, Configuration config) {
bindingset[call]
predicate flowOutAllowedToCall(DotNet::Expr call) {
// This context poses no restriction
this instanceof NoContext or
// Data in this context is from a call, so flow back out must be through
@@ -1532,8 +1643,8 @@ module DataFlow {
// call context, in which case flow further out must respect that call
// context
this = any(ReturnContext rc |
not exists(rc.getARequiredContext(config)) or
rc.getARequiredContext(config).(ArgumentCallContext).isArgument(call, _)
not exists(rc.getARequiredContext()) or
rc.getARequiredContext().(ArgumentCallContext).isArgument(call, _)
)
}
}
@@ -1598,22 +1709,15 @@ module DataFlow {
* Gets a call context required for the flow out to the data described by this
* context to be possible.
*/
ArgumentCallContext getARequiredContext(Configuration config) {
result = getARequiredContext0(call, callable, config)
ArgumentCallContext getARequiredContext() {
exists(ReturnNode ret | Pruning::flowOutOfCallableStepCand(call, ret, _, result, _) |
callable = ret.getEnclosingCallable()
)
}
override string toString() { result = call.toString() }
}
pragma[noinline]
private ArgumentCallContext getARequiredContext0(
CallNode call, DotNet::Callable callable, Configuration config
) {
exists(ReturnNode ret | flowOutOfCallableStep(call, ret, _, result, config) |
callable = ret.getEnclosingCallable()
)
}
newtype TFlowGraphNode =
TFlowGraphNode0(Node node, Context ctx, Configuration config) {
// A source
@@ -1691,7 +1795,7 @@ module DataFlow {
ctx = mid.getContext() and
LocalFlow::localFlowBigStep(mid.getNode(), node, mid.getConfiguration())
or
jumpStep(mid.getNode(), node) and
jumpStep(mid.getNode(), node, mid.getConfiguration()) and
ctx instanceof NoContext
or
flowIntoCallable(mid, node, ctx)
@@ -1703,16 +1807,15 @@ module DataFlow {
pragma[noinline]
private predicate flowIntoCallable0(FlowGraphNode mid, ArgumentNode arg, ParameterNode p) {
exists(Context outerctx, CallContext cc, Configuration config |
config = mid.getConfiguration() and
flowIntoCallableStep(_, arg, p, cc, config) and
exists(Context outerctx, CallContext cc |
Pruning::flowIntoCallableStepCand(_, arg, p, cc, mid.getConfiguration()) and
arg = mid.getNode() and
outerctx = mid.getContext()
|
cc instanceof EmptyCallContext
or
exists(DotNet::Expr call | cc.(ArgumentCallContext).isArgument(call, _) |
outerctx.flowOutAllowedToCall(call, config)
outerctx.flowOutAllowedToCall(call)
)
)
}
@@ -1731,7 +1834,7 @@ module DataFlow {
private predicate flowOutOfCallable0(
FlowGraphNode mid, CallNode call, OutNode out, DotNet::Callable callable, Context innerctx
) {
flowOutOfCallableStep(call, mid.getNode(), out, _, mid.getConfiguration()) and
Pruning::flowOutOfCallableStepCand(call, mid.getNode(), out, _, mid.getConfiguration()) and
innerctx = mid.getContext() and
not innerctx instanceof ArgumentContext and
callable = mid.getEnclosingCallable()
@@ -1747,7 +1850,7 @@ module DataFlow {
flowOutOfCallable0(mid, call, out, callable, innerctx) and
outerctx = TReturnContext(call, callable)
|
innerctx.flowOutAllowedToCall(call.getCall(), mid.getConfiguration())
innerctx.flowOutAllowedToCall(call.getCall())
)
}
@@ -1758,7 +1861,7 @@ module DataFlow {
exists(int i | innerctx.getCallContext() = call.getCallContext(i) |
mid.getNode() = ret and
mid.getContext() = innerctx and
mid.getEnclosingCallable().getParameter(i) = p.getParameter()
mid.getEnclosingCallable() = p.getParameter().getCallable()
)
}
@@ -1774,13 +1877,14 @@ module DataFlow {
/** Holds if data may flow from `p` to a a node `out` returned by the callable. */
private predicate paramFlowsThrough(
CallNode call, ParameterNode p, OutNode out, ArgumentContext innerctx, CallContext cc
CallNode call, ParameterNode p, OutNode out, ArgumentContext innerctx, CallContext cc,
Configuration config
) {
exists(FlowGraphNode mid, ReturnNode ret |
paramFlowsThroughExplicit(call, p, innerctx, mid, ret) or
paramFlowsThroughImplicit(call, p, innerctx, mid, ret)
|
flowOutOfCallableStep(call, ret, out, cc, mid.getConfiguration())
Pruning::flowOutOfCallableStepCand(call, ret, out, cc, config)
)
}
@@ -1792,7 +1896,7 @@ module DataFlow {
private predicate flowThroughCallable0(FlowGraphNode mid, OutNode out, Context ctx) {
exists(CallNode call, ParameterNode p, ArgumentContext innerctx, CallContext cc |
flowIntoCallable(mid, p, innerctx) and
paramFlowsThrough(call, p, out, innerctx, cc)
paramFlowsThrough(call, p, out, innerctx, cc, mid.getConfiguration())
|
// Data in `mid` is from a call, so that call must match the required call (if any),
// and the context after flow through `call` must be recovered
@@ -1814,7 +1918,9 @@ module DataFlow {
private predicate flowThroughCallable1Scope(OutNode out, Expr e) {
flowThroughCallable0(_, out, _) and
e = out.asExpr().(Expr).getAChildExpr*()
e = out.asExpr()
or
exists(Expr mid | flowThroughCallable1Scope(out, mid) | e = mid.getAChildExpr())
}
pragma[nomagic]
@@ -1968,21 +2074,6 @@ module DataFlow {
config.isAdditionalFlowStepIntoCall(call, arg, p.getParameter(), cc)
}
/**
* Holds if `ret` is an expression returned by a callable to which the call
* `call` resolves, and `out` is the corresponding output (either `call`
* itself or an `out`/`ref` argument).
*
* Additional steps specified by the configuration are taken into account.
*/
bindingset[config]
predicate flowOutOfCallableStep(
CallNode call, ReturnNode ret, OutNode out, CallContext cc, Configuration config
) {
flowOutOfCallableStepNoConfig(call, ret, out, cc) or
config.isAdditionalFlowStepOutOfCall(call, ret, out, cc)
}
/**
* Holds if `arg` is an argument of the non-delegate call `call`,
* which resolves to a callable with corresponding parameter `p`.
@@ -2051,25 +2142,35 @@ module DataFlow {
p = result.getParameter(i)
}
pragma[noinline]
private predicate flowOutOfCallableNonDelegateCall0(ReturnNode ret, DotNet::Callable c) {
c = ret.(NormalReturnNode).getEnclosingCallable()
or
c = ret.(YieldReturnNode).getEnclosingCallable()
}
pragma[noinline]
private predicate flowOutOfCallableNonDelegateCall1(NonDelegateCall call, ReturnNode ret) {
flowOutOfCallableNonDelegateCall0(ret, call.getARuntimeTarget())
}
/**
* Holds if `ret` is an expression returned by a callable to
* which the non-delegate call `call` resolves, and `out` is the
* corresponding output (either `call` itself or first uses of
* a relevant `out`/`ref` argument).
*/
predicate flowOutOfCallableNonDelegateCall(NonDelegateCall call, DotNet::Expr ret, OutNode out) {
exists(DotNet::Callable callable | callable = call.getARuntimeTarget() |
// ordinary return value
callable.canReturn(ret) and
call = out.asExpr()
or
// return via out/ref parameter
exists(Parameter outRef, AssignableDefinitions::OutRefDefinition def |
callableReturnsOutOrRef(callable.getSourceDeclaration(), outRef.getSourceDeclaration(),
ret) and
def = out.(SsaDefinitionNode).getDefinition().(Ssa::ExplicitDefinition).getADefinition() and
def.getTargetAccess() = call.(Call).getArgumentForParameter(outRef)
)
predicate flowOutOfCallableNonDelegateCall(NonDelegateCall call, ReturnNode ret, OutNode out) {
// (yield) return value
flowOutOfCallableNonDelegateCall1(call, ret) and
call = out.asExpr()
or
// return via out/ref parameter
exists(Parameter p, AssignableDefinitions::OutRefDefinition def |
p.getSourceDeclaration() = ret.(OutRefReturnNode).getParameter()
|
def = out.(SsaDefinitionNode).getDefinition().(Ssa::ExplicitDefinition).getADefinition() and
def.getTargetAccess() = call.(Call).getArgumentForParameter(p)
)
}
@@ -2077,8 +2178,10 @@ module DataFlow {
* Holds if `ret` is an expression returned by a callable to
* which the delegate call `call` resolves.
*/
private predicate flowOutOfCallableDelegateCall(CallNode call, Expr ret, CallContext cc) {
exists(Callable target | target.getSourceDeclaration().canReturn(ret) |
private predicate flowOutOfCallableDelegateCall(
CallNode call, NormalReturnNode ret, CallContext cc
) {
exists(Callable target | ret.getEnclosingCallable() = target.getSourceDeclaration() |
target = call.asExpr().(DelegateCall).getARuntimeTarget(cc) or
target = call.(ImplicitDelegateCallNode).getArgument().getARuntimeTarget(cc)
)
@@ -2088,11 +2191,11 @@ module DataFlow {
* Holds if callable `c` can return `e` as an `out`/`ref` value
* for parameter `outRef`.
*/
predicate callableReturnsOutOrRef(Callable c, Parameter outRef, Expr e) {
predicate callableReturnsOutOrRef(Callable c, Parameter p, Expr e) {
exists(Ssa::ExplicitDefinition def |
def.getADefinition().getSource() = e and
def.isLiveOutRefParameterDefinition(outRef) and
outRef = c.getAParameter()
def.isLiveOutRefParameterDefinition(p) and
p = c.getAParameter()
)
}
}

View File

@@ -172,7 +172,7 @@ private predicate flowsFrom(
// Flow through static field or property
exists(DataFlow::Node mid |
flowsFrom(sink, mid, _, _) and
Cached::jumpStep(node, mid) and
Cached::jumpStepNoConfig(node, mid) and
isReturned = false and
lastCall instanceof EmptyCallContext
)
@@ -205,14 +205,14 @@ private predicate flowsFrom(
exists(DataFlow::Node mid |
flowsFrom(sink, mid, _, lastCall) and
isReturned = true and
flowOutOfCallableNonDelegateCall(_, node.asExpr(), mid)
flowOutOfCallableNonDelegateCall(_, node, mid)
)
or
// Flow out of a callable (delegate call).
exists(DataFlow::ExprNode mid |
flowsFrom(sink, mid, _, _) and
isReturned = true and
flowOutOfDelegateCall(mid.getExpr(), node.asExpr(), lastCall)
flowOutOfDelegateCall(mid.getExpr(), node, lastCall)
)
}
@@ -230,7 +230,7 @@ private CallContext getLastCall(CallContext prevLastCall, Expr call, int i) {
result = prevLastCall
}
// Predicate folding to get proper join-order
pragma[noinline]
private predicate flowIntoDelegateCall(DelegateCall dc, Callable c, Expr e, int i) {
exists(DelegateFlowSource dfs, DelegateCallExpr dce |
// the call context is irrelevant because the delegate call
@@ -242,11 +242,13 @@ private predicate flowIntoDelegateCall(DelegateCall dc, Callable c, Expr e, int
)
}
// Predicate folding to get proper join-order
private predicate flowOutOfDelegateCall(DelegateCall dc, Expr e, CallContext lastCall) {
pragma[noinline]
private predicate flowOutOfDelegateCall(
DelegateCall dc, DataFlow::Internal::NormalReturnNode ret, CallContext lastCall
) {
exists(DelegateFlowSource dfs, DelegateCallExpr dce, Callable c |
flowsFrom(dce, dfs, _, lastCall) and
c.canReturn(e) and
ret.getEnclosingCallable() = c and
c = dfs.getCallable() and
dc = dce.getDelegateCall()
)

View File

@@ -67,6 +67,14 @@ module Ssa {
)
)
}
cached
AssignableDefinition getADefinition(ExplicitDefinition def) {
exists(TrackedVar tv, AssignableDefinition ad | def = TSsaExplicitDef(tv, ad, _, _) |
result = ad or
result = getASameOutRefDefAfter(tv, ad)
)
}
}
import Cached
@@ -587,8 +595,7 @@ module Ssa {
* (when `k` is `SsaDef()`).
*/
private predicate ssaRef(BasicBlock bb, int i, SourceVariable v, SsaRefKind k) {
exists(ReadKind rk |
variableRead(bb, i, v, _, rk) |
exists(ReadKind rk | variableRead(bb, i, v, _, rk) |
not rk instanceof RefReadBeforeWrite and
k = SsaRead()
)
@@ -2248,8 +2255,7 @@ module Ssa {
* where there may be more than one underlying definition.
*/
AssignableDefinition getADefinition() {
result = ad or
result = getASameOutRefDefAfter(tv, ad)
result = getADefinition(this)
}
/**

View File

@@ -80,9 +80,11 @@ module TaintTracking {
predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { none() }
final override predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) {
isAdditionalTaintStep(pred, succ) or
localAdditionalTaintStep(pred, succ) or
DataFlow::Internal::flowThroughCallableLibraryOutRef(_, pred, succ, false)
isAdditionalTaintStep(pred, succ)
or
localAdditionalTaintStep(pred, succ)
or
succ = pred.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}
final override predicate isAdditionalFlowStepIntoCall(
@@ -91,17 +93,6 @@ module TaintTracking {
DataFlow::Internal::flowIntoCallableLibraryCall(_, arg, call, p, false, cc)
}
final override predicate isAdditionalFlowStepOutOfCall(
DataFlow::Node call, DataFlow::Node ret, DataFlow::Node out, CallContext::CallContext cc
) {
exists(DispatchCall dc, Callable callable | canYieldReturn(callable, ret.asExpr()) |
dc.getCall() = call.asExpr() and
call = out and
callable = dc.getADynamicTarget() and
cc instanceof CallContext::EmptyCallContext
)
}
/**
* Holds if taint may flow from `source` to `sink` for this configuration.
*/
@@ -113,8 +104,6 @@ module TaintTracking {
/** INTERNAL: Do not use. */
module Internal {
predicate canYieldReturn(Callable c, Expr e) { c.getSourceDeclaration().canYieldReturn(e) }
private CIL::DataFlowNode asCilDataFlowNode(DataFlow::Node node) {
result = node.asParameter() or
result = node.asExpr()
@@ -257,6 +246,12 @@ module TaintTracking {
or
access.(PropertyRead).getQualifier() = nodeFrom.asExpr()
)
or
DataFlow::Internal::flowThroughCallableLibraryOutRef(_, nodeFrom, nodeTo, false)
or
exists(Callable c | c.canYieldReturn(nodeFrom.asExpr()) |
c = nodeTo.(DataFlow::Internal::YieldReturnNode).getEnclosingCallable()
)
}
}
import Cached

View File

@@ -222,11 +222,43 @@ private module Internal {
}
}
private class FieldOrProperty extends Assignable {
FieldOrProperty() {
this instanceof Field or
this instanceof Property
private class DynamicFieldOrProperty extends Assignable {
DynamicFieldOrProperty() {
(
this instanceof Field or
this instanceof Property
) and
this.getName() = any(DynamicMemberAccess dma).getLateBoundTargetName()
}
predicate isMemberOf(string name, ValueOrRefType t) {
name = this.getName() and t.hasMember(this)
}
}
private class TypeWithDynamicFieldOrProperty extends ValueOrRefType {
DynamicFieldOrProperty fp;
TypeWithDynamicFieldOrProperty() { fp.isMemberOf(_, this) }
predicate isImplicitlyConvertibleTo(string name, Type t) {
name = fp.getName() and
this.isImplicitlyConvertibleTo(t)
}
}
pragma[noinline]
private predicate isPossibleDynamicMemberAccessQualifierType(
DynamicMemberAccess dma, string name, TypeWithDynamicFieldOrProperty t
) {
exists(Type qt, boolean isExact |
qt = getAPossibleType(dma.getQualifier(), isExact) and
name = dma.getLateBoundTargetName()
|
isExact = true and t = qt
or
isExact = false and t.isImplicitlyConvertibleTo(name, qt)
)
}
/**
@@ -235,14 +267,10 @@ private module Internal {
* corresponding to the type of a relevant field or property are included.
*/
private Type getAPossibleType(Expr e, boolean isExact) {
exists(ValueOrRefType qualifierType, FieldOrProperty fp, boolean qualifierTypeIsExact |
qualifierType = getAPossibleTypeDynamicMemberAccessQualifier(e, qualifierTypeIsExact, fp)
exists(DynamicFieldOrProperty fp, string name, TypeWithDynamicFieldOrProperty t |
isPossibleDynamicMemberAccessQualifierType(e, name, t) and
fp.isMemberOf(name, t)
|
(
if qualifierTypeIsExact = true
then qualifierType.hasMember(fp)
else fp.getDeclaringType().isImplicitlyConvertibleTo(qualifierType)
) and
result = fp.getType() and
isExact = false
)
@@ -251,13 +279,6 @@ private module Internal {
result = getASourceType(e, isExact)
}
private Type getAPossibleTypeDynamicMemberAccessQualifier(
DynamicMemberAccess dma, boolean isExact, FieldOrProperty fp
) {
result = getAPossibleType(dma.getQualifier(), isExact) and
fp.getName() = dma.getLateBoundTargetName()
}
/**
* Provides the predicate `getASourceType()` for finding all relevant source
* types for a given expression.
@@ -799,22 +820,14 @@ private module Internal {
// conflicting types (for example, `Tuple<int, string>` is considered
// compatible with `Tuple<T, T>`).
override RuntimeCallable getADynamicTarget() {
// Condition 1
result = getADynamicTargetCandidate() and
// Condition 2
forall(int i | i in [0 .. getNumberOfArguments() - 1] |
result = getADynamicTargetCandidateWithCompatibleArg(i)
)
result = this.getADynamicTarget(this.getNumberOfArguments() - 1)
}
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg(int i) {
result = getADynamicTargetCandidateWithCompatibleArg1(i) or
result = getADynamicTargetCandidateWithCompatibleArg2(i)
}
pragma[noinline]
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg1(int i) {
result = this.getADynamicTargetCandidate() and
private RuntimeCallable getADynamicTarget(int i) {
i = -1 and
result = this.getADynamicTargetCandidate()
or
result = this.getADynamicTarget(i - 1) and
exists(Type parameterType, Type argumentType |
parameterType = this.getAParameterType(result, i) and
argumentType = getAPossibleType(this.getArgument(i), _)
@@ -827,6 +840,12 @@ private module Internal {
or
reflectionOrDynamicArgEqualsParamModuloTypeParameters(argumentType, parameterType)
)
or
result = this.getADynamicTarget(i - 1) and
exists(Type parameterType, Type t | parameterType = this.getAParameterType(result, i) |
this.argumentConvConstExpr(i, t) and
t.isImplicitlyConvertibleTo(parameterType)
)
}
private Type getAParameterType(RuntimeCallable c, int i) {
@@ -840,15 +859,6 @@ private module Internal {
)
}
pragma[noinline]
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg2(int i) {
result = this.getADynamicTargetCandidate() and
exists(Type parameterType, Type t | parameterType = this.getAParameterType(result, i) |
this.argumentConvConstExpr(i, t) and
t.isImplicitlyConvertibleTo(parameterType)
)
}
pragma[noinline]
private predicate argumentConvConstExpr(int i, Type t) {
convConstantExpr(this.getArgument(i), t)
@@ -954,7 +964,7 @@ private module Internal {
*/
private predicate isReflectionOrDynamicCallArgumentWithTypeParameters(Type argType, Type paramType) {
exists(DispatchReflectionOrDynamicCall call, Parameter p, int i, int j |
p = call.getAStaticTarget().getParameter(i) and
p = call.getADynamicTargetCandidate().getParameter(i) and
(
if p.isParams()
then (

View File

@@ -654,6 +654,14 @@ class QualifiableExpr extends Expr, @qualifiable_expr {
predicate isConditional() { conditional_access(this) }
}
private Expr getAnAssignOrForeachChild() {
result = any(AssignExpr e).getLValue()
or
result = any(ForeachStmt fs).getVariableDeclTuple()
or
result = getAnAssignOrForeachChild().getAChildExpr()
}
/**
* An expression representing a tuple, for example
* `(1, 2)` on line 2 or `(var x, var y)` on line 5 in
@@ -678,10 +686,7 @@ class TupleExpr extends Expr, @tuple_expr {
Expr getAnArgument() { result = getArgument(_) }
/** Holds if this tuple is a read access. */
predicate isReadAccess() {
not exists(AssignExpr e | this = e.getLValue().getAChildExpr*()) and
not exists(ForeachStmt fs | this = fs.getVariableDeclTuple().getAChildExpr*())
}
predicate isReadAccess() { not this = getAnAssignOrForeachChild() }
}
/**

View File

@@ -0,0 +1,193 @@
/**
* Classes modelling EntityFramework and EntityFrameworkCore.
*/
import csharp
private import semmle.code.csharp.frameworks.system.data.Entity
private import semmle.code.csharp.frameworks.system.collections.Generic
private import semmle.code.csharp.frameworks.Sql
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
module DataAnnotations {
class NotMappedAttribute extends Attribute {
NotMappedAttribute() {
this
.getType()
.hasQualifiedName("System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute")
}
}
}
module EntityFramework {
/** An EF6 or EFCore namespace. */
class EFNamespace extends Namespace {
EFNamespace() {
this.getQualifiedName() = "Microsoft.EntityFrameworkCore"
or
this.getQualifiedName() = "System.Data.Entity"
}
}
/** A taint source where the data has come from a mapped property stored in the database. */
class StoredFlowSource extends DataFlow::Node {
StoredFlowSource() {
this.asExpr() = any(PropertyRead read | read.getTarget() instanceof MappedProperty)
}
}
private class EFClass extends Class {
EFClass() { this.getDeclaringNamespace() instanceof EFNamespace }
}
/** The class `Microsoft.EntityFrameworkCore.DbContext` or `System.Data.Entity.DbContext`. */
class DbContext extends EFClass {
DbContext() { this.getName() = "DbContext" }
Method getAFindMethod() {
result = this.getAMethod("Find")
or
result = this.getAMethod("FindAsync")
}
Method getAnUpdateMethod() { result = this.getAMethod("Update") }
}
/** The class `Microsoft.EntityFrameworkCore.DbSet<>` or `System.Data.Entity.DbSet<>`. */
class DbSet extends EFClass, UnboundGenericClass { DbSet() { this.getName() = "DbSet<>" } }
/** The class `Microsoft.EntityFrameworkCore.DbQuery<>` or `System.Data.Entity.DbQuery<>`. */
class DbQuery extends EFClass, UnboundGenericClass { DbQuery() { this.hasName("DbQuery<>") } }
/** A generic type or method that takes a mapped type as its type argument. */
private predicate usesMappedType(UnboundGeneric g) {
g instanceof DbSet
or
g instanceof DbQuery
or
exists(DbContext db |
g = db.getAnUpdateMethod()
or
g = db.getAFindMethod()
)
}
/** A type that is mapped to database table, or used as a query. */
class MappedType extends ValueOrRefType {
MappedType() {
not this instanceof ObjectType and
not this instanceof StringType and
not this instanceof ValueType and
(
exists(UnboundGeneric g | usesMappedType(g) |
this = g.getAConstructedGeneric().getATypeArgument()
)
or
this.getASubType() instanceof MappedType
)
}
}
/** A property that is potentially stored and retrieved from a database. */
class MappedProperty extends Property {
MappedProperty() {
this = any(MappedType t).getAMember() and
this.isPublic() and
not this.getAnAttribute() instanceof DataAnnotations::NotMappedAttribute
}
}
/** The struct `Microsoft.EntityFrameworkCore.RawSqlString`. */
class RawSqlStringStruct extends Struct, LibraryTypeDataFlow {
RawSqlStringStruct() { this.getQualifiedName() = "Microsoft.EntityFrameworkCore.RawSqlString" }
override predicate callableFlow(
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
boolean preservesValue
) {
c = this.getAConstructor() and
source.(CallableFlowSourceArg).getArgumentIndex() = 0 and
sink instanceof CallableFlowSinkReturn and
preservesValue = true
or
c = this.getAConversionTo() and
source.(CallableFlowSourceArg).getArgumentIndex() = 0 and
sink instanceof CallableFlowSinkReturn and
preservesValue = true
}
ConversionOperator getAConversionTo() {
result = this.getAMember() and
result.getTargetType() instanceof RawSqlStringStruct and
result.getSourceType() instanceof StringType
}
}
/**
* A parameter that accepts raw SQL. Parameters of type `System.FormattableString`
* are not included as they are not vulnerable to SQL injection.
*/
private class SqlParameter extends Parameter {
SqlParameter() {
this.getType() instanceof StringType and
(
exists(Callable c | this = c.getParameter(0) | c.getName().matches("%Sql"))
or
this.getName() = "sql"
) and
this.getCallable().getDeclaringType().getDeclaringNamespace().getParentNamespace*() instanceof
EFNamespace
or
this.getType() instanceof RawSqlStringStruct
or
this = any(RawSqlStringStruct s).getAConstructor().getAParameter()
or
this = any(RawSqlStringStruct s).getAConversionTo().getAParameter()
}
}
/** A call to a method in EntityFrameworkCore that executes SQL. */
class EntityFrameworkCoreSqlSink extends SqlExpr, Call {
SqlParameter sqlParam;
EntityFrameworkCoreSqlSink() { this.getTarget().getAParameter() = sqlParam }
override Expr getSql() { result = this.getArgumentForParameter(sqlParam) }
}
/** A call to `System.Data.Entity.DbSet.SqlQuery`. */
class SystemDataEntityDbSetSqlExpr extends SqlExpr, MethodCall {
SystemDataEntityDbSetSqlExpr() {
this.getTarget() = any(SystemDataEntity::DbSet dbSet).getSqlQueryMethod()
}
override Expr getSql() { result = this.getArgumentForName("sql") }
}
/** A call to a method in `System.Data.Entity.Database` that executes SQL. */
class SystemDataEntityDatabaseSqlExpr extends SqlExpr, MethodCall {
SystemDataEntityDatabaseSqlExpr() {
exists(SystemDataEntity::Database db |
this.getTarget() = db.getSqlQueryMethod() or
this.getTarget() = db.getExecuteSqlCommandMethod() or
this.getTarget() = db.getExecuteSqlCommandAsyncMethod()
)
}
override Expr getSql() { result = this.getArgumentForName("sql") }
}
/**
* A dataflow node whereby data flows from a property write to a property read
* via some database. The assumption is that all writes can flow to all reads.
*/
class MappedPropertyJumpNode extends DataFlow::NonLocalJumpNode {
MappedProperty property;
MappedPropertyJumpNode() { this.asExpr() = property.getAnAssignedValue() }
override DataFlow::Node getAJumpSuccessor(boolean preservesValue) {
result.asExpr().(PropertyRead).getTarget() = property and
preservesValue = false
}
}
}

View File

@@ -0,0 +1,113 @@
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.Sql
module NHibernate {
/** A class that is mapped to the database. */
abstract class MappedClass extends Class { }
/** The interface `NHibernamte.ISession`. */
class ISessionInterface extends Interface {
ISessionInterface() { this.hasQualifiedName("NHibernate.ISession") }
/** Gets a parameter that uses a mapped object. */
Parameter getAMappedObjectParameter() {
exists(Callable c |
result.getType() instanceof ObjectType and
c = this.getAMethod() and
result = c.getAParameter() and
result.getName() = "obj"
)
}
/** Gets a type parameter that specifies a mapped class. */
TypeParameter getAMappedObjectTp() {
exists(string methodName |
methodName = "Load"
or
methodName = "Merge"
or
methodName = "Get"
or
methodName = "Query"
|
result = this.getAMethod(methodName).(UnboundGenericMethod).getTypeParameter(0)
)
}
}
/** A mapped class that is mapped because it is used as a type argument. */
private class MappedByTypeArgument extends MappedClass {
MappedByTypeArgument() {
this = any(ISessionInterface si).getAMappedObjectTp().getASuppliedType()
}
}
/** A mapped class that is mapped because it is passed as a parameter. */
private class MappedByParam extends MappedClass {
MappedByParam() {
exists(ISessionInterface si, Expr e, MethodCall c, Parameter p |
p = si.getAMappedObjectParameter() and
e = c.getArgumentForParameter(p) and
this = e.getType()
) and
not this instanceof ObjectType and
not this.getABaseInterface*() instanceof SystemCollectionsIEnumerableInterface and
not this instanceof SystemTypeClass
}
}
/** A property that is persisted in the database. */
class MappedProperty extends Property {
MappedProperty() {
this.getDeclaringType() instanceof MappedClass and
this.isPublic()
}
}
/** A parameter that is interpreted as SQL. */
class SqlParameter extends Parameter {
SqlParameter() {
this.getType() instanceof StringType and
(this.getName() = "sql" or this.getName() = "sqlString" or this.getName() = "query") and
this
.getCallable()
.getDeclaringType()
.getDeclaringNamespace()
.getParent*()
.hasQualifiedName("", "NHibernate")
}
}
/** A call to a method in NHibernate that executes SQL. */
class NHibernateSqlSink extends SqlExpr, Call {
SqlParameter sqlParam;
NHibernateSqlSink() { this.getTarget().getAParameter() = sqlParam }
override Expr getSql() { result = this.getArgumentForParameter(sqlParam) }
}
/** A taint source where the data has come from a mapped property stored in the database. */
class StoredFlowSource extends DataFlow::Node {
StoredFlowSource() {
this.asExpr() = any(PropertyRead read | read.getTarget() instanceof MappedProperty)
}
}
/**
* A dataflow node whereby data flows from a property write to a property read
* via some database. The assumption is that all writes can flow to all reads.
*/
class MappedPropertyJumpNode extends DataFlow::NonLocalJumpNode {
MappedProperty property;
MappedPropertyJumpNode() { this.asExpr() = property.getAnAssignedValue() }
override DataFlow::Node getAJumpSuccessor(boolean preservesValue) {
result.asExpr().(PropertyRead).getTarget() = property and
preservesValue = false
}
}
}

View File

@@ -2,8 +2,9 @@
import csharp
private import semmle.code.csharp.frameworks.system.Data
private import semmle.code.csharp.frameworks.system.data.Entity
private import semmle.code.csharp.frameworks.system.data.SqlClient
private import semmle.code.csharp.frameworks.EntityFramework
private import semmle.code.csharp.frameworks.NHibernate
/** An expression containing a SQL command. */
abstract class SqlExpr extends Expr {
@@ -22,7 +23,7 @@ class CommandTextAssignmentSqlExpr extends SqlExpr, AssignExpr {
)
}
override Expr getSql() { result = getRValue() }
override Expr getSql() { result = this.getRValue() }
}
/** A construction of an `IDbCommand` object. */
@@ -34,7 +35,7 @@ class IDbCommandConstructionSqlExpr extends SqlExpr, ObjectCreation {
)
}
override Expr getSql() { result = getArgument(0) }
override Expr getSql() { result = this.getArgument(0) }
}
/** A construction of an `SqlDataAdapter` object. */
@@ -47,7 +48,7 @@ class SqlDataAdapterConstructionSqlExpr extends SqlExpr, ObjectCreation {
)
}
override Expr getSql() { result = getArgument(0) }
override Expr getSql() { result = this.getArgument(0) }
}
/** A `MySql.Data.MySqlClient.MySqlHelper` method. */
@@ -83,25 +84,3 @@ class MicrosoftSqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall {
)
}
}
/** A call to `System.Data.Entity.DbSet.SqlQuery`. */
class SystemDataEntityDbSetSqlExpr extends SqlExpr, MethodCall {
SystemDataEntityDbSetSqlExpr() {
this.getTarget() = any(SystemDataEntity::DbSet dbSet).getSqlQueryMethod()
}
override Expr getSql() { result = getArgumentForName("sql") }
}
/** A call to a method in `System.Data.Entity.Database` that executes SQL. */
class SystemDataEntityDatabaseSqlExpr extends SqlExpr, MethodCall {
SystemDataEntityDatabaseSqlExpr() {
exists(SystemDataEntity::Database db |
this.getTarget() = db.getSqlQueryMethod() or
this.getTarget() = db.getExecuteSqlCommandMethod() or
this.getTarget() = db.getExecuteSqlCommandAsyncMethod()
)
}
override Expr getSql() { result = getArgumentForName("sql") }
}

View File

@@ -56,6 +56,11 @@ class SystemArrayClass extends SystemClass {
SystemArrayClass() { this.hasName("Array") }
}
/** `System.Attribute` class. */
class SystemAttributeClass extends SystemClass {
SystemAttributeClass() { this.hasName("Attribute") }
}
/** The `System.Boolean` structure. */
class SystemBooleanStruct extends BoolType {
/** Gets the `Parse(string)` method. */

View File

@@ -5,18 +5,13 @@
import csharp
private import semmle.code.csharp.frameworks.system.data.Common
private import semmle.code.csharp.frameworks.system.data.Entity
private import semmle.code.csharp.frameworks.EntityFramework
private import semmle.code.csharp.frameworks.NHibernate
private import semmle.code.csharp.frameworks.Sql
/** A data flow source of stored user input. */
abstract class StoredFlowSource extends DataFlow::Node { }
/** An access of an Entity Framework `Entity` property that may hold stored data. */
class EntityPropertyStoredFlowSource extends StoredFlowSource {
EntityPropertyStoredFlowSource() {
this.asExpr().(PropertyAccess).getTarget() = any(SystemDataEntity::Entity e).getAProperty()
}
}
/**
* An expression that has a type of `DbRawSqlQuery`, representing the result of an Entity Framework
* SqlQuery.
@@ -37,9 +32,7 @@ class DbDataReaderStoredFlowSource extends StoredFlowSource {
}
}
/**
* An expression that accesses a method of `DbDataReader` or a sub-class.
*/
/** An expression that accesses a method of `DbDataReader` or a sub-class. */
class DbDataReaderMethodStoredFlowSource extends StoredFlowSource {
DbDataReaderMethodStoredFlowSource() {
this.asExpr().(MethodCall).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader
@@ -47,12 +40,18 @@ class DbDataReaderMethodStoredFlowSource extends StoredFlowSource {
}
}
/**
* An expression that accesses a property of `DbDataReader` or a sub-class.
*/
/** An expression that accesses a property of `DbDataReader` or a sub-class. */
class DbDataReaderPropertyStoredFlowSource extends StoredFlowSource {
DbDataReaderPropertyStoredFlowSource() {
this.asExpr().(PropertyAccess).getTarget().getDeclaringType() = any(SystemDataCommon::DbDataReader dataReader
).getASubType*()
}
}
/** A read of a mapped property. */
class ORMMappedProperty extends StoredFlowSource {
ORMMappedProperty() {
this instanceof EntityFramework::StoredFlowSource or
this instanceof NHibernate::StoredFlowSource
}
}

View File

@@ -166,4 +166,4 @@ class SplittingStressTest
;
;
}
}
}

View File

@@ -1,17 +1,27 @@
| CSharp7.cs:17:18:17:22 | access to field field | CSharp7.cs:17:9:17:11 | return Foo |
| CSharp7.cs:18:14:18:14 | 5 | CSharp7.cs:18:14:18:14 | return get_P |
| CSharp7.cs:21:16:21:20 | call to method Foo | CSharp7.cs:21:9:21:11 | return get_Q |
| CSharp7.cs:22:9:22:11 | value | CSharp7.cs:22:24:22:28 | access to parameter value |
| CSharp7.cs:22:16:22:28 | ... = ... | CSharp7.cs:22:9:22:11 | return set_Q |
| CSharp7.cs:25:39:25:43 | call to method Foo | CSharp7.cs:25:5:25:27 | return ExpressionBodiedMembers |
| CSharp7.cs:26:35:26:39 | call to method Foo | CSharp7.cs:26:6:26:28 | return ~ExpressionBodiedMembers |
| CSharp7.cs:31:19:31:19 | i | CSharp7.cs:33:16:33:16 | access to parameter i |
| CSharp7.cs:33:16:33:16 | access to parameter i | CSharp7.cs:33:16:33:20 | ... > ... |
| CSharp7.cs:33:16:33:16 | access to parameter i | CSharp7.cs:33:24:33:24 | access to parameter i |
| CSharp7.cs:33:16:33:20 | ... > ... | CSharp7.cs:33:16:33:59 | ... ? ... : ... |
| CSharp7.cs:33:16:33:59 | ... ? ... : ... | CSharp7.cs:31:9:31:13 | return Throw |
| CSharp7.cs:33:24:33:24 | access to parameter i | CSharp7.cs:33:16:33:59 | ... ? ... : ... |
| CSharp7.cs:33:28:33:59 | throw ... | CSharp7.cs:33:16:33:59 | ... ? ... : ... |
| CSharp7.cs:41:13:41:21 | "tainted" | CSharp7.cs:39:23:39:23 | return (out/ref) F |
| CSharp7.cs:41:13:41:21 | "tainted" | CSharp7.cs:41:9:41:21 | SSA def(x) |
| CSharp7.cs:44:19:44:19 | x | CSharp7.cs:46:13:46:13 | access to parameter x |
| CSharp7.cs:46:13:46:13 | access to parameter x | CSharp7.cs:44:33:44:33 | return (out/ref) G |
| CSharp7.cs:46:13:46:13 | access to parameter x | CSharp7.cs:46:9:46:13 | SSA def(y) |
| CSharp7.cs:51:22:51:23 | SSA def(t1) | CSharp7.cs:53:18:53:19 | access to local variable t1 |
| CSharp7.cs:52:19:52:20 | SSA def(t2) | CSharp7.cs:56:14:56:15 | access to local variable t2 |
| CSharp7.cs:54:15:54:16 | SSA def(t1) | CSharp7.cs:55:14:55:15 | access to local variable t1 |
| CSharp7.cs:57:30:57:31 | SSA def(t4) | CSharp7.cs:58:18:58:19 | access to local variable t4 |
| CSharp7.cs:66:16:66:21 | (..., ...) | CSharp7.cs:64:16:64:16 | return F |
| CSharp7.cs:66:17:66:17 | 1 | CSharp7.cs:66:16:66:21 | (..., ...) |
| CSharp7.cs:66:20:66:20 | 2 | CSharp7.cs:66:16:66:21 | (..., ...) |
| CSharp7.cs:72:13:72:19 | SSA def(z) | CSharp7.cs:75:16:75:16 | access to local variable z |
@@ -39,6 +49,7 @@
| CSharp7.cs:79:27:79:27 | access to local variable x | CSharp7.cs:79:22:79:28 | (..., ...) |
| CSharp7.cs:82:21:82:21 | x | CSharp7.cs:84:20:84:20 | access to parameter x |
| CSharp7.cs:84:16:84:24 | (..., ...) | CSharp7.cs:84:16:84:26 | access to field a |
| CSharp7.cs:84:16:84:26 | access to field a | CSharp7.cs:82:12:82:12 | return I |
| CSharp7.cs:84:20:84:20 | access to parameter x | CSharp7.cs:84:16:84:24 | (..., ...) |
| CSharp7.cs:84:23:84:23 | 2 | CSharp7.cs:84:16:84:24 | (..., ...) |
| CSharp7.cs:89:13:89:34 | SSA def(t1) | CSharp7.cs:90:28:90:29 | access to local variable t1 |
@@ -86,30 +97,47 @@
| CSharp7.cs:123:28:123:36 | "DefUse3" | CSharp7.cs:123:22:123:36 | ... = ... |
| CSharp7.cs:131:20:131:20 | x | CSharp7.cs:131:32:131:32 | access to parameter x |
| CSharp7.cs:131:32:131:32 | access to parameter x | CSharp7.cs:131:32:131:36 | ... + ... |
| CSharp7.cs:131:32:131:36 | ... + ... | CSharp7.cs:131:9:131:39 | return f1 |
| CSharp7.cs:131:36:131:36 | 1 | CSharp7.cs:131:32:131:36 | ... + ... |
| CSharp7.cs:133:22:133:22 | t | CSharp7.cs:133:39:133:39 | access to parameter t |
| CSharp7.cs:133:39:133:39 | access to parameter t | CSharp7.cs:133:9:133:42 | return f2 |
| CSharp7.cs:137:21:137:21 | 2 | CSharp7.cs:137:9:137:22 | return f3 |
| CSharp7.cs:139:29:139:29 | x | CSharp7.cs:139:34:139:34 | access to parameter x |
| CSharp7.cs:139:34:139:34 | access to parameter x | CSharp7.cs:139:34:139:38 | ... + ... |
| CSharp7.cs:139:34:139:38 | ... + ... | CSharp7.cs:139:29:139:38 | return (...) => ... |
| CSharp7.cs:139:38:139:38 | 1 | CSharp7.cs:139:34:139:38 | ... + ... |
| CSharp7.cs:141:20:141:20 | x | CSharp7.cs:141:26:141:26 | access to parameter x |
| CSharp7.cs:141:26:141:26 | access to parameter x | CSharp7.cs:141:26:141:30 | ... > ... |
| CSharp7.cs:141:26:141:26 | access to parameter x | CSharp7.cs:141:41:141:41 | access to parameter x |
| CSharp7.cs:141:26:141:30 | ... > ... | CSharp7.cs:141:26:141:50 | ... ? ... : ... |
| CSharp7.cs:141:26:141:50 | ... ? ... : ... | CSharp7.cs:141:9:141:51 | return f6 |
| CSharp7.cs:141:34:141:34 | 1 | CSharp7.cs:141:34:141:46 | ... + ... |
| CSharp7.cs:141:34:141:46 | ... + ... | CSharp7.cs:141:26:141:50 | ... ? ... : ... |
| CSharp7.cs:141:38:141:46 | call to local function f7 | CSharp7.cs:141:34:141:46 | ... + ... |
| CSharp7.cs:141:50:141:50 | 0 | CSharp7.cs:141:26:141:50 | ... ? ... : ... |
| CSharp7.cs:143:20:143:20 | x | CSharp7.cs:143:29:143:29 | access to parameter x |
| CSharp7.cs:143:26:143:30 | call to local function f6 | CSharp7.cs:143:9:143:31 | return f7 |
| CSharp7.cs:147:24:147:24 | x | CSharp7.cs:147:33:147:33 | access to parameter x |
| CSharp7.cs:147:30:147:34 | call to local function f7 | CSharp7.cs:147:13:147:35 | return f9 |
| CSharp7.cs:148:20:148:24 | call to local function f9 | CSharp7.cs:145:9:149:9 | return f8 |
| CSharp7.cs:152:25:152:25 | 0 | CSharp7.cs:152:13:152:26 | return f9 |
| CSharp7.cs:155:16:155:20 | call to local function f1 | CSharp7.cs:129:9:129:12 | return Main |
| CSharp7.cs:160:23:160:23 | 1 | CSharp7.cs:160:9:160:24 | return f |
| CSharp7.cs:161:18:161:18 | t | CSharp7.cs:161:24:161:24 | access to parameter t |
| CSharp7.cs:161:24:161:24 | access to parameter t | CSharp7.cs:161:9:161:25 | return g |
| CSharp7.cs:163:26:163:26 | u | CSharp7.cs:167:22:167:22 | access to parameter u |
| CSharp7.cs:165:25:165:30 | call to local function f | CSharp7.cs:165:13:165:31 | return f2 |
| CSharp7.cs:167:20:167:23 | call to local function g | CSharp7.cs:163:9:168:9 | return h |
| CSharp7.cs:176:16:176:30 | SSA def(src) | CSharp7.cs:181:23:181:25 | access to local variable src |
| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:176:16:176:30 | SSA def(src) |
| CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:33:177:33 | access to parameter s |
| CSharp7.cs:177:31:177:34 | call to local function g | CSharp7.cs:177:31:177:39 | ... + ... |
| CSharp7.cs:177:31:177:39 | ... + ... | CSharp7.cs:177:9:177:40 | return f |
| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... |
| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:31:178:31 | access to parameter s |
| CSharp7.cs:178:31:178:31 | access to parameter s | CSharp7.cs:178:9:178:32 | return g |
| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:37:179:37 | access to parameter s |
| CSharp7.cs:179:37:179:37 | access to parameter s | CSharp7.cs:179:9:179:40 | return h |
| CSharp7.cs:181:23:181:25 | access to local variable src | CSharp7.cs:182:23:182:25 | access to local variable src |
| CSharp7.cs:182:23:182:25 | access to local variable src | CSharp7.cs:183:23:183:25 | access to local variable src |
| CSharp7.cs:191:13:191:18 | SSA def(v1) | CSharp7.cs:192:26:192:27 | access to local variable v1 |
@@ -128,7 +156,11 @@
| CSharp7.cs:199:33:199:34 | access to local variable r1 | CSharp7.cs:200:16:200:17 | access to local variable r1 |
| CSharp7.cs:203:24:203:24 | p | CSharp7.cs:206:20:206:20 | access to parameter p |
| CSharp7.cs:205:28:205:28 | q | CSharp7.cs:205:44:205:44 | access to parameter q |
| CSharp7.cs:205:40:205:44 | ref ... | CSharp7.cs:205:9:205:47 | return F3 |
| CSharp7.cs:206:16:206:20 | ref ... | CSharp7.cs:203:13:203:14 | return F2 |
| CSharp7.cs:216:13:216:17 | false | CSharp7.cs:214:30:214:30 | return (out/ref) f |
| CSharp7.cs:216:13:216:17 | false | CSharp7.cs:216:9:216:17 | SSA def(x) |
| CSharp7.cs:217:16:217:23 | (..., ...) | CSharp7.cs:214:19:214:19 | return f |
| CSharp7.cs:217:17:217:17 | 0 | CSharp7.cs:217:16:217:23 | (..., ...) |
| CSharp7.cs:217:20:217:22 | 0 | CSharp7.cs:217:16:217:23 | (..., ...) |
| CSharp7.cs:233:16:233:23 | SSA def(o) | CSharp7.cs:234:13:234:13 | access to local variable o |
@@ -179,6 +211,7 @@
| CSharp7.cs:284:20:284:62 | call to method Select | CSharp7.cs:284:13:284:62 | SSA def(list) |
| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item |
| CSharp7.cs:284:32:284:61 | [implicit call] (...) => ... | CSharp7.cs:284:20:284:62 | call to method Select |
| CSharp7.cs:284:40:284:61 | (..., ...) | CSharp7.cs:284:32:284:61 | return (...) => ... |
| CSharp7.cs:284:41:284:44 | access to parameter item | CSharp7.cs:284:51:284:54 | access to parameter item |
| CSharp7.cs:284:41:284:48 | access to property Key | CSharp7.cs:284:40:284:61 | (..., ...) |
| CSharp7.cs:284:51:284:54 | access to parameter item | CSharp7.cs:284:51:284:60 | access to property Value |

View File

@@ -1,3 +1,4 @@
| CSharp7.cs:41:13:41:21 | "tainted" | CSharp7.cs:39:23:39:23 | return (out/ref) F |
| CSharp7.cs:41:13:41:21 | "tainted" | CSharp7.cs:41:9:41:21 | SSA def(x) |
| CSharp7.cs:79:23:79:24 | "" | CSharp7.cs:79:22:79:28 | (..., ...) |
| CSharp7.cs:89:19:89:27 | "tainted" | CSharp7.cs:89:13:89:34 | SSA def(t1) |
@@ -29,6 +30,7 @@
| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:181:23:181:25 | access to local variable src |
| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:182:23:182:25 | access to local variable src |
| CSharp7.cs:176:22:176:30 | "tainted" | CSharp7.cs:183:23:183:25 | access to local variable src |
| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:9:177:40 | return f |
| CSharp7.cs:177:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... |
| CSharp7.cs:236:33:236:36 | "int " | CSharp7.cs:236:31:236:41 | $"..." |
| CSharp7.cs:240:33:240:39 | "string " | CSharp7.cs:240:31:240:44 | $"..." |

View File

@@ -137,7 +137,8 @@ edges
| GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) | GlobalDataFlow.cs:153:15:153:19 | access to local variable sink7 |
| GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) | GlobalDataFlow.cs:156:15:156:19 | access to local variable sink8 |
| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" | GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:175:29:175:48 | return (...) => ... | GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" | GlobalDataFlow.cs:175:29:175:48 | return (...) => ... |
| GlobalDataFlow.cs:176:21:176:26 | delegate call | GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 |
| GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> | GlobalDataFlow.cs:186:15:186:20 | access to local variable sink10 |
| GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | GlobalDataFlow.cs:194:15:194:20 | access to local variable sink19 |
@@ -153,10 +154,13 @@ edges
| GlobalDataFlow.cs:251:26:251:35 | sinkParam5 | GlobalDataFlow.cs:253:15:253:24 | access to parameter sinkParam5 |
| GlobalDataFlow.cs:256:26:256:35 | sinkParam6 | GlobalDataFlow.cs:258:15:258:24 | access to parameter sinkParam6 |
| GlobalDataFlow.cs:261:26:261:35 | sinkParam7 | GlobalDataFlow.cs:263:15:263:24 | access to parameter sinkParam7 |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:149:21:149:25 | call to method Out |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" | GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) |
| GlobalDataFlow.cs:311:12:311:14 | return Out | GlobalDataFlow.cs:149:21:149:25 | call to method Out |
| GlobalDataFlow.cs:311:12:311:14 | return Out | GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:311:12:311:14 | return Out |
| GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut | GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" | GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut |
| GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef | GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef |
| GlobalDataFlow.cs:354:41:354:41 | x | GlobalDataFlow.cs:356:11:356:11 | access to parameter x |
| GlobalDataFlow.cs:354:41:354:41 | x | GlobalDataFlow.cs:356:11:356:11 | access to parameter x |
| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | GlobalDataFlow.cs:53:15:53:15 | x |
@@ -167,11 +171,12 @@ edges
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:56:37:56:37 | x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:251:26:251:35 | sinkParam5 |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:256:26:256:35 | sinkParam6 |
| GlobalDataFlow.cs:373:19:373:30 | return TaintedParam | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:373:19:373:30 | return TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 |
| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:399:9:399:11 | value | GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty |
| GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty |
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted |
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted |
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x |
@@ -270,6 +275,7 @@ nodes
| GlobalDataFlow.cs:156:15:156:19 | access to local variable sink8 |
| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 |
| GlobalDataFlow.cs:175:29:175:48 | return (...) => ... |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" |
| GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 |
@@ -295,8 +301,11 @@ nodes
| GlobalDataFlow.cs:258:15:258:24 | access to parameter sinkParam6 |
| GlobalDataFlow.cs:261:26:261:35 | sinkParam7 |
| GlobalDataFlow.cs:263:15:263:24 | access to parameter sinkParam7 |
| GlobalDataFlow.cs:311:12:311:14 | return Out |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" |
| GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" |
| GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" |
| GlobalDataFlow.cs:354:41:354:41 | x |
| GlobalDataFlow.cs:354:41:354:41 | x |
@@ -308,11 +317,12 @@ nodes
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:373:19:373:30 | return TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted |
| GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 |
| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 |
| GlobalDataFlow.cs:399:9:399:11 | value |
| GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 |
| GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" |
| Splitting.cs:3:28:3:34 | tainted |
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return |

View File

@@ -161,7 +161,8 @@ edges
| GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) | GlobalDataFlow.cs:156:15:156:19 | access to local variable sink8 |
| GlobalDataFlow.cs:157:22:157:31 | call to method OutYield | GlobalDataFlow.cs:158:15:158:20 | access to local variable sink12 |
| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam | GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" | GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:175:29:175:48 | return (...) => ... | GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" | GlobalDataFlow.cs:175:29:175:48 | return (...) => ... |
| GlobalDataFlow.cs:176:21:176:26 | delegate call | GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 |
| GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> | GlobalDataFlow.cs:186:15:186:20 | access to local variable sink10 |
| GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty | GlobalDataFlow.cs:194:15:194:20 | access to local variable sink19 |
@@ -195,11 +196,15 @@ edges
| GlobalDataFlow.cs:287:31:287:40 | sinkParam8 | GlobalDataFlow.cs:289:15:289:24 | access to parameter sinkParam8 |
| GlobalDataFlow.cs:293:32:293:41 | sinkParam9 | GlobalDataFlow.cs:295:15:295:24 | access to parameter sinkParam9 |
| GlobalDataFlow.cs:299:32:299:42 | sinkParam11 | GlobalDataFlow.cs:301:15:301:25 | access to parameter sinkParam11 |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:149:21:149:25 | call to method Out |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" | GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) |
| GlobalDataFlow.cs:329:22:329:35 | "taint source" | GlobalDataFlow.cs:157:22:157:31 | call to method OutYield |
| GlobalDataFlow.cs:311:12:311:14 | return Out | GlobalDataFlow.cs:149:21:149:25 | call to method Out |
| GlobalDataFlow.cs:311:12:311:14 | return Out | GlobalDataFlow.cs:185:39:185:41 | [implicit call] delegate creation of type Func<String> |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" | GlobalDataFlow.cs:311:12:311:14 | return Out |
| GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut | GlobalDataFlow.cs:152:20:152:24 | SSA def(sink7) |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" | GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut |
| GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef | GlobalDataFlow.cs:155:20:155:24 | SSA def(sink8) |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" | GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef |
| GlobalDataFlow.cs:326:25:326:32 | yield return OutYield | GlobalDataFlow.cs:157:22:157:31 | call to method OutYield |
| GlobalDataFlow.cs:329:22:329:35 | "taint source" | GlobalDataFlow.cs:326:25:326:32 | yield return OutYield |
| GlobalDataFlow.cs:354:41:354:41 | x | GlobalDataFlow.cs:356:11:356:11 | access to parameter x |
| GlobalDataFlow.cs:354:41:354:41 | x | GlobalDataFlow.cs:356:11:356:11 | access to parameter x |
| GlobalDataFlow.cs:356:11:356:11 | access to parameter x | GlobalDataFlow.cs:53:15:53:15 | x |
@@ -210,11 +215,12 @@ edges
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:56:37:56:37 | x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:251:26:251:35 | sinkParam5 |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x | GlobalDataFlow.cs:256:26:256:35 | sinkParam6 |
| GlobalDataFlow.cs:373:19:373:30 | return TaintedParam | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:373:19:373:30 | return TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 |
| GlobalDataFlow.cs:373:39:373:45 | tainted | GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 |
| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 | GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:399:9:399:11 | value | GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty |
| GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty | GlobalDataFlow.cs:193:22:193:32 | access to property OutProperty |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" | GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty |
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:8:24:8:30 | [b (line 3): false] access to parameter tainted |
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:8:24:8:30 | [b (line 3): true] access to parameter tainted |
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return | Splitting.cs:9:15:9:15 | [b (line 3): false] access to local variable x |
@@ -337,6 +343,7 @@ nodes
| GlobalDataFlow.cs:158:15:158:20 | access to local variable sink12 |
| GlobalDataFlow.cs:159:22:159:43 | call to method TaintedParam |
| GlobalDataFlow.cs:160:15:160:20 | access to local variable sink23 |
| GlobalDataFlow.cs:175:29:175:48 | return (...) => ... |
| GlobalDataFlow.cs:175:35:175:48 | "taint source" |
| GlobalDataFlow.cs:176:21:176:26 | delegate call |
| GlobalDataFlow.cs:177:15:177:19 | access to local variable sink9 |
@@ -382,9 +389,13 @@ nodes
| GlobalDataFlow.cs:295:15:295:24 | access to parameter sinkParam9 |
| GlobalDataFlow.cs:299:32:299:42 | sinkParam11 |
| GlobalDataFlow.cs:301:15:301:25 | access to parameter sinkParam11 |
| GlobalDataFlow.cs:311:12:311:14 | return Out |
| GlobalDataFlow.cs:313:16:313:29 | "taint source" |
| GlobalDataFlow.cs:316:28:316:28 | return (out/ref) OutOut |
| GlobalDataFlow.cs:318:13:318:26 | "taint source" |
| GlobalDataFlow.cs:321:28:321:28 | return (out/ref) OutRef |
| GlobalDataFlow.cs:323:13:323:26 | "taint source" |
| GlobalDataFlow.cs:326:25:326:32 | yield return OutYield |
| GlobalDataFlow.cs:329:22:329:35 | "taint source" |
| GlobalDataFlow.cs:354:41:354:41 | x |
| GlobalDataFlow.cs:354:41:354:41 | x |
@@ -396,11 +407,12 @@ nodes
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:370:11:370:11 | access to parameter x |
| GlobalDataFlow.cs:373:19:373:30 | return TaintedParam |
| GlobalDataFlow.cs:373:39:373:45 | tainted |
| GlobalDataFlow.cs:376:15:376:20 | access to local variable sink11 |
| GlobalDataFlow.cs:377:16:377:21 | access to local variable sink11 |
| GlobalDataFlow.cs:399:9:399:11 | value |
| GlobalDataFlow.cs:399:41:399:46 | access to local variable sink20 |
| GlobalDataFlow.cs:410:9:410:11 | return get_OutProperty |
| GlobalDataFlow.cs:410:22:410:35 | "taint source" |
| Splitting.cs:3:28:3:34 | tainted |
| Splitting.cs:8:17:8:31 | [b (line 3): false] call to method Return |

View File

@@ -14,6 +14,11 @@
| Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) |
| Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) |
| Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i |
| LocalDataFlow.cs:16:55:16:58 | null | LocalDataFlow.cs:16:42:16:44 | return get_Item |
| LocalDataFlow.cs:18:63:18:66 | null | LocalDataFlow.cs:18:50:18:52 | return get_QueryString |
| LocalDataFlow.cs:20:59:20:62 | null | LocalDataFlow.cs:20:46:20:48 | return get_Headers |
| LocalDataFlow.cs:22:45:22:48 | null | LocalDataFlow.cs:22:32:22:34 | return get_RawUrl |
| LocalDataFlow.cs:24:39:24:42 | null | LocalDataFlow.cs:24:26:24:28 | return get_Url |
| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b |
| LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 |
| LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) |
@@ -107,12 +112,14 @@
| LocalDataFlow.cs:136:22:136:55 | call to method First | LocalDataFlow.cs:136:13:136:55 | SSA def(sink14) |
| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x |
| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value |
| LocalDataFlow.cs:136:40:136:54 | ... != ... | LocalDataFlow.cs:136:35:136:54 | return (...) => ... |
| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 |
| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 |
| LocalDataFlow.cs:140:20:140:55 | (...) ... | LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) |
| LocalDataFlow.cs:140:20:140:55 | call to method First | LocalDataFlow.cs:140:20:140:55 | (...) ... |
| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x |
| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value |
| LocalDataFlow.cs:140:40:140:54 | ... != ... | LocalDataFlow.cs:140:35:140:54 | return (...) => ... |
| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 |
| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 |
| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) |
@@ -310,6 +317,7 @@
| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 |
| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy<String> | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) |
| LocalDataFlow.cs:303:39:303:58 | [implicit call] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy<String> |
| LocalDataFlow.cs:303:45:303:58 | "taint source" | LocalDataFlow.cs:303:39:303:58 | return (...) => ... |
| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 |
| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 |
| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value |
@@ -324,6 +332,7 @@
| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 |
| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy<String> | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) |
| LocalDataFlow.cs:313:38:313:45 | [implicit call] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy<String> |
| LocalDataFlow.cs:313:44:313:45 | "" | LocalDataFlow.cs:313:38:313:45 | return (...) => ... |
| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 |
| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value |
@@ -418,6 +427,7 @@
| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 |
| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) |
| LocalDataFlow.cs:391:31:391:50 | [implicit call] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run |
| LocalDataFlow.cs:391:37:391:50 | "taint source" | LocalDataFlow.cs:391:31:391:50 | return (...) => ... |
| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 |
| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 |
| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) |
@@ -425,6 +435,7 @@
| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 |
| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) |
| LocalDataFlow.cs:397:34:397:41 | [implicit call] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run |
| LocalDataFlow.cs:397:40:397:41 | "" | LocalDataFlow.cs:397:34:397:41 | return (...) => ... |
| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 |
| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) |
@@ -453,6 +464,9 @@
| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 |
| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) |
| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 |
| LocalDataFlow.cs:447:37:447:38 | "" | LocalDataFlow.cs:447:12:447:24 | return TaintedMethod |
| LocalDataFlow.cs:449:40:449:41 | "" | LocalDataFlow.cs:449:12:449:27 | return NonTaintedMethod |
| LocalDataFlow.cs:458:41:458:45 | access to field anInt | LocalDataFlow.cs:458:28:458:30 | return get_AnInt |
| LocalDataFlow.cs:458:50:458:52 | value | LocalDataFlow.cs:458:64:458:68 | access to parameter value |
| LocalDataFlow.cs:464:41:464:47 | tainted | LocalDataFlow.cs:466:15:466:21 | access to parameter tainted |
| LocalDataFlow.cs:469:44:469:53 | nonTainted | LocalDataFlow.cs:471:15:471:24 | access to parameter nonTainted |
@@ -624,8 +638,10 @@
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:146:13:146:13 | (...) ... |
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:149:17:149:17 | access to parameter t |
| SSA.cs:147:13:147:26 | SSA def(t) | SSA.cs:144:17:144:26 | SSA phi(t) |
| SSA.cs:147:17:147:26 | default(...) | SSA.cs:144:34:144:34 | return (out/ref) Certain |
| SSA.cs:147:17:147:26 | default(...) | SSA.cs:147:13:147:26 | SSA def(t) |
| SSA.cs:149:13:149:17 | SSA def(t) | SSA.cs:144:17:144:26 | SSA phi(t) |
| SSA.cs:149:17:149:17 | access to parameter t | SSA.cs:144:34:144:34 | return (out/ref) Certain |
| SSA.cs:149:17:149:17 | access to parameter t | SSA.cs:149:13:149:17 | SSA def(t) |
| SSA.cs:152:36:152:36 | t | SSA.cs:154:13:154:13 | access to parameter t |
| SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:152:17:152:28 | SSA phi(t) |

View File

@@ -14,6 +14,11 @@
| Capture.cs:58:21:58:21 | 1 | Capture.cs:58:17:58:21 | SSA def(i) |
| Capture.cs:61:17:61:17 | 1 | Capture.cs:61:13:61:17 | SSA def(i) |
| Capture.cs:63:9:63:17 | SSA call def(i) | Capture.cs:64:13:64:13 | access to local variable i |
| LocalDataFlow.cs:16:55:16:58 | null | LocalDataFlow.cs:16:42:16:44 | return get_Item |
| LocalDataFlow.cs:18:63:18:66 | null | LocalDataFlow.cs:18:50:18:52 | return get_QueryString |
| LocalDataFlow.cs:20:59:20:62 | null | LocalDataFlow.cs:20:46:20:48 | return get_Headers |
| LocalDataFlow.cs:22:45:22:48 | null | LocalDataFlow.cs:22:32:22:34 | return get_RawUrl |
| LocalDataFlow.cs:24:39:24:42 | null | LocalDataFlow.cs:24:26:24:28 | return get_Url |
| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:96:21:96:21 | access to parameter b |
| LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) | LocalDataFlow.cs:53:15:53:19 | access to local variable sink0 |
| LocalDataFlow.cs:52:21:52:34 | "taint source" | LocalDataFlow.cs:52:13:52:34 | SSA def(sink0) |
@@ -131,6 +136,7 @@
| LocalDataFlow.cs:136:35:136:35 | x | LocalDataFlow.cs:136:40:136:40 | access to parameter x |
| LocalDataFlow.cs:136:40:136:40 | access to parameter x | LocalDataFlow.cs:136:40:136:46 | access to property Value |
| LocalDataFlow.cs:136:40:136:46 | access to property Value | LocalDataFlow.cs:136:40:136:54 | ... != ... |
| LocalDataFlow.cs:136:40:136:54 | ... != ... | LocalDataFlow.cs:136:35:136:54 | return (...) => ... |
| LocalDataFlow.cs:140:9:140:55 | SSA def(nonSink3) | LocalDataFlow.cs:206:33:206:40 | access to local variable nonSink3 |
| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:140:20:140:55 | call to method First |
| LocalDataFlow.cs:140:20:140:27 | access to local variable nonSink1 | LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 |
@@ -139,6 +145,7 @@
| LocalDataFlow.cs:140:35:140:35 | x | LocalDataFlow.cs:140:40:140:40 | access to parameter x |
| LocalDataFlow.cs:140:40:140:40 | access to parameter x | LocalDataFlow.cs:140:40:140:46 | access to property Value |
| LocalDataFlow.cs:140:40:140:46 | access to property Value | LocalDataFlow.cs:140:40:140:54 | ... != ... |
| LocalDataFlow.cs:140:40:140:54 | ... != ... | LocalDataFlow.cs:140:35:140:54 | return (...) => ... |
| LocalDataFlow.cs:141:15:141:22 | access to local variable nonSink1 | LocalDataFlow.cs:214:20:214:27 | access to local variable nonSink1 |
| LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) | LocalDataFlow.cs:145:15:145:20 | access to local variable sink15 |
| LocalDataFlow.cs:144:22:144:39 | call to method Parse | LocalDataFlow.cs:144:13:144:39 | SSA def(sink15) |
@@ -426,6 +433,7 @@
| LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) | LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 |
| LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy<String> | LocalDataFlow.cs:303:13:303:59 | SSA def(sink42) |
| LocalDataFlow.cs:303:39:303:58 | [implicit call] (...) => ... | LocalDataFlow.cs:303:22:303:59 | object creation of type Lazy<String> |
| LocalDataFlow.cs:303:45:303:58 | "taint source" | LocalDataFlow.cs:303:39:303:58 | return (...) => ... |
| LocalDataFlow.cs:304:15:304:20 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 |
| LocalDataFlow.cs:305:13:305:33 | SSA def(sink43) | LocalDataFlow.cs:306:15:306:20 | access to local variable sink43 |
| LocalDataFlow.cs:305:22:305:27 | access to local variable sink42 | LocalDataFlow.cs:305:22:305:33 | access to property Value |
@@ -440,6 +448,7 @@
| LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) | LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 |
| LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy<String> | LocalDataFlow.cs:313:9:313:46 | SSA def(nonSink12) |
| LocalDataFlow.cs:313:38:313:45 | [implicit call] (...) => ... | LocalDataFlow.cs:313:21:313:46 | object creation of type Lazy<String> |
| LocalDataFlow.cs:313:44:313:45 | "" | LocalDataFlow.cs:313:38:313:45 | return (...) => ... |
| LocalDataFlow.cs:314:15:314:23 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 |
| LocalDataFlow.cs:315:9:315:34 | SSA def(nonSink0) | LocalDataFlow.cs:316:15:316:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:315:20:315:28 | access to local variable nonSink12 | LocalDataFlow.cs:315:20:315:34 | access to property Value |
@@ -556,6 +565,7 @@
| LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) | LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 |
| LocalDataFlow.cs:391:22:391:51 | call to method Run | LocalDataFlow.cs:391:13:391:51 | SSA def(sink67) |
| LocalDataFlow.cs:391:31:391:50 | [implicit call] (...) => ... | LocalDataFlow.cs:391:22:391:51 | call to method Run |
| LocalDataFlow.cs:391:37:391:50 | "taint source" | LocalDataFlow.cs:391:31:391:50 | return (...) => ... |
| LocalDataFlow.cs:392:15:392:20 | access to local variable sink67 | LocalDataFlow.cs:393:28:393:33 | access to local variable sink67 |
| LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) | LocalDataFlow.cs:394:15:394:20 | access to local variable sink68 |
| LocalDataFlow.cs:393:22:393:33 | await ... | LocalDataFlow.cs:393:13:393:33 | SSA def(sink68) |
@@ -563,6 +573,7 @@
| LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) | LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 |
| LocalDataFlow.cs:397:25:397:42 | call to method Run | LocalDataFlow.cs:397:13:397:42 | SSA def(nonSink21) |
| LocalDataFlow.cs:397:34:397:41 | [implicit call] (...) => ... | LocalDataFlow.cs:397:25:397:42 | call to method Run |
| LocalDataFlow.cs:397:40:397:41 | "" | LocalDataFlow.cs:397:34:397:41 | return (...) => ... |
| LocalDataFlow.cs:398:15:398:23 | access to local variable nonSink21 | LocalDataFlow.cs:399:26:399:34 | access to local variable nonSink21 |
| LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) | LocalDataFlow.cs:400:15:400:22 | access to local variable nonSink0 |
| LocalDataFlow.cs:399:20:399:34 | await ... | LocalDataFlow.cs:399:9:399:34 | SSA def(nonSink0) |
@@ -595,6 +606,9 @@
| LocalDataFlow.cs:429:18:429:30 | SSA def(sink72) | LocalDataFlow.cs:430:23:430:28 | access to local variable sink72 |
| LocalDataFlow.cs:435:17:435:24 | access to local variable nonSink0 | LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) |
| LocalDataFlow.cs:437:18:437:33 | SSA def(nonSink17) | LocalDataFlow.cs:438:23:438:31 | access to local variable nonSink17 |
| LocalDataFlow.cs:447:37:447:38 | "" | LocalDataFlow.cs:447:12:447:24 | return TaintedMethod |
| LocalDataFlow.cs:449:40:449:41 | "" | LocalDataFlow.cs:449:12:449:27 | return NonTaintedMethod |
| LocalDataFlow.cs:458:41:458:45 | access to field anInt | LocalDataFlow.cs:458:28:458:30 | return get_AnInt |
| LocalDataFlow.cs:458:50:458:52 | value | LocalDataFlow.cs:458:64:458:68 | access to parameter value |
| LocalDataFlow.cs:464:41:464:47 | tainted | LocalDataFlow.cs:466:15:466:21 | access to parameter tainted |
| LocalDataFlow.cs:469:44:469:53 | nonTainted | LocalDataFlow.cs:471:15:471:24 | access to parameter nonTainted |
@@ -781,8 +795,10 @@
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:146:13:146:13 | (...) ... |
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:149:17:149:17 | access to parameter t |
| SSA.cs:147:13:147:26 | SSA def(t) | SSA.cs:144:17:144:26 | SSA phi(t) |
| SSA.cs:147:17:147:26 | default(...) | SSA.cs:144:34:144:34 | return (out/ref) Certain |
| SSA.cs:147:17:147:26 | default(...) | SSA.cs:147:13:147:26 | SSA def(t) |
| SSA.cs:149:13:149:17 | SSA def(t) | SSA.cs:144:17:144:26 | SSA phi(t) |
| SSA.cs:149:17:149:17 | access to parameter t | SSA.cs:144:34:144:34 | return (out/ref) Certain |
| SSA.cs:149:17:149:17 | access to parameter t | SSA.cs:149:13:149:17 | SSA def(t) |
| SSA.cs:152:36:152:36 | t | SSA.cs:154:13:154:13 | access to parameter t |
| SSA.cs:154:13:154:13 | (...) ... | SSA.cs:154:13:154:21 | ... == ... |

View File

@@ -0,0 +1,7 @@
| EntityFramework.cs:52:18:52:24 | access to property Name | EntityFramework.cs:47:34:47:42 | "tainted" |
| EntityFramework.cs:53:18:53:34 | access to property Name | EntityFramework.cs:47:34:47:42 | "tainted" |
| EntityFrameworkCore.cs:50:18:50:28 | access to local variable taintSource | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:51:18:51:46 | (...) ... | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:52:18:52:42 | (...) ... | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:60:18:60:24 | access to property Name | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:61:18:61:34 | access to property Name | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |

View File

@@ -0,0 +1,16 @@
import csharp
import semmle.code.csharp.dataflow.TaintTracking
class MyConfiguration extends TaintTracking::Configuration {
MyConfiguration() { this = "EntityFramework dataflow" }
override predicate isSource(DataFlow::Node node) { node.asExpr().getValue() = "tainted" }
override predicate isSink(DataFlow::Node node) {
node.asExpr() = any(MethodCall c | c.getTarget().hasName("Sink")).getAnArgument()
}
}
from MyConfiguration config, DataFlow::Node source, DataFlow::Node sink
where config.hasFlow(source, sink)
select sink, source

View File

@@ -0,0 +1,64 @@
// semmle-extractor-options: /r:System.Data.dll /r:System.ComponentModel.Primitives.dll /r:System.ComponentModel.TypeConverter.dll ${testdir}/../../../resources/stubs/EntityFramework.cs ${testdir}/../../../resources/stubs/System.Data.cs /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
namespace EFTests
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public int Age { get; set; }
}
class MyContext : DbContext
{
DbSet<Person> person { get; set; }
void FlowSources()
{
var p = new Person();
var id = p.Id; // Remote flow source
var name = p.Name; // Remote flow source
var age = p.Age; // Not a remote flow source
}
DbCommand command;
async void SqlSinks()
{
// System.Data.Common.DbCommand.set_CommandText
command.CommandText = ""; // SqlExpr
// System.Data.SqlClient.SqlCommand.SqlCommand
new System.Data.SqlClient.SqlCommand(""); // SqlExpr
this.Database.ExecuteSqlCommand(""); // SqlExpr
await this.Database.ExecuteSqlCommandAsync(""); // SqlExpr
}
void TestDataFlow()
{
string taintSource = "tainted";
// Tainted via database, even though technically there were no reads or writes to the database in this particular case.
var p1 = new Person { Name = taintSource };
var p2 = new Person();
Sink(p2.Name); // Tainted
Sink(new Person().Name); // Tainted
p1.Age = int.Parse(taintSource);
Sink(p2.Age); // Not tainted due to NotMappedAttribute
}
void Sink(object @object)
{
}
}
}

View File

@@ -0,0 +1,71 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
namespace EFCoreTests
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public int Age { get; set; }
}
class MyContext : DbContext
{
DbSet<Person> person;
void FlowSources()
{
var p = new Person();
var id = p.Id; // Remote flow source
var name = p.Name; // Remote flow source
var age = p.Age; // Not a remote flow source
}
Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder builder;
async void SqlExprs()
{
// Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlCommand
this.Database.ExecuteSqlCommand(""); // SqlExpr
await this.Database.ExecuteSqlCommandAsync(""); // SqlExpr
// Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder.Build
builder.Build(""); // SqlExpr
// Microsoft.EntityFrameworkCore.RawSqlString
new RawSqlString(""); // SqlExpr
RawSqlString str = ""; // SqlExpr
}
void TestDataFlow()
{
var taintSource = "tainted";
var untaintedSource = "untainted";
Sink(taintSource); // Tainted
Sink(new RawSqlString(taintSource)); // Tainted
Sink((RawSqlString)taintSource); // Tainted
Sink((RawSqlString)(FormattableString)$"{taintSource}"); // Not tainted
// Tainted via database, even though technically there were no reads or writes to the database in this particular case.
var p1 = new Person { Name = taintSource };
p1.Name = untaintedSource;
var p2 = new Person();
Sink(p2.Name); // Tainted
Sink(new Person().Name); // Tainted
p1.Age = int.Parse(taintSource);
Sink(p2.Age); // Not tainted due to NotMappedAttribute
}
void Sink(object @object)
{
}
}
}

View File

@@ -0,0 +1,4 @@
| EntityFramework.cs:12:20:12:21 | Id |
| EntityFramework.cs:13:23:13:26 | Name |
| EntityFrameworkCore.cs:10:18:10:19 | Id |
| EntityFrameworkCore.cs:11:21:11:24 | Name |

View File

@@ -0,0 +1,5 @@
import csharp
import semmle.code.csharp.frameworks.EntityFramework
from EntityFramework::MappedProperty property
select property

View File

@@ -0,0 +1,11 @@
| EntityFramework.cs:36:13:36:36 | ... = ... |
| EntityFramework.cs:39:13:39:52 | object creation of type SqlCommand |
| EntityFramework.cs:41:13:41:47 | call to method ExecuteSqlCommand |
| EntityFramework.cs:42:19:42:58 | call to method ExecuteSqlCommandAsync |
| EntityFrameworkCore.cs:34:13:34:47 | call to method ExecuteSqlCommand |
| EntityFrameworkCore.cs:35:19:35:58 | call to method ExecuteSqlCommandAsync |
| EntityFrameworkCore.cs:38:13:38:29 | call to method Build |
| EntityFrameworkCore.cs:41:13:41:32 | object creation of type RawSqlString |
| EntityFrameworkCore.cs:42:32:42:33 | call to operator implicit conversion |
| EntityFrameworkCore.cs:51:18:51:46 | object creation of type RawSqlString |
| EntityFrameworkCore.cs:52:18:52:42 | call to operator implicit conversion |

View File

@@ -0,0 +1,5 @@
import csharp
import semmle.code.csharp.frameworks.Sql
from SqlExpr expr
select expr

View File

@@ -0,0 +1,8 @@
| EntityFramework.cs:26:22:26:25 | access to property Id |
| EntityFramework.cs:27:24:27:29 | access to property Name |
| EntityFramework.cs:52:18:52:24 | access to property Name |
| EntityFramework.cs:53:18:53:34 | access to property Name |
| EntityFrameworkCore.cs:24:22:24:25 | access to property Id |
| EntityFrameworkCore.cs:25:24:25:29 | access to property Name |
| EntityFrameworkCore.cs:60:18:60:24 | access to property Name |
| EntityFrameworkCore.cs:61:18:61:34 | access to property Name |

View File

@@ -0,0 +1,5 @@
import csharp
import semmle.code.csharp.security.dataflow.flowsources.Stored
from StoredFlowSource source
select source

View File

@@ -0,0 +1,2 @@
| nhibernate.cs:50:14:50:19 | access to property Name | Data flow from $@. | nhibernate.cs:45:24:45:32 | "tainted" | "tainted" |
| nhibernate.cs:55:14:55:23 | access to property Address | Data flow from $@. | nhibernate.cs:45:24:45:32 | "tainted" | "tainted" |

View File

@@ -0,0 +1,18 @@
import csharp
import semmle.code.csharp.dataflow.TaintTracking
class MyConfiguration extends TaintTracking::Configuration {
MyConfiguration() { this = "MyConfiguration" }
override predicate isSource(DataFlow::Node node) {
node.asExpr().(StringLiteral).getValue() = "tainted"
}
override predicate isSink(DataFlow::Node node) {
exists(MethodCall mc | mc.getTarget().hasName("Sink") and node.asExpr() = mc.getArgument(0))
}
}
from MyConfiguration config, DataFlow::Node source, DataFlow::Node sink
where config.hasFlow(source, sink)
select sink, "Data flow from $@.", source, source.toString()

View File

@@ -0,0 +1,2 @@
| nhibernate.cs:16:9:16:26 | object creation of type SqlString |
| nhibernate.cs:17:9:17:27 | call to method Delete |

View File

@@ -0,0 +1,5 @@
import csharp
import semmle.code.csharp.frameworks.Sql
from SqlExpr e
select e

View File

@@ -0,0 +1,6 @@
| nhibernate.cs:49:14:49:17 | access to property Id |
| nhibernate.cs:50:14:50:19 | access to property Name |
| nhibernate.cs:51:14:51:22 | access to property Address |
| nhibernate.cs:53:14:53:18 | access to property Id |
| nhibernate.cs:54:14:54:19 | access to property Age |
| nhibernate.cs:55:14:55:23 | access to property Address |

View File

@@ -0,0 +1,5 @@
import csharp
import semmle.code.csharp.security.dataflow.flowsources.Stored
from StoredFlowSource source
select source

View File

@@ -0,0 +1,62 @@
// semmle-extractor-options: /r:System.Data.dll /r:System.ComponentModel.Primitives.dll ${testdir}/../../../resources/stubs/NHibernate.cs ${testdir}/../../../resources/stubs/System.Data.cs /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll
using NHibernate;
using NHibernate.SqlCommand;
namespace NHibernateTest
{
class Test
{
ISession session;
void SqlExprs()
{
var sql = "sql";
new SqlString(sql); // SQL expression
session.Delete(sql); // SQL expression
}
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
class Person2
{
public int Id { get; set; }
public int Age { get; set; }
public string Address { get; set; }
}
void FlowSources()
{
session.Query<Person>();
session.Save(new Person2());
}
void DataFlow()
{
var p = new Person();
var p2 = new Person2();
string taint = "tainted";
p.Name = taint;
p2.Address = taint;
Sink(p.Id); // Not tainted
Sink(p.Name); // Tainted
Sink(p.Address); // Not tainted
Sink(p2.Id); // Not tainted
Sink(p2.Age); // Not tainted
Sink(p2.Address); // Tainted
}
void Sink(object sink)
{
}
}
}

View File

@@ -32,14 +32,14 @@ public class BloggingContext : DbContext
DbRawSqlQuery<Blog> blogs = Database.SqlQuery<Blog>("SELECT * FROM Blogs");
foreach (var blog in blogs)
{
// This will be a sink because it is an access of an entity property
// This will be a source because it is an access of an entity property
Console.WriteLine(blog.Name);
}
DbRawSqlQuery<string> blogNames = Database.SqlQuery<string>("SELECT Name FROM Blogs");
foreach (var blogName in blogNames)
{
// This will be a sink because it is returned from an SqlQuery
// This will be a source because it is returned from an SqlQuery
Console.WriteLine(blogName);
}
}

View File

@@ -44,7 +44,7 @@ class Program
{
if (obj2 == null)
{
obj2 = null;
obj2 = null;
}
}
}

View File

@@ -55,6 +55,6 @@ public class CommandInjectionHandler : IHttpHandler
void OnButtonClicked()
{
// BAD: Use the Roslyn APIs to dynamically evaluate C#
CSharpScript.EvaluateAsync(box1.Text);
CSharpScript.EvaluateAsync(box1.Text);
}
}

View File

@@ -5,8 +5,8 @@ nodes
| CodeInjection.cs:25:23:25:45 | access to property QueryString |
| CodeInjection.cs:31:64:31:67 | access to local variable code |
| CodeInjection.cs:42:36:42:39 | access to local variable code |
| CodeInjection.cs:58:33:58:41 | access to property Text |
| CodeInjection.cs:58:36:58:44 | access to property Text |
#select
| CodeInjection.cs:31:64:31:67 | access to local variable code | CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:31:64:31:67 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value |
| CodeInjection.cs:42:36:42:39 | access to local variable code | CodeInjection.cs:25:23:25:45 | access to property QueryString | CodeInjection.cs:42:36:42:39 | access to local variable code | $@ flows to here and is compiled as code. | CodeInjection.cs:25:23:25:45 | access to property QueryString | User-provided value |
| CodeInjection.cs:58:33:58:41 | access to property Text | CodeInjection.cs:58:33:58:41 | access to property Text | CodeInjection.cs:58:33:58:41 | access to property Text | $@ flows to here and is compiled as code. | CodeInjection.cs:58:33:58:41 | access to property Text | User-provided value |
| CodeInjection.cs:58:36:58:44 | access to property Text | CodeInjection.cs:58:36:58:44 | access to property Text | CodeInjection.cs:58:36:58:44 | access to property Text | $@ flows to here and is compiled as code. | CodeInjection.cs:58:36:58:44 | access to property Text | User-provided value |

View File

@@ -9,16 +9,16 @@ public class TaintedPathHandler : IHttpHandler
public void ProcessRequest(HttpContext ctx)
{
String path = ctx.Request.QueryString["page"];
// BAD: Uncontrolled format string.
String.Format(path, "Do not do this");
// BAD: Using an IFormatProvider.
String.Format((IFormatProvider)null, path, "Do not do this");
// GOOD: Not the format string.
String.Format("Do not do this", path);
// GOOD: Not the format string.
String.Format((IFormatProvider)null, "Do not do this", path);
}
@@ -27,7 +27,7 @@ public class TaintedPathHandler : IHttpHandler
void OnButtonClicked()
{
// BAD: Uncontrolled format string.
String.Format(box1.Text, "Do not do this");
// BAD: Uncontrolled format string.
String.Format(box1.Text, "Do not do this");
}
}

View File

@@ -8,11 +8,11 @@ nodes
| UncontrolledFormatString.cs:17:46:17:49 | access to local variable path |
| UncontrolledFormatString.cs:20:23:20:38 | "Do not do this" |
| UncontrolledFormatString.cs:23:46:23:61 | "Do not do this" |
| UncontrolledFormatString.cs:31:20:31:28 | access to property Text |
| UncontrolledFormatString.cs:31:23:31:31 | access to property Text |
| UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString |
| UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format |
#select
| UncontrolledFormatString.cs:14:23:14:26 | access to local variable path | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | UncontrolledFormatString.cs:14:23:14:26 | access to local variable path | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | access to property QueryString |
| UncontrolledFormatString.cs:17:46:17:49 | access to local variable path | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | UncontrolledFormatString.cs:17:46:17:49 | access to local variable path | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:11:23:11:45 | access to property QueryString | access to property QueryString |
| UncontrolledFormatString.cs:31:20:31:28 | access to property Text | UncontrolledFormatString.cs:31:20:31:28 | access to property Text | UncontrolledFormatString.cs:31:20:31:28 | access to property Text | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:31:20:31:28 | access to property Text | access to property Text |
| UncontrolledFormatString.cs:31:23:31:31 | access to property Text | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | $@ flows to here and is used as a format string. | UncontrolledFormatString.cs:31:23:31:31 | access to property Text | access to property Text |
| UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format | UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString | UncontrolledFormatStringBad.cs:12:39:12:44 | access to local variable format | $@ flows to here and is used as a format string. | UncontrolledFormatStringBad.cs:9:25:9:47 | access to property QueryString | access to property QueryString |

View File

@@ -7,7 +7,7 @@ public class HttpHandler : IHttpHandler
public void ProcessRequest(HttpContext ctx)
{
string format = ctx.Request.QueryString["nameformat"];
// BAD: Uncontrolled format string.
FormattedName = string.Format(format, Surname, Forenames);
}

View File

@@ -1,23 +1,30 @@
edges
| InsecureRandomness.cs:21:26:21:45 | return InsecureRandomString | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString |
| InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:21:26:21:45 | return InsecureRandomString |
| InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:29:27:29:61 | call to method GetString |
| InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:31:16:31:32 | call to method ToString |
| InsecureRandomness.cs:29:27:29:61 | call to method GetString | InsecureRandomness.cs:21:26:21:45 | return InsecureRandomString |
| InsecureRandomness.cs:29:27:29:61 | call to method GetString | InsecureRandomness.cs:31:16:31:32 | call to method ToString |
| InsecureRandomness.cs:31:16:31:32 | call to method ToString | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString |
| InsecureRandomness.cs:31:16:31:32 | call to method ToString | InsecureRandomness.cs:21:26:21:45 | return InsecureRandomString |
| InsecureRandomness.cs:53:26:53:58 | return InsecureRandomStringFromSelection | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection |
| InsecureRandomness.cs:60:31:60:39 | call to method Next | InsecureRandomness.cs:53:26:53:58 | return InsecureRandomStringFromSelection |
| InsecureRandomness.cs:60:31:60:39 | call to method Next | InsecureRandomness.cs:62:16:62:32 | call to method ToString |
| InsecureRandomness.cs:62:16:62:32 | call to method ToString | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection |
| InsecureRandomness.cs:72:31:72:39 | call to method Next | InsecureRandomness.cs:74:16:74:21 | access to local variable result |
| InsecureRandomness.cs:74:16:74:21 | access to local variable result | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer |
| InsecureRandomness.cs:62:16:62:32 | call to method ToString | InsecureRandomness.cs:53:26:53:58 | return InsecureRandomStringFromSelection |
| InsecureRandomness.cs:65:26:65:56 | return InsecureRandomStringFromIndexer | InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer |
| InsecureRandomness.cs:72:31:72:39 | call to method Next | InsecureRandomness.cs:65:26:65:56 | return InsecureRandomStringFromIndexer |
nodes
| InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString |
| InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection |
| InsecureRandomness.cs:14:20:14:54 | call to method InsecureRandomStringFromIndexer |
| InsecureRandomness.cs:21:26:21:45 | return InsecureRandomString |
| InsecureRandomness.cs:28:29:28:43 | call to method Next |
| InsecureRandomness.cs:29:27:29:61 | call to method GetString |
| InsecureRandomness.cs:31:16:31:32 | call to method ToString |
| InsecureRandomness.cs:53:26:53:58 | return InsecureRandomStringFromSelection |
| InsecureRandomness.cs:60:31:60:39 | call to method Next |
| InsecureRandomness.cs:62:16:62:32 | call to method ToString |
| InsecureRandomness.cs:65:26:65:56 | return InsecureRandomStringFromIndexer |
| InsecureRandomness.cs:72:31:72:39 | call to method Next |
| InsecureRandomness.cs:74:16:74:21 | access to local variable result |
#select
| InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | InsecureRandomness.cs:28:29:28:43 | call to method Next | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:28:29:28:43 | call to method Next | call to method Next |
| InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | InsecureRandomness.cs:60:31:60:39 | call to method Next | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | Cryptographically insecure random number is generated at $@ and used here in a security context. | InsecureRandomness.cs:60:31:60:39 | call to method Next | call to method Next |

View File

@@ -6,7 +6,8 @@ edges
| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:38:22:38:59 | ... + ... |
| InappropriateEncoding.cs:36:28:36:55 | call to method UrlEncode | InappropriateEncoding.cs:39:22:39:71 | call to method Format |
| InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode | InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue |
| InappropriateEncoding.cs:68:16:68:42 | call to method Replace | InappropriateEncoding.cs:15:28:15:40 | call to method Encode |
| InappropriateEncoding.cs:66:19:66:24 | return Encode | InappropriateEncoding.cs:15:28:15:40 | call to method Encode |
| InappropriateEncoding.cs:68:16:68:42 | call to method Replace | InappropriateEncoding.cs:66:19:66:24 | return Encode |
| SqlEncode.cs:16:62:16:87 | call to method Replace | SqlEncode.cs:17:46:17:50 | access to local variable query |
| UrlEncode.cs:12:43:12:69 | call to method HtmlEncode | UrlEncode.cs:12:31:12:69 | ... + ... |
nodes
@@ -25,6 +26,7 @@ nodes
| InappropriateEncoding.cs:39:22:39:71 | call to method Format |
| InappropriateEncoding.cs:57:28:57:56 | call to method HtmlEncode |
| InappropriateEncoding.cs:58:31:58:42 | access to local variable encodedValue |
| InappropriateEncoding.cs:66:19:66:24 | return Encode |
| InappropriateEncoding.cs:68:16:68:42 | call to method Replace |
| SqlEncode.cs:16:62:16:87 | call to method Replace |
| SqlEncode.cs:17:46:17:50 | access to local variable query |

View File

@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Threading.Tasks;
using System;
namespace System.Data.Entity
{
@@ -16,6 +18,7 @@ namespace System.Data.Entity
{
public int ExecuteSqlQuery(string sql, params object[] parameters) => 0;
public int ExecuteSqlCommand(string sql, params object[] parameters) => 0;
public async Task ExecuteSqlCommandAsync(string sql, params object[] parameters) => throw null;
public Infrastructure.DbRawSqlQuery<T> SqlQuery<T>(string sql, params object[] parameters) => null;
}
@@ -41,3 +44,52 @@ namespace System.Data.Entity.Infrastructure
IList IListSource.GetList() => null;
}
}
namespace Microsoft.EntityFrameworkCore
{
public class DbSet<T>
{
}
public class DbContext : IDisposable
{
public void Dispose() { }
public virtual Infrastructure.DatabaseFacade Database => null;
// public Infrastructure.DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters) => null;
}
namespace Infrastructure
{
public class DatabaseFacade
{
}
}
public static class RelationalDatabaseFacaseExtensions
{
public static void ExecuteSqlCommand(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) {}
public static Task ExecuteSqlCommandAsync(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) => throw null;
}
struct RawSqlString
{
public RawSqlString(string str) { }
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString (FormattableString fs) => throw null;
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString (string s) => throw null;
}
}
namespace System.ComponentModel.DataAnnotations.Schema
{
class NotMappedAttribute : Attribute
{
}
}
namespace Microsoft.EntityFrameworkCore.Storage
{
interface IRawSqlCommandBuilder
{
void Build(string sql);
}
}

View File

@@ -43,7 +43,7 @@ namespace Newtonsoft.Json.Linq
public static explicit operator string(JToken t) => null;
public IEnumerable<JToken> SelectToken(string s) => null;
public IEnumerable<JToken> SelectToken(string s) => null;
}
public class JObject : JToken

View File

@@ -0,0 +1,18 @@
namespace NHibernate
{
public interface ISession
{
void Delete(string query);
T Query<T>();
void Save(object obj);
}
namespace SqlCommand
{
public class SqlString
{
public SqlString(string sql) { }
}
}
}

View File

@@ -71,6 +71,7 @@ namespace System.Data
IDataReader ExecuteReader();
CommandType CommandType { get; set; }
IDataParameterCollection Parameters { get; set; }
string CommandText { get; set; }
}
public interface IDataReader
@@ -117,13 +118,14 @@ namespace System.Data.Common
public virtual string GetString(int i) => "";
}
public class DbCommand : IDbCommand, IDisposable
public abstract class DbCommand : IDbCommand, IDisposable
{
public DbDataReader ExecuteReader() => null;
public CommandType CommandType { get; set; }
public IDataParameterCollection Parameters { get; set; }
IDataReader IDbCommand.ExecuteReader() => null;
public void Dispose() { }
public string CommandText { get; set; }
}
public class DbDataAdapter : IDataAdapter, IDbDataAdapter

View File

@@ -31,7 +31,7 @@ namespace System.Windows.Forms
public char PasswordChar { get; set; }
public bool UseSystemPasswordChar { get; set; }
}
class RichTextBox : TextBoxBase
{
public string Rtf => null;