mirror of
https://github.com/github/codeql.git
synced 2026-05-05 21:55:19 +02:00
Merge branch 'rc/1.20' into merge-rc
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 };`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(), _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
193
csharp/ql/src/semmle/code/csharp/frameworks/EntityFramework.qll
Normal file
193
csharp/ql/src/semmle/code/csharp/frameworks/EntityFramework.qll
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
113
csharp/ql/src/semmle/code/csharp/frameworks/NHibernate.qll
Normal file
113
csharp/ql/src/semmle/code/csharp/frameworks/NHibernate.qll
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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") }
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,4 +166,4 @@ class SplittingStressTest
|
||||
;
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 | $"..." |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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 | ... == ... |
|
||||
|
||||
@@ -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" |
|
||||
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.EntityFramework
|
||||
|
||||
from EntityFramework::MappedProperty property
|
||||
select property
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.Sql
|
||||
|
||||
from SqlExpr expr
|
||||
select expr
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Stored
|
||||
|
||||
from StoredFlowSource source
|
||||
select source
|
||||
@@ -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" |
|
||||
@@ -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()
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.frameworks.Sql
|
||||
|
||||
from SqlExpr e
|
||||
select e
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,5 @@
|
||||
import csharp
|
||||
import semmle.code.csharp.security.dataflow.flowsources.Stored
|
||||
|
||||
from StoredFlowSource source
|
||||
select source
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class Program
|
||||
{
|
||||
if (obj2 == null)
|
||||
{
|
||||
obj2 = null;
|
||||
obj2 = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
18
csharp/ql/test/resources/stubs/NHibernate.cs
Normal file
18
csharp/ql/test/resources/stubs/NHibernate.cs
Normal 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) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user