mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
Merge branch 'master' into SplitFPs
This commit is contained in:
@@ -3,9 +3,18 @@
|
||||
/java/ @github/codeql-java
|
||||
/javascript/ @github/codeql-javascript
|
||||
/python/ @github/codeql-python
|
||||
|
||||
# Assign query help for docs review
|
||||
/cpp/**/*.qhelp @hubwriter
|
||||
/csharp/**/*.qhelp @jf205
|
||||
/java/**/*.qhelp @felicitymay
|
||||
/javascript/**/*.qhelp @mchammer01
|
||||
/python/**/*.qhelp @felicitymay
|
||||
/docs/language/ @shati-patel @jf205
|
||||
|
||||
# Exclude help for experimental queries from docs review
|
||||
/cpp/**/experimental/**/*.qhelp @github/codeql-c-analysis
|
||||
/csharp/**/experimental/**/*.qhelp @github/codeql-csharp
|
||||
/java/**/experimental/**/*.qhelp @github/codeql-java
|
||||
/javascript/**/experimental/**/*.qhelp @github/codeql-javascript
|
||||
/python/**/experimental/**/*.qhelp @github/codeql-python
|
||||
|
||||
28
change-notes/1.25/analysis-csharp.md
Normal file
28
change-notes/1.25/analysis-csharp.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Improvements to C# analysis
|
||||
|
||||
The following changes in version 1.25 affect C# analysis in all applications.
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
|
||||
|
||||
## Removal of old queries
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
* The class `UnboundGeneric` has been refined to only be those declarations that actually
|
||||
have type parameters. This means that non-generic nested types inside construced types,
|
||||
such as `A<int>.B`, no longer are considered unbound generics. (Such nested types do,
|
||||
however, still have relevant `.getSourceDeclaration()`s, for example `A<>.B`.)
|
||||
|
||||
## Changes to autobuilder
|
||||
@@ -24,6 +24,7 @@
|
||||
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe strings based on URLs. |
|
||||
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
|
||||
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
|
||||
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
|
||||
|
||||
## Changes to libraries
|
||||
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/**
|
||||
* Provides precise tracking of how big the memory pointed to by pointers is.
|
||||
* For each pointer, we start tracking (starting from the allocation or an array declaration)
|
||||
* 1) how long is the chunk of memory allocated
|
||||
* 2) where the current pointer is in this chunk of memory
|
||||
* As computing this information is obviously not possible for all pointers,
|
||||
* we do not guarantee the existence of length/offset information for all pointers.
|
||||
* However, when it exists it is guaranteed to be accurate.
|
||||
*
|
||||
* The length and offset are tracked in a similar way to the Rangeanalysis.
|
||||
* Each length is a `ValueNumber + delta`, and each Offset is an `Operand + delta`.
|
||||
* We choose to track a `ValueNumber` for length, because the Rangeanalysis offers
|
||||
* integer bounds on instructions and operands in terms of `ValueNumber`s,
|
||||
* and `Operand` for offset because integer bounds on `Operand`s are
|
||||
* tighter than bounds on `Instruction`s.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.models.interfaces.Allocation
|
||||
private import semmle.code.cpp.rangeanalysis.RangeUtils
|
||||
|
||||
private newtype TLength =
|
||||
TZeroLength() or
|
||||
TVNLength(ValueNumber vn) {
|
||||
not vn.getAnInstruction() instanceof ConstantInstruction and
|
||||
exists(Instruction i |
|
||||
vn.getAnInstruction() = i and
|
||||
(
|
||||
i.getResultIRType() instanceof IRSignedIntegerType or
|
||||
i.getResultIRType() instanceof IRUnsignedIntegerType
|
||||
)
|
||||
|
|
||||
i instanceof PhiInstruction
|
||||
or
|
||||
i instanceof InitializeParameterInstruction
|
||||
or
|
||||
i instanceof CallInstruction
|
||||
or
|
||||
i.(LoadInstruction).getSourceAddress() instanceof VariableAddressInstruction
|
||||
or
|
||||
i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction
|
||||
or
|
||||
i.getAUse() instanceof ArgumentOperand
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Array lengths are represented in a ValueNumber | Zero + delta format.
|
||||
* This class keeps track of the ValueNumber or Zero.
|
||||
* The delta is tracked in the predicate `knownArrayLength`.
|
||||
*/
|
||||
class Length extends TLength {
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
* This length class corresponds to an array having a constant length
|
||||
* that is tracked by the delta value.
|
||||
*/
|
||||
class ZeroLength extends Length, TZeroLength {
|
||||
override string toString() { result = "ZeroLength" }
|
||||
}
|
||||
|
||||
/**
|
||||
* This length class corresponds to an array having variable length, i.e. the
|
||||
* length is tracked by a value number. One example is an array having length
|
||||
* `count` for an integer variable `count` in the program.
|
||||
*/
|
||||
class VNLength extends Length, TVNLength {
|
||||
ValueNumber vn;
|
||||
|
||||
VNLength() { this = TVNLength(vn) }
|
||||
|
||||
/** Gets an instruction with this value number bound. */
|
||||
Instruction getInstruction() { this = TVNLength(valueNumber(result)) }
|
||||
|
||||
ValueNumber getValueNumber() { result = vn }
|
||||
|
||||
override string toString() { result = "VNLength(" + vn.getExampleInstruction().toString() + ")" }
|
||||
}
|
||||
|
||||
private newtype TOffset =
|
||||
TZeroOffset() or
|
||||
TOpOffset(Operand op) {
|
||||
op.getAnyDef().getResultIRType() instanceof IRSignedIntegerType or
|
||||
op.getAnyDef().getResultIRType() instanceof IRUnsignedIntegerType
|
||||
}
|
||||
|
||||
/**
|
||||
* This class describes the offset of a pointer in a chunk of memory.
|
||||
* It is either an `Operand` or zero, an additional integer delta is added later.
|
||||
*/
|
||||
class Offset extends TOffset {
|
||||
string toString() { none() } // overridden in subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents a fixed offset, only specified by a delta.
|
||||
*/
|
||||
class ZeroOffset extends Offset, TZeroOffset {
|
||||
override string toString() { result = "ZeroOffset" }
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents an offset of an operand.
|
||||
*/
|
||||
class OpOffset extends Offset, TOpOffset {
|
||||
Operand op;
|
||||
|
||||
OpOffset() { this = TOpOffset(op) }
|
||||
|
||||
Operand getOperand() { result = op }
|
||||
|
||||
override string toString() { result = "OpOffset(" + op.getDef().toString() + ")" }
|
||||
}
|
||||
|
||||
private int getBaseSizeForPointerType(PointerType type) { result = type.getBaseType().getSize() }
|
||||
|
||||
/**
|
||||
* Holds if pointer `prev` that points at offset `prevOffset + prevOffsetDelta`
|
||||
* steps to `array` that points to `offset + offsetDelta` in one step.
|
||||
* This predicate does not contain any recursive steps.
|
||||
*/
|
||||
bindingset[prevOffset, prevOffsetDelta]
|
||||
predicate simpleArrayLengthStep(
|
||||
Instruction array, Offset offset, int offsetDelta, Instruction prev, Offset prevOffset,
|
||||
int prevOffsetDelta
|
||||
) {
|
||||
// array assign
|
||||
array.(CopyInstruction).getSourceValue() = prev and
|
||||
offset = prevOffset and
|
||||
offsetDelta = prevOffsetDelta
|
||||
or
|
||||
// pointer add with constant
|
||||
array.(PointerAddInstruction).getLeft() = prev and
|
||||
offset = prevOffset and
|
||||
offsetDelta = prevOffsetDelta + getConstantValue(array.(PointerAddInstruction).getRight())
|
||||
or
|
||||
// pointer add with variable
|
||||
array.(PointerAddInstruction).getLeft() = prev and
|
||||
prevOffset instanceof ZeroOffset and
|
||||
offset.(OpOffset).getOperand() = array.(PointerAddInstruction).getRightOperand() and
|
||||
offsetDelta = prevOffsetDelta and
|
||||
not exists(getConstantValue(array.(PointerAddInstruction).getRight()))
|
||||
or
|
||||
// pointer sub with constant
|
||||
array.(PointerSubInstruction).getLeft() = prev and
|
||||
offset = prevOffset and
|
||||
offsetDelta = prevOffsetDelta - getConstantValue(array.(PointerSubInstruction).getRight())
|
||||
or
|
||||
// array to pointer decay
|
||||
array.(ConvertInstruction).getUnary() = prev and
|
||||
array.getConvertedResultExpression() instanceof ArrayToPointerConversion and
|
||||
offset = prevOffset and
|
||||
offsetDelta = prevOffsetDelta
|
||||
or
|
||||
// cast of pointer to pointer with the same element size
|
||||
exists(PointerType fromTyp, PointerType toTyp |
|
||||
array.(PtrToPtrCastInstruction).getUnary() = prev and
|
||||
prev.getResultLanguageType().hasType(fromTyp, false) and
|
||||
array.getResultLanguageType().hasType(toTyp, false) and
|
||||
offset = prevOffset and
|
||||
offsetDelta = prevOffsetDelta and
|
||||
if fromTyp instanceof VoidPointerType
|
||||
then getBaseSizeForPointerType(toTyp) = 1
|
||||
else (
|
||||
if toTyp instanceof VoidPointerType
|
||||
then getBaseSizeForPointerType(fromTyp) = 1
|
||||
else getBaseSizeForPointerType(toTyp) = getBaseSizeForPointerType(fromTyp)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a `sizeExpr` of malloc into a variable part (`lengthExpr`) and an integer offset (`delta`).
|
||||
*/
|
||||
private predicate deconstructMallocSizeExpr(Expr sizeExpr, Expr lengthExpr, int delta) {
|
||||
sizeExpr instanceof AddExpr and
|
||||
exists(Expr constantExpr |
|
||||
lengthExpr = sizeExpr.(AddExpr).getAnOperand() and
|
||||
constantExpr = sizeExpr.(AddExpr).getAnOperand() and
|
||||
lengthExpr != constantExpr and
|
||||
delta = constantExpr.getValue().toInt()
|
||||
)
|
||||
or
|
||||
sizeExpr instanceof SubExpr and
|
||||
exists(Expr constantExpr |
|
||||
lengthExpr = sizeExpr.(SubExpr).getLeftOperand() and
|
||||
constantExpr = sizeExpr.(SubExpr).getRightOperand() and
|
||||
delta = -constantExpr.getValue().toInt()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the instruction `array` is a dynamic memory allocation of `length`+`delta` elements.
|
||||
*/
|
||||
private predicate allocation(Instruction array, Length length, int delta) {
|
||||
exists(AllocationExpr alloc, Type ptrTyp |
|
||||
array.getUnconvertedResultExpression() = alloc and
|
||||
array.getResultLanguageType().hasType(ptrTyp, false) and
|
||||
// ensure that we have the same type of the allocation and the pointer
|
||||
ptrTyp.stripTopLevelSpecifiers().(PointerType).getBaseType().getUnspecifiedType() =
|
||||
alloc.getAllocatedElementType().getUnspecifiedType() and
|
||||
// ensure that the size multiplier of the allocation is the same as the
|
||||
// size of the type we are allocating
|
||||
alloc.getSizeMult() = getBaseSizeForPointerType(ptrTyp) and
|
||||
(
|
||||
length instanceof ZeroLength and
|
||||
delta = alloc.getSizeExpr().getValue().toInt()
|
||||
or
|
||||
not exists(alloc.getSizeExpr().getValue().toInt()) and
|
||||
(
|
||||
exists(Expr lengthExpr |
|
||||
deconstructMallocSizeExpr(alloc.getSizeExpr(), lengthExpr, delta) and
|
||||
length.(VNLength).getInstruction().getConvertedResultExpression() = lengthExpr
|
||||
)
|
||||
or
|
||||
not exists(int d | deconstructMallocSizeExpr(alloc.getSizeExpr(), _, d)) and
|
||||
length.(VNLength).getInstruction().getConvertedResultExpression() = alloc.getSizeExpr() and
|
||||
delta = 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `array` is declared as an array with length `length + lengthDelta`
|
||||
*/
|
||||
private predicate arrayDeclaration(Instruction array, Length length, int lengthDelta) {
|
||||
(
|
||||
array instanceof VariableAddressInstruction or
|
||||
array instanceof FieldAddressInstruction
|
||||
) and
|
||||
exists(ArrayType type | array.getResultLanguageType().hasType(type, _) |
|
||||
length instanceof ZeroLength and
|
||||
lengthDelta = type.getArraySize()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `array` is declared as an array or allocated
|
||||
* with length `length + lengthDelta`
|
||||
*/
|
||||
predicate arrayAllocationOrDeclaration(Instruction array, Length length, int lengthDelta) {
|
||||
allocation(array, length, lengthDelta)
|
||||
or
|
||||
// declaration of variable of array type
|
||||
arrayDeclaration(array, length, lengthDelta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the instruction `array` represents a pointer to a chunk of memory that holds
|
||||
* `length + lengthDelta` elements, using only local analysis.
|
||||
* `array` points at `offset + offsetDelta` in the chunk of memory.
|
||||
* The pointer is in-bounds if `offset + offsetDelta < length + lengthDelta` and
|
||||
* `offset + offsetDelta >= 0` holds.
|
||||
* The pointer is out-of-bounds if `offset + offsetDelta >= length + lengthDelta`
|
||||
* or `offset + offsetDelta < 0` holds.
|
||||
* All pointers in this predicate are guaranteed to be non-null,
|
||||
* but are not guaranteed to be live.
|
||||
*/
|
||||
predicate knownArrayLength(
|
||||
Instruction array, Length length, int lengthDelta, Offset offset, int offsetDelta
|
||||
) {
|
||||
arrayAllocationOrDeclaration(array, length, lengthDelta) and
|
||||
offset instanceof ZeroOffset and
|
||||
offsetDelta = 0
|
||||
or
|
||||
// simple step (no phi nodes)
|
||||
exists(Instruction prev, Offset prevOffset, int prevOffsetDelta |
|
||||
knownArrayLength(prev, length, lengthDelta, prevOffset, prevOffsetDelta) and
|
||||
simpleArrayLengthStep(array, offset, offsetDelta, prev, prevOffset, prevOffsetDelta)
|
||||
)
|
||||
or
|
||||
// merge control flow after phi node - but only if all the bounds agree
|
||||
forex(Instruction input | array.(PhiInstruction).getAnInput() = input |
|
||||
knownArrayLength(input, length, lengthDelta, offset, offsetDelta)
|
||||
)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,30 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
pragma[nomagic]
|
||||
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) {
|
||||
viableCallable(call) = result.getCallable() and
|
||||
kind = result.getKind()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a value at return position `pos` can be returned to `out` via `call`,
|
||||
* taking virtual dispatch into account.
|
||||
*/
|
||||
cached
|
||||
predicate viableReturnPosOut(DataFlowCall call, ReturnPosition pos, Node out) {
|
||||
exists(ReturnKindExt kind |
|
||||
pos = viableReturnPos(call, kind) and
|
||||
out = kind.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
private module FlowThrough {
|
||||
/**
|
||||
* The first flow-through approximation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a Boolean parameter
|
||||
* - Input access paths are abstracted with a Boolean parameter
|
||||
* that indicates (non-)emptiness.
|
||||
*/
|
||||
private module Cand {
|
||||
@@ -40,83 +57,47 @@ private module Cached {
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`,
|
||||
* and `stored` indicates whether it flows to contents of `node`.
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowCand(
|
||||
ParameterNode p, Node node, boolean read, boolean stored
|
||||
) {
|
||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
||||
p = node and
|
||||
read = false and
|
||||
stored = false
|
||||
read = false
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, stored) and
|
||||
parameterValueFlowCand(p, mid, read) and
|
||||
simpleLocalFlowStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, boolean readMid, boolean storedMid |
|
||||
parameterValueFlowCand(p, mid, readMid, storedMid) and
|
||||
readStep(mid, _, node) and
|
||||
stored = false
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
readMid = false and
|
||||
storedMid = false and
|
||||
read = true
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
read = readMid and
|
||||
storedMid = true
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, false) and
|
||||
storeStep(mid, _, node) and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
readStep(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, false, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read, stored)
|
||||
parameterValueFlowArgCand(p, arg, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, read, stored) and
|
||||
argumentValueFlowsThroughCand(arg, node, false, false)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, boolean mid |
|
||||
parameterValueFlowArgCand(p, arg, read, mid) and
|
||||
argumentValueFlowsThroughCand(arg, node, mid, stored)
|
||||
parameterValueFlowArgCand(p, arg, read) and
|
||||
argumentValueFlowsThroughCand(arg, node, false)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArgCand(
|
||||
ParameterNode p, ArgumentNode arg, boolean read, boolean stored
|
||||
) {
|
||||
parameterValueFlowCand(p, arg, read, stored)
|
||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
||||
parameterValueFlowCand(p, arg, read)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false, false)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdateCand(
|
||||
ParameterNode p, PostUpdateNode n, boolean read
|
||||
) {
|
||||
parameterValueFlowCand(p, n, read, true)
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,33 +106,21 @@ private module Cached {
|
||||
* into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||
* node, and `stored` indicates whether it flows to contents of the return
|
||||
* node.
|
||||
*/
|
||||
predicate parameterValueFlowReturnCand(
|
||||
ParameterNode p, ReturnKindExt kind, boolean read, boolean stored
|
||||
) {
|
||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlowCand(p, ret, read, stored) and
|
||||
kind = TValueReturn(ret.getKind())
|
||||
)
|
||||
or
|
||||
exists(ParameterNode p2, int pos2, PostUpdateNode n |
|
||||
parameterValueFlowsToPostUpdateCand(p, n, read) and
|
||||
parameterValueFlowsToPreUpdateCand(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2 and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, ret, read) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThroughCand0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, boolean read, boolean stored
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturnCand(param, kind, read, stored)
|
||||
parameterValueFlowReturnCand(param, kind, read)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -159,22 +128,19 @@ private module Cached {
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`, and
|
||||
* `stored` indicates whether it flows to contents of `out`.
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
||||
*/
|
||||
predicate argumentValueFlowsThroughCand(
|
||||
ArgumentNode arg, Node out, boolean read, boolean stored
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKindExt kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read, stored) and
|
||||
out = kind.getAnOutNode(call)
|
||||
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate cand(ParameterNode p, Node n) {
|
||||
parameterValueFlowCand(p, n, _, _) and
|
||||
parameterValueFlowCand(p, n, _) and
|
||||
(
|
||||
parameterValueFlowReturnCand(p, _, _, _)
|
||||
parameterValueFlowReturnCand(p, _, _)
|
||||
or
|
||||
parameterValueFlowsToPreUpdateCand(p, _)
|
||||
)
|
||||
@@ -187,7 +153,6 @@ private module Cached {
|
||||
(
|
||||
n instanceof ParameterNode or
|
||||
n instanceof OutNode or
|
||||
n instanceof PostUpdateNode or
|
||||
readStep(_, _, n) or
|
||||
n instanceof CastNode
|
||||
)
|
||||
@@ -200,10 +165,6 @@ private module Cached {
|
||||
or
|
||||
n instanceof ReturnNode
|
||||
or
|
||||
Cand::parameterValueFlowsToPreUpdateCand(_, n)
|
||||
or
|
||||
storeStep(n, _, _)
|
||||
or
|
||||
readStep(n, _, _)
|
||||
or
|
||||
n instanceof CastNode
|
||||
@@ -237,230 +198,140 @@ private module Cached {
|
||||
/**
|
||||
* The final flow-through calculation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a `ContentOption` parameter
|
||||
* - Input access paths are abstracted with a `ContentOption` parameter
|
||||
* that represents the head of the access path. `TContentNone()` means that
|
||||
* the access path is unrestricted.
|
||||
* - Types are checked using the `compatibleTypes()` relation.
|
||||
*/
|
||||
cached
|
||||
private module Final {
|
||||
/**
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps, not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to `node`
|
||||
* (if any), and `contentOut` describes the content of `node` that
|
||||
* it flows to (if any).
|
||||
* (if any).
|
||||
*/
|
||||
private predicate parameterValueFlow(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow0(p, node, contentIn, contentOut) and
|
||||
predicate parameterValueFlow(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
parameterValueFlow0(p, node, contentIn) and
|
||||
if node instanceof CastingNode
|
||||
then
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
or
|
||||
// (getter+)setter
|
||||
exists(Content fOut |
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlow0(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
p = node and
|
||||
Cand::cand(p, _) and
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone()
|
||||
contentIn = TContentNone()
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlow(p, mid, contentIn, contentOut) and
|
||||
parameterValueFlow(p, mid, contentIn) and
|
||||
LocalFlowBigStep::localFlowBigStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, Content f, ContentOption contentInMid, ContentOption contentOutMid |
|
||||
parameterValueFlow(p, mid, contentInMid, contentOutMid) and
|
||||
readStep(mid, f, node)
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
contentInMid = TContentNone() and
|
||||
contentOutMid = TContentNone() and
|
||||
contentIn.getContent() = f and
|
||||
contentOut = TContentNone() and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true, _) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
contentIn = contentInMid and
|
||||
contentOutMid.getContent() = f and
|
||||
contentOut = TContentNone()
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid, Content f |
|
||||
parameterValueFlow(p, mid, contentIn, TContentNone()) and
|
||||
storeStep(mid, f, node) and
|
||||
contentOut.getContent() = f
|
||||
|
|
||||
contentIn = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getType())
|
||||
or
|
||||
compatibleTypes(contentIn.getContent().getType(), f.getType())
|
||||
parameterValueFlow(p, mid, TContentNone()) and
|
||||
readStep(mid, f, node) and
|
||||
contentIn.getContent() = f and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, TContentNone(), TContentNone()) and
|
||||
argumentValueFlowsThrough(_, arg, contentIn, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, TContentNone()) and
|
||||
argumentValueFlowsThrough(arg, contentIn, node)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentOut) and
|
||||
argumentValueFlowsThrough(_, arg, TContentNone(), TContentNone(), node)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, ContentOption contentMid |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentMid) and
|
||||
argumentValueFlowsThrough(_, arg, contentMid, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, contentIn) and
|
||||
argumentValueFlowsThrough(arg, TContentNone(), node)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArg(
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn
|
||||
) {
|
||||
parameterValueFlow(p, arg, contentIn, contentOut) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _, _)
|
||||
parameterValueFlow(p, arg, contentIn) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThrough0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturn(param, _, kind, contentIn, contentOut)
|
||||
parameterValueFlowReturn(param, kind, contentIn)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` flows to `out` through `call` using only value-preserving steps,
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any), and
|
||||
* `contentOut` describes the content of `out` that it flows to (if any).
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any).
|
||||
*/
|
||||
cached
|
||||
predicate argumentValueFlowsThrough(
|
||||
DataFlowCall call, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut,
|
||||
Node out
|
||||
) {
|
||||
exists(ReturnKindExt kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn, contentOut) and
|
||||
out = kind.getAnOutNode(call)
|
||||
pragma[nomagic]
|
||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ContentOption contentIn, Node out) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn) and
|
||||
out = getAnOutNode(call, kind)
|
||||
|
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// setter
|
||||
exists(Content fOut |
|
||||
contentIn = TContentNone() and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fOut.getType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// getter+setter
|
||||
exists(Content fIn, Content fOut |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), TContentNone())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdate(
|
||||
ParameterNode p, PostUpdateNode n, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
contentOut.hasContent()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to a return node of kind `kind` in the same
|
||||
* callable using only value-preserving steps.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to the return
|
||||
* node (if any), and `contentOut` describes the content of the return
|
||||
* node that it flows to (if any).
|
||||
* node (if any).
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowReturn(
|
||||
ParameterNode p, Node ret, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
private predicate parameterValueFlowReturn(
|
||||
ParameterNode p, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
ret =
|
||||
any(ReturnNode n |
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
kind = TValueReturn(n.getKind())
|
||||
)
|
||||
or
|
||||
ret =
|
||||
any(PostUpdateNode n |
|
||||
exists(ParameterNode p2, int pos2 |
|
||||
parameterValueFlowsToPostUpdate(p, n, contentIn, contentOut) and
|
||||
parameterValueFlowsToPreUpdate(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2
|
||||
)
|
||||
)
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlow(p, ret, contentIn) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Final
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -469,14 +340,14 @@ private module Cached {
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate storeDirect(Node node1, Content f, Node node2) {
|
||||
predicate store(Node node1, Content f, Node node2) {
|
||||
storeStep(node1, f, node2) and readStep(_, f, _)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(_, n2, TContentSome(f), TContentNone(), n1)
|
||||
argumentValueFlowsThrough(n2, TContentSome(f), n1)
|
||||
or
|
||||
readStep(n2, f, n1)
|
||||
)
|
||||
@@ -520,6 +391,21 @@ private module Cached {
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
TBooleanNone() or
|
||||
TBooleanSome(boolean b) { b = true or b = false }
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(Content f)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
TAccessPathFrontNone() or
|
||||
TAccessPathFrontSome(AccessPathFront apf)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,8 +415,7 @@ class CastingNode extends Node {
|
||||
CastingNode() {
|
||||
this instanceof ParameterNode or
|
||||
this instanceof CastNode or
|
||||
this instanceof OutNode or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
this instanceof OutNodeExt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +423,7 @@ newtype TContentOption =
|
||||
TContentNone() or
|
||||
TContentSome(Content f)
|
||||
|
||||
class ContentOption extends TContentOption {
|
||||
private class ContentOption extends TContentOption {
|
||||
Content getContent() { this = TContentSome(result) }
|
||||
|
||||
predicate hasContent() { exists(this.getContent()) }
|
||||
@@ -678,6 +563,18 @@ class ReturnNodeExt extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() {
|
||||
this instanceof OutNode
|
||||
or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended return kind. A return kind describes how data can be returned
|
||||
* from a callable. This can either be through a returned value or an updated
|
||||
@@ -688,7 +585,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
||||
abstract string toString();
|
||||
|
||||
/** Gets a node corresponding to data flow out of `call`. */
|
||||
abstract Node getAnOutNode(DataFlowCall call);
|
||||
abstract OutNodeExt getAnOutNode(DataFlowCall call);
|
||||
}
|
||||
|
||||
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
@@ -700,7 +597,9 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
|
||||
override string toString() { result = kind.toString() }
|
||||
|
||||
override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) }
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
result = getAnOutNode(call, this.getKind())
|
||||
}
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
@@ -712,9 +611,9 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
|
||||
override PostUpdateNode getAnOutNode(DataFlowCall call) {
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
exists(ArgumentNode arg |
|
||||
result.getPreUpdateNode() = arg and
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, this.getPosition())
|
||||
)
|
||||
}
|
||||
@@ -779,77 +678,58 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
result = viableCallable(call) and cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
newtype TSummary =
|
||||
TSummaryVal() or
|
||||
TSummaryTaint() or
|
||||
TSummaryReadVal(Content f) or
|
||||
TSummaryReadTaint(Content f) or
|
||||
TSummaryTaintStore(Content f)
|
||||
|
||||
/**
|
||||
* A summary of flow through a callable. This can either be value-preserving
|
||||
* if no additional steps are used, taint-flow if at least one additional step
|
||||
* is used, or any one of those combined with a store or a read. Summaries
|
||||
* recorded at a return node are restricted to include at least one additional
|
||||
* step, as the value-based summaries are calculated independent of the
|
||||
* configuration.
|
||||
*/
|
||||
class Summary extends TSummary {
|
||||
string toString() {
|
||||
result = "Val" and this = TSummaryVal()
|
||||
or
|
||||
result = "Taint" and this = TSummaryTaint()
|
||||
or
|
||||
exists(Content f |
|
||||
result = "ReadVal " + f.toString() and this = TSummaryReadVal(f)
|
||||
or
|
||||
result = "ReadTaint " + f.toString() and this = TSummaryReadTaint(f)
|
||||
or
|
||||
result = "TaintStore " + f.toString() and this = TSummaryTaintStore(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with an additional step. */
|
||||
Summary additionalStep() {
|
||||
this = TSummaryVal() and result = TSummaryTaint()
|
||||
or
|
||||
this = TSummaryTaint() and result = TSummaryTaint()
|
||||
or
|
||||
exists(Content f | this = TSummaryReadVal(f) and result = TSummaryReadTaint(f))
|
||||
or
|
||||
exists(Content f | this = TSummaryReadTaint(f) and result = TSummaryReadTaint(f))
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with a read. */
|
||||
Summary readStep(Content f) { this = TSummaryVal() and result = TSummaryReadVal(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with a store. */
|
||||
Summary storeStep(Content f) { this = TSummaryTaint() and result = TSummaryTaintStore(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with `step`. */
|
||||
bindingset[this, step]
|
||||
Summary compose(Summary step) {
|
||||
this = TSummaryVal() and result = step
|
||||
or
|
||||
this = TSummaryTaint() and
|
||||
(step = TSummaryTaint() or step = TSummaryTaintStore(_)) and
|
||||
result = step
|
||||
or
|
||||
exists(Content f |
|
||||
this = TSummaryReadVal(f) and step = TSummaryTaint() and result = TSummaryReadTaint(f)
|
||||
)
|
||||
or
|
||||
this = TSummaryReadTaint(_) and step = TSummaryTaint() and result = this
|
||||
}
|
||||
|
||||
/** Holds if this summary does not include any taint steps. */
|
||||
predicate isPartial() {
|
||||
this = TSummaryVal() or
|
||||
this = TSummaryReadVal(_)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
|
||||
|
||||
predicate readDirect = readStep/3;
|
||||
predicate read = readStep/3;
|
||||
|
||||
/** An optional Boolean value. */
|
||||
class BooleanOption extends TBooleanOption {
|
||||
string toString() {
|
||||
this = TBooleanNone() and result = "<none>"
|
||||
or
|
||||
this = TBooleanSome(any(boolean b | result = b.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TFrontNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override DataFlowType getType() { this = TFrontNil(result) }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
override string toString() { exists(Content f | this = TFrontHead(f) | result = f.toString()) }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
class AccessPathFrontOption extends TAccessPathFrontOption {
|
||||
string toString() {
|
||||
this = TAccessPathFrontNone() and result = "<none>"
|
||||
or
|
||||
this = TAccessPathFrontSome(any(AccessPathFront apf | result = apf.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -655,7 +655,7 @@ private module FieldFlow {
|
||||
exists(FieldConfiguration cfg | cfg.hasFlow(node1, node2)) and
|
||||
// This configuration should not be able to cross function boundaries, but
|
||||
// we double-check here just to be sure.
|
||||
node1.getFunction() = node2.getFunction()
|
||||
node1.getEnclosingCallable() = node2.getEnclosingCallable()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
* int myFunctionTarget(int);
|
||||
*
|
||||
* void myFunction() {
|
||||
* int (*myFunctionPointer)(int) = &myTarget;
|
||||
* int (*myFunctionPointer)(int) = &myFunctionTarget;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,30 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
pragma[nomagic]
|
||||
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) {
|
||||
viableCallable(call) = result.getCallable() and
|
||||
kind = result.getKind()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a value at return position `pos` can be returned to `out` via `call`,
|
||||
* taking virtual dispatch into account.
|
||||
*/
|
||||
cached
|
||||
predicate viableReturnPosOut(DataFlowCall call, ReturnPosition pos, Node out) {
|
||||
exists(ReturnKindExt kind |
|
||||
pos = viableReturnPos(call, kind) and
|
||||
out = kind.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
private module FlowThrough {
|
||||
/**
|
||||
* The first flow-through approximation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a Boolean parameter
|
||||
* - Input access paths are abstracted with a Boolean parameter
|
||||
* that indicates (non-)emptiness.
|
||||
*/
|
||||
private module Cand {
|
||||
@@ -40,83 +57,47 @@ private module Cached {
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`,
|
||||
* and `stored` indicates whether it flows to contents of `node`.
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowCand(
|
||||
ParameterNode p, Node node, boolean read, boolean stored
|
||||
) {
|
||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
||||
p = node and
|
||||
read = false and
|
||||
stored = false
|
||||
read = false
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, stored) and
|
||||
parameterValueFlowCand(p, mid, read) and
|
||||
simpleLocalFlowStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, boolean readMid, boolean storedMid |
|
||||
parameterValueFlowCand(p, mid, readMid, storedMid) and
|
||||
readStep(mid, _, node) and
|
||||
stored = false
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
readMid = false and
|
||||
storedMid = false and
|
||||
read = true
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
read = readMid and
|
||||
storedMid = true
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, false) and
|
||||
storeStep(mid, _, node) and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
readStep(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, false, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read, stored)
|
||||
parameterValueFlowArgCand(p, arg, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, read, stored) and
|
||||
argumentValueFlowsThroughCand(arg, node, false, false)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, boolean mid |
|
||||
parameterValueFlowArgCand(p, arg, read, mid) and
|
||||
argumentValueFlowsThroughCand(arg, node, mid, stored)
|
||||
parameterValueFlowArgCand(p, arg, read) and
|
||||
argumentValueFlowsThroughCand(arg, node, false)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArgCand(
|
||||
ParameterNode p, ArgumentNode arg, boolean read, boolean stored
|
||||
) {
|
||||
parameterValueFlowCand(p, arg, read, stored)
|
||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
||||
parameterValueFlowCand(p, arg, read)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false, false)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdateCand(
|
||||
ParameterNode p, PostUpdateNode n, boolean read
|
||||
) {
|
||||
parameterValueFlowCand(p, n, read, true)
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,33 +106,21 @@ private module Cached {
|
||||
* into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||
* node, and `stored` indicates whether it flows to contents of the return
|
||||
* node.
|
||||
*/
|
||||
predicate parameterValueFlowReturnCand(
|
||||
ParameterNode p, ReturnKindExt kind, boolean read, boolean stored
|
||||
) {
|
||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlowCand(p, ret, read, stored) and
|
||||
kind = TValueReturn(ret.getKind())
|
||||
)
|
||||
or
|
||||
exists(ParameterNode p2, int pos2, PostUpdateNode n |
|
||||
parameterValueFlowsToPostUpdateCand(p, n, read) and
|
||||
parameterValueFlowsToPreUpdateCand(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2 and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, ret, read) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThroughCand0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, boolean read, boolean stored
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturnCand(param, kind, read, stored)
|
||||
parameterValueFlowReturnCand(param, kind, read)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -159,22 +128,19 @@ private module Cached {
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`, and
|
||||
* `stored` indicates whether it flows to contents of `out`.
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
||||
*/
|
||||
predicate argumentValueFlowsThroughCand(
|
||||
ArgumentNode arg, Node out, boolean read, boolean stored
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKindExt kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read, stored) and
|
||||
out = kind.getAnOutNode(call)
|
||||
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate cand(ParameterNode p, Node n) {
|
||||
parameterValueFlowCand(p, n, _, _) and
|
||||
parameterValueFlowCand(p, n, _) and
|
||||
(
|
||||
parameterValueFlowReturnCand(p, _, _, _)
|
||||
parameterValueFlowReturnCand(p, _, _)
|
||||
or
|
||||
parameterValueFlowsToPreUpdateCand(p, _)
|
||||
)
|
||||
@@ -187,7 +153,6 @@ private module Cached {
|
||||
(
|
||||
n instanceof ParameterNode or
|
||||
n instanceof OutNode or
|
||||
n instanceof PostUpdateNode or
|
||||
readStep(_, _, n) or
|
||||
n instanceof CastNode
|
||||
)
|
||||
@@ -200,10 +165,6 @@ private module Cached {
|
||||
or
|
||||
n instanceof ReturnNode
|
||||
or
|
||||
Cand::parameterValueFlowsToPreUpdateCand(_, n)
|
||||
or
|
||||
storeStep(n, _, _)
|
||||
or
|
||||
readStep(n, _, _)
|
||||
or
|
||||
n instanceof CastNode
|
||||
@@ -237,230 +198,140 @@ private module Cached {
|
||||
/**
|
||||
* The final flow-through calculation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a `ContentOption` parameter
|
||||
* - Input access paths are abstracted with a `ContentOption` parameter
|
||||
* that represents the head of the access path. `TContentNone()` means that
|
||||
* the access path is unrestricted.
|
||||
* - Types are checked using the `compatibleTypes()` relation.
|
||||
*/
|
||||
cached
|
||||
private module Final {
|
||||
/**
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps, not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to `node`
|
||||
* (if any), and `contentOut` describes the content of `node` that
|
||||
* it flows to (if any).
|
||||
* (if any).
|
||||
*/
|
||||
private predicate parameterValueFlow(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow0(p, node, contentIn, contentOut) and
|
||||
predicate parameterValueFlow(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
parameterValueFlow0(p, node, contentIn) and
|
||||
if node instanceof CastingNode
|
||||
then
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
or
|
||||
// (getter+)setter
|
||||
exists(Content fOut |
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlow0(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
p = node and
|
||||
Cand::cand(p, _) and
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone()
|
||||
contentIn = TContentNone()
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlow(p, mid, contentIn, contentOut) and
|
||||
parameterValueFlow(p, mid, contentIn) and
|
||||
LocalFlowBigStep::localFlowBigStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, Content f, ContentOption contentInMid, ContentOption contentOutMid |
|
||||
parameterValueFlow(p, mid, contentInMid, contentOutMid) and
|
||||
readStep(mid, f, node)
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
contentInMid = TContentNone() and
|
||||
contentOutMid = TContentNone() and
|
||||
contentIn.getContent() = f and
|
||||
contentOut = TContentNone() and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true, _) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
contentIn = contentInMid and
|
||||
contentOutMid.getContent() = f and
|
||||
contentOut = TContentNone()
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid, Content f |
|
||||
parameterValueFlow(p, mid, contentIn, TContentNone()) and
|
||||
storeStep(mid, f, node) and
|
||||
contentOut.getContent() = f
|
||||
|
|
||||
contentIn = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getType())
|
||||
or
|
||||
compatibleTypes(contentIn.getContent().getType(), f.getType())
|
||||
parameterValueFlow(p, mid, TContentNone()) and
|
||||
readStep(mid, f, node) and
|
||||
contentIn.getContent() = f and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, TContentNone(), TContentNone()) and
|
||||
argumentValueFlowsThrough(_, arg, contentIn, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, TContentNone()) and
|
||||
argumentValueFlowsThrough(arg, contentIn, node)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentOut) and
|
||||
argumentValueFlowsThrough(_, arg, TContentNone(), TContentNone(), node)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, ContentOption contentMid |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentMid) and
|
||||
argumentValueFlowsThrough(_, arg, contentMid, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, contentIn) and
|
||||
argumentValueFlowsThrough(arg, TContentNone(), node)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArg(
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn
|
||||
) {
|
||||
parameterValueFlow(p, arg, contentIn, contentOut) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _, _)
|
||||
parameterValueFlow(p, arg, contentIn) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThrough0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturn(param, _, kind, contentIn, contentOut)
|
||||
parameterValueFlowReturn(param, kind, contentIn)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` flows to `out` through `call` using only value-preserving steps,
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any), and
|
||||
* `contentOut` describes the content of `out` that it flows to (if any).
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any).
|
||||
*/
|
||||
cached
|
||||
predicate argumentValueFlowsThrough(
|
||||
DataFlowCall call, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut,
|
||||
Node out
|
||||
) {
|
||||
exists(ReturnKindExt kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn, contentOut) and
|
||||
out = kind.getAnOutNode(call)
|
||||
pragma[nomagic]
|
||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ContentOption contentIn, Node out) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn) and
|
||||
out = getAnOutNode(call, kind)
|
||||
|
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// setter
|
||||
exists(Content fOut |
|
||||
contentIn = TContentNone() and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fOut.getType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// getter+setter
|
||||
exists(Content fIn, Content fOut |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), TContentNone())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdate(
|
||||
ParameterNode p, PostUpdateNode n, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
contentOut.hasContent()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to a return node of kind `kind` in the same
|
||||
* callable using only value-preserving steps.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to the return
|
||||
* node (if any), and `contentOut` describes the content of the return
|
||||
* node that it flows to (if any).
|
||||
* node (if any).
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowReturn(
|
||||
ParameterNode p, Node ret, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
private predicate parameterValueFlowReturn(
|
||||
ParameterNode p, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
ret =
|
||||
any(ReturnNode n |
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
kind = TValueReturn(n.getKind())
|
||||
)
|
||||
or
|
||||
ret =
|
||||
any(PostUpdateNode n |
|
||||
exists(ParameterNode p2, int pos2 |
|
||||
parameterValueFlowsToPostUpdate(p, n, contentIn, contentOut) and
|
||||
parameterValueFlowsToPreUpdate(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2
|
||||
)
|
||||
)
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlow(p, ret, contentIn) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Final
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -469,14 +340,14 @@ private module Cached {
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate storeDirect(Node node1, Content f, Node node2) {
|
||||
predicate store(Node node1, Content f, Node node2) {
|
||||
storeStep(node1, f, node2) and readStep(_, f, _)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(_, n2, TContentSome(f), TContentNone(), n1)
|
||||
argumentValueFlowsThrough(n2, TContentSome(f), n1)
|
||||
or
|
||||
readStep(n2, f, n1)
|
||||
)
|
||||
@@ -520,6 +391,21 @@ private module Cached {
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
TBooleanNone() or
|
||||
TBooleanSome(boolean b) { b = true or b = false }
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(Content f)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
TAccessPathFrontNone() or
|
||||
TAccessPathFrontSome(AccessPathFront apf)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,8 +415,7 @@ class CastingNode extends Node {
|
||||
CastingNode() {
|
||||
this instanceof ParameterNode or
|
||||
this instanceof CastNode or
|
||||
this instanceof OutNode or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
this instanceof OutNodeExt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +423,7 @@ newtype TContentOption =
|
||||
TContentNone() or
|
||||
TContentSome(Content f)
|
||||
|
||||
class ContentOption extends TContentOption {
|
||||
private class ContentOption extends TContentOption {
|
||||
Content getContent() { this = TContentSome(result) }
|
||||
|
||||
predicate hasContent() { exists(this.getContent()) }
|
||||
@@ -678,6 +563,18 @@ class ReturnNodeExt extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() {
|
||||
this instanceof OutNode
|
||||
or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended return kind. A return kind describes how data can be returned
|
||||
* from a callable. This can either be through a returned value or an updated
|
||||
@@ -688,7 +585,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
||||
abstract string toString();
|
||||
|
||||
/** Gets a node corresponding to data flow out of `call`. */
|
||||
abstract Node getAnOutNode(DataFlowCall call);
|
||||
abstract OutNodeExt getAnOutNode(DataFlowCall call);
|
||||
}
|
||||
|
||||
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
@@ -700,7 +597,9 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
|
||||
override string toString() { result = kind.toString() }
|
||||
|
||||
override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) }
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
result = getAnOutNode(call, this.getKind())
|
||||
}
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
@@ -712,9 +611,9 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
|
||||
override PostUpdateNode getAnOutNode(DataFlowCall call) {
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
exists(ArgumentNode arg |
|
||||
result.getPreUpdateNode() = arg and
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, this.getPosition())
|
||||
)
|
||||
}
|
||||
@@ -779,77 +678,58 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
result = viableCallable(call) and cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
newtype TSummary =
|
||||
TSummaryVal() or
|
||||
TSummaryTaint() or
|
||||
TSummaryReadVal(Content f) or
|
||||
TSummaryReadTaint(Content f) or
|
||||
TSummaryTaintStore(Content f)
|
||||
|
||||
/**
|
||||
* A summary of flow through a callable. This can either be value-preserving
|
||||
* if no additional steps are used, taint-flow if at least one additional step
|
||||
* is used, or any one of those combined with a store or a read. Summaries
|
||||
* recorded at a return node are restricted to include at least one additional
|
||||
* step, as the value-based summaries are calculated independent of the
|
||||
* configuration.
|
||||
*/
|
||||
class Summary extends TSummary {
|
||||
string toString() {
|
||||
result = "Val" and this = TSummaryVal()
|
||||
or
|
||||
result = "Taint" and this = TSummaryTaint()
|
||||
or
|
||||
exists(Content f |
|
||||
result = "ReadVal " + f.toString() and this = TSummaryReadVal(f)
|
||||
or
|
||||
result = "ReadTaint " + f.toString() and this = TSummaryReadTaint(f)
|
||||
or
|
||||
result = "TaintStore " + f.toString() and this = TSummaryTaintStore(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with an additional step. */
|
||||
Summary additionalStep() {
|
||||
this = TSummaryVal() and result = TSummaryTaint()
|
||||
or
|
||||
this = TSummaryTaint() and result = TSummaryTaint()
|
||||
or
|
||||
exists(Content f | this = TSummaryReadVal(f) and result = TSummaryReadTaint(f))
|
||||
or
|
||||
exists(Content f | this = TSummaryReadTaint(f) and result = TSummaryReadTaint(f))
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with a read. */
|
||||
Summary readStep(Content f) { this = TSummaryVal() and result = TSummaryReadVal(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with a store. */
|
||||
Summary storeStep(Content f) { this = TSummaryTaint() and result = TSummaryTaintStore(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with `step`. */
|
||||
bindingset[this, step]
|
||||
Summary compose(Summary step) {
|
||||
this = TSummaryVal() and result = step
|
||||
or
|
||||
this = TSummaryTaint() and
|
||||
(step = TSummaryTaint() or step = TSummaryTaintStore(_)) and
|
||||
result = step
|
||||
or
|
||||
exists(Content f |
|
||||
this = TSummaryReadVal(f) and step = TSummaryTaint() and result = TSummaryReadTaint(f)
|
||||
)
|
||||
or
|
||||
this = TSummaryReadTaint(_) and step = TSummaryTaint() and result = this
|
||||
}
|
||||
|
||||
/** Holds if this summary does not include any taint steps. */
|
||||
predicate isPartial() {
|
||||
this = TSummaryVal() or
|
||||
this = TSummaryReadVal(_)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
|
||||
|
||||
predicate readDirect = readStep/3;
|
||||
predicate read = readStep/3;
|
||||
|
||||
/** An optional Boolean value. */
|
||||
class BooleanOption extends TBooleanOption {
|
||||
string toString() {
|
||||
this = TBooleanNone() and result = "<none>"
|
||||
or
|
||||
this = TBooleanSome(any(boolean b | result = b.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TFrontNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override DataFlowType getType() { this = TFrontNil(result) }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
override string toString() { exists(Content f | this = TFrontHead(f) | result = f.toString()) }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
class AccessPathFrontOption extends TAccessPathFrontOption {
|
||||
string toString() {
|
||||
this = TAccessPathFrontNone() and result = "<none>"
|
||||
or
|
||||
this = TAccessPathFrontSome(any(AccessPathFront apf | result = apf.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,38 +241,6 @@ class CondReason extends Reason, TCondReason {
|
||||
override string toString() { result = getCond().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a cast from `fromtyp` to `totyp` can be ignored for the purpose of
|
||||
* range analysis.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate safeCast(IntegralType fromtyp, IntegralType totyp) {
|
||||
fromtyp.getSize() < totyp.getSize() and
|
||||
(
|
||||
fromtyp.isUnsigned()
|
||||
or
|
||||
totyp.isSigned()
|
||||
)
|
||||
or
|
||||
fromtyp.getSize() <= totyp.getSize() and
|
||||
(
|
||||
fromtyp.isSigned() and
|
||||
totyp.isSigned()
|
||||
or
|
||||
fromtyp.isUnsigned() and
|
||||
totyp.isUnsigned()
|
||||
)
|
||||
}
|
||||
|
||||
private class SafeCastInstruction extends ConvertInstruction {
|
||||
SafeCastInstruction() {
|
||||
safeCast(getUnary().getResultType(), getResultType())
|
||||
or
|
||||
getResultType() instanceof PointerType and
|
||||
getUnary().getResultType() instanceof PointerType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `typ` is a small integral type with the given lower and upper bounds.
|
||||
*/
|
||||
|
||||
@@ -80,3 +80,55 @@ predicate backEdge(PhiInstruction phi, PhiInputOperand op) {
|
||||
phi.getAnOperand() = op and
|
||||
phi.getBlock() = op.getPredecessorBlock().getBackEdgeSuccessor(_)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a cast from `fromtyp` to `totyp` can be ignored for the purpose of
|
||||
* range analysis.
|
||||
*/
|
||||
pragma[inline]
|
||||
private predicate safeCast(IntegralType fromtyp, IntegralType totyp) {
|
||||
fromtyp.getSize() < totyp.getSize() and
|
||||
(
|
||||
fromtyp.isUnsigned()
|
||||
or
|
||||
totyp.isSigned()
|
||||
)
|
||||
or
|
||||
fromtyp.getSize() <= totyp.getSize() and
|
||||
(
|
||||
fromtyp.isSigned() and
|
||||
totyp.isSigned()
|
||||
or
|
||||
fromtyp.isUnsigned() and
|
||||
totyp.isUnsigned()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which casts from one pointer type to another.
|
||||
*/
|
||||
class PtrToPtrCastInstruction extends ConvertInstruction {
|
||||
PtrToPtrCastInstruction() {
|
||||
getResultType() instanceof PointerType and
|
||||
getUnary().getResultType() instanceof PointerType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which casts from one integer type to another in a way
|
||||
* that cannot overflow or underflow.
|
||||
*/
|
||||
class SafeIntCastInstruction extends ConvertInstruction {
|
||||
SafeIntCastInstruction() { safeCast(getUnary().getResultType(), getResultType()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which does not invalidate bounds determined by
|
||||
* range analysis.
|
||||
*/
|
||||
class SafeCastInstruction extends ConvertInstruction {
|
||||
SafeCastInstruction() {
|
||||
this instanceof PtrToPtrCastInstruction or
|
||||
this instanceof SafeIntCastInstruction
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
| test.cpp:15:8:15:11 | Load: aptr | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:19:8:19:8 | Load: a | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:21:8:21:8 | Load: a | VNLength(Chi: ptr) | -1 | ZeroOffset | 0 |
|
||||
| test.cpp:23:8:23:8 | Load: a | VNLength(Chi: ptr) | 1 | ZeroOffset | 0 |
|
||||
| test.cpp:27:8:27:8 | Load: c | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:28:8:28:24 | Convert: (unsigned char *)... | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:30:8:30:8 | Load: v | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:34:8:34:12 | Convert: array to pointer conversion | ZeroLength | 100 | ZeroOffset | 0 |
|
||||
| test.cpp:37:10:37:10 | Load: b | VNLength(Chi: ptr) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:44:8:44:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
|
||||
| test.cpp:53:10:53:10 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
|
||||
| test.cpp:56:10:56:10 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 3 |
|
||||
| test.cpp:63:10:63:14 | CopyValue: & ... | VNLength(InitializeParameter: count) | 0 | OpOffset(Load: i) | 0 |
|
||||
| test.cpp:66:8:66:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:68:8:68:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 3 |
|
||||
| test.cpp:70:8:70:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 2 |
|
||||
| test.cpp:72:8:72:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | 0 |
|
||||
| test.cpp:74:8:74:8 | Load: a | VNLength(InitializeParameter: count) | 0 | ZeroOffset | -10 |
|
||||
| test.cpp:76:8:76:8 | Load: a | VNLength(InitializeParameter: count) | 1 | ZeroOffset | 0 |
|
||||
| test.cpp:78:8:78:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Load: count) | 0 |
|
||||
| test.cpp:80:8:80:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Load: count) | 1 |
|
||||
| test.cpp:85:8:85:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 0 |
|
||||
| test.cpp:87:8:87:8 | Load: a | VNLength(InitializeParameter: count) | 1 | OpOffset(Add: ... + ...) | 1 |
|
||||
@@ -0,0 +1,8 @@
|
||||
import cpp
|
||||
import experimental.semmle.code.cpp.rangeanalysis.ArrayLengthAnalysis
|
||||
|
||||
from Instruction array, Length length, int delta, Offset offset, int offsetDelta
|
||||
where
|
||||
knownArrayLength(array, length, delta, offset, offsetDelta) and
|
||||
array.getAUse() instanceof ArgumentOperand
|
||||
select array, length, delta, offset, offsetDelta
|
||||
@@ -0,0 +1,90 @@
|
||||
void *malloc(unsigned long);
|
||||
void sink(...);
|
||||
|
||||
typedef struct A {
|
||||
int a;
|
||||
int b;
|
||||
char * c;
|
||||
} A;
|
||||
|
||||
void test1(unsigned int count) {
|
||||
if (count < 1) {
|
||||
return;
|
||||
}
|
||||
A* aptr = (A *) malloc(sizeof(A) * count);
|
||||
sink(aptr); // (count, 0, Zero, 0)
|
||||
unsigned int* ptr = &count;
|
||||
sink(ptr); // (Zero, 1, Zero, 0) TODO none, as the feature is not implemented
|
||||
int* a = (int *) malloc(sizeof(int) * count);
|
||||
sink(a); // (count, 0, Zero, 0)
|
||||
a = (int *) malloc(sizeof(int) * (count - 1));
|
||||
sink(a); // (count, -1, Zero, 0)
|
||||
a = (int *) malloc(sizeof(int) * (count + 1));
|
||||
sink(a); // (count, 1, Zero, 0)
|
||||
a = (int *) malloc(sizeof(int) * (2 * count));
|
||||
sink(a); // none, as the size expression is too complicated
|
||||
char* c = (char *)malloc(count);
|
||||
sink(c); // /count, 0, Zero, 0)
|
||||
sink((unsigned char*)c); // (count, 0, Zero, 0)
|
||||
void* v = c;
|
||||
sink(v); // (count, 0, Zero, 0)
|
||||
v = malloc(count);
|
||||
sink((char *)v); // none, as we don't track void* allocations
|
||||
int stack[100];
|
||||
sink(stack); // (Zero, 100, Zero, 0)
|
||||
for(unsigned int i = 0; i < count; ++i) {
|
||||
int* b = (int*) malloc(sizeof(int) * count);
|
||||
sink(b); // (count, 0, Zero, 0)
|
||||
}
|
||||
}
|
||||
|
||||
void test2(unsigned int count, bool b) {
|
||||
int* a = (int *) malloc(sizeof(int) * count);
|
||||
a = a + 2;
|
||||
sink(a); // (count, 0, Zero, 2)
|
||||
for(unsigned int i = 2; i < count; ++i) {
|
||||
sink(a); // none
|
||||
a++;
|
||||
sink(a); // none
|
||||
}
|
||||
a = (int*) malloc(sizeof(int) * count);
|
||||
if (b) {
|
||||
a += 2;
|
||||
sink(a); // (count, 0, Zero, 2)
|
||||
} else {
|
||||
a += 3;
|
||||
sink(a); // (count, 0, Zero, 2)
|
||||
}
|
||||
sink(a); // none
|
||||
a -= 2;
|
||||
sink(a); // none
|
||||
a = (int*) malloc(sizeof(int) * count);
|
||||
for(unsigned int i = 0; i < count; i++) {
|
||||
sink(&a[i]); // (count, 0, i, 0)
|
||||
}
|
||||
a = (int*) malloc(sizeof(int) * count);
|
||||
sink(a); // (count, 0, Zero, 0)
|
||||
a += 3;
|
||||
sink(a); // (count, 0, Zero, 3)
|
||||
a -= 1;
|
||||
sink(a); // (count, 0, Zero, 2)
|
||||
a -= 2;
|
||||
sink(a); // (count, 0, Zero, 0)
|
||||
a -= 10;
|
||||
sink(a); // (count, 0, Zero, -10)
|
||||
a = (int*) malloc(sizeof(int) * (count + 1));
|
||||
sink(a); // (count, 1, Zero, 0)
|
||||
a += count;
|
||||
sink(a); // (count, 1, count, 0);
|
||||
a += 1;
|
||||
sink(a); // (count, 1, count, 1);
|
||||
a -= count;
|
||||
sink(a); // none
|
||||
a = (int*) malloc(sizeof(int) * (count + 1));
|
||||
a += count + 1;
|
||||
sink(a); // TODO, should be (count, 1, count, 1), but is (count, 1, count + 1, 0)
|
||||
a += 1;
|
||||
sink(a); // TODO, should be (count, 1, count, 2), but is (count, 1, count + 1, 1)
|
||||
a = (int*) malloc(sizeof(int) * (1024 - count));
|
||||
sink(a); // none, as the size expression is too complicated
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
struct S1 {
|
||||
[[deprecated]] int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct S2 {
|
||||
int x;
|
||||
[[deprecated, gnu::unused]] int b;
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
| field_attributes.cpp:2:22:2:22 | a | field_attributes.cpp:2:5:2:14 | deprecated |
|
||||
| field_attributes.cpp:8:35:8:35 | b | field_attributes.cpp:8:5:8:14 | deprecated |
|
||||
| field_attributes.cpp:8:35:8:35 | b | field_attributes.cpp:8:17:8:27 | unused |
|
||||
@@ -0,0 +1,3 @@
|
||||
import cpp
|
||||
|
||||
select any(Variable v) as v, v.getAnAttribute()
|
||||
@@ -3,6 +3,7 @@
|
||||
| ms_var_attributes.cpp:7:5:7:10 | myInt2 | ms_var_attributes.h:4:1:4:9 | dllexport |
|
||||
| ms_var_attributes.cpp:8:15:8:20 | myInt4 | ms_var_attributes.cpp:8:1:8:9 | dllexport |
|
||||
| ms_var_attributes.cpp:9:5:9:10 | myInt5 | ms_var_attributes.h:7:1:7:9 | dllexport |
|
||||
| ms_var_attributes.cpp:12:42:12:46 | field | ms_var_attributes.cpp:12:14:12:21 | property |
|
||||
| ms_var_attributes.h:5:22:5:27 | myInt3 | ms_var_attributes.h:5:1:5:9 | dllexport |
|
||||
| var_attributes.c:1:12:1:19 | weak_var | var_attributes.c:1:36:1:39 | weak |
|
||||
| var_attributes.c:2:12:2:22 | weakref_var | var_attributes.c:2:39:2:45 | weakref |
|
||||
|
||||
@@ -340,7 +340,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
if (isFullyConstructed)
|
||||
{
|
||||
trapFile.is_constructed(this);
|
||||
trapFile.constructed_generic(this, Method.Create(Context, ConstructedFromSymbol));
|
||||
foreach (var tp in symbol.GetAnnotatedTypeArguments())
|
||||
{
|
||||
@@ -354,7 +353,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
trapFile.is_generic(this);
|
||||
foreach (var typeParam in symbol.TypeParameters.Select(tp => TypeParameter.Create(Context, tp)))
|
||||
{
|
||||
trapFile.type_parameters(typeParam, child, this);
|
||||
|
||||
@@ -40,8 +40,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
else if (symbol.IsReallyUnbound())
|
||||
{
|
||||
trapFile.is_generic(this);
|
||||
|
||||
for (int i = 0; i < symbol.TypeParameters.Length; ++i)
|
||||
{
|
||||
TypeParameter.Create(Context, symbol.TypeParameters[i]);
|
||||
@@ -52,7 +50,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
else
|
||||
{
|
||||
trapFile.is_constructed(this);
|
||||
trapFile.constructed_generic(this, Type.Create(Context, symbol.ConstructedFrom).TypeRef);
|
||||
|
||||
for (int i = 0; i < symbol.TypeArguments.Length; ++i)
|
||||
|
||||
@@ -306,16 +306,6 @@ namespace Semmle.Extraction.CSharp
|
||||
trapFile.WriteTuple("indexers", propKey, name, declaringType, memberType, unboundProperty);
|
||||
}
|
||||
|
||||
internal static void is_constructed(this TextWriter trapFile, IEntity typeOrMethod)
|
||||
{
|
||||
trapFile.WriteTuple("is_constructed", typeOrMethod);
|
||||
}
|
||||
|
||||
internal static void is_generic(this TextWriter trapFile, IEntity typeOrMethod)
|
||||
{
|
||||
trapFile.WriteTuple("is_generic", typeOrMethod);
|
||||
}
|
||||
|
||||
internal static void local_function_stmts(this TextWriter trapFile, Entities.Statements.LocalFunction fnStmt, LocalFunction fn)
|
||||
{
|
||||
trapFile.WriteTuple("local_function_stmts", fnStmt, fn);
|
||||
|
||||
@@ -68,6 +68,8 @@ module Stages {
|
||||
or
|
||||
exists(any(DataFlow::Node n).getType())
|
||||
or
|
||||
exists(any(DataFlow::Node n).getTypeBound())
|
||||
or
|
||||
exists(any(DataFlow::Node n).getLocation())
|
||||
or
|
||||
exists(any(DataFlow::Node n).toString())
|
||||
|
||||
@@ -23,19 +23,19 @@ private import dotnet
|
||||
*/
|
||||
class Generic extends DotNet::Generic, Declaration, @generic {
|
||||
Generic() {
|
||||
is_generic(this) or
|
||||
is_constructed(this)
|
||||
type_parameters(_, _, this, _) or
|
||||
type_arguments(_, _, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A generic declaration that can have type parameters.
|
||||
* A generic declaration with type parameters.
|
||||
*
|
||||
* Either an unbound generic type (`UnboundGenericType`) or an unbound generic method
|
||||
* (`UnboundGenericMethod`).
|
||||
*/
|
||||
class UnboundGeneric extends DotNet::UnboundGeneric, Generic {
|
||||
UnboundGeneric() { is_generic(this) }
|
||||
UnboundGeneric() { type_parameters(_, _, this, _) }
|
||||
|
||||
override TypeParameter getTypeParameter(int n) { type_parameters(result, n, this, _) }
|
||||
|
||||
@@ -47,13 +47,13 @@ class UnboundGeneric extends DotNet::UnboundGeneric, Generic {
|
||||
}
|
||||
|
||||
/**
|
||||
* A declaration constructed from an `UnboundGeneric` by supplying type arguments.
|
||||
* A constructed generic.
|
||||
*
|
||||
* Either a constructed generic type (`ConstructedType`) or a constructed
|
||||
* generic method (`ConstructedMethod`).
|
||||
*/
|
||||
class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic {
|
||||
ConstructedGeneric() { is_constructed(this) }
|
||||
ConstructedGeneric() { type_arguments(_, _, this) }
|
||||
|
||||
override UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) }
|
||||
|
||||
@@ -61,10 +61,7 @@ class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic {
|
||||
result = getUnboundGeneric().getSourceDeclaration()
|
||||
}
|
||||
|
||||
override int getNumberOfTypeArguments() {
|
||||
// getTypeArgument() could fail if the type does not exist in the database
|
||||
result = count(int i | type_arguments(_, i, this))
|
||||
}
|
||||
override int getNumberOfTypeArguments() { result = count(int i | type_arguments(_, i, this)) }
|
||||
|
||||
override Type getTypeArgument(int i) { none() }
|
||||
|
||||
@@ -84,11 +81,12 @@ class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic {
|
||||
*/
|
||||
class UnboundGenericType extends ValueOrRefType, UnboundGeneric {
|
||||
/**
|
||||
* Gets a bound/constructed version of this unbound generic type. This includes not only closed constructed types such as `G<int>`,
|
||||
* but also open constructed types such as the `G<T>` in `class Other<T> { G<T> g; }`. Note that such a type is distinct from the
|
||||
* `G<T>` used in the class definition, since in `G<T> g;` the `T` will be the actual type parameter used for the `Other` that contains
|
||||
* `g`, whereas in `class G<T> { ... }` the `T` is a formal type parameter of `G`. It is important not to get confused by the superficial
|
||||
* syntactic similarity.
|
||||
* Gets a bound/constructed version of this unbound generic type. This includes
|
||||
* not only closed constructed types such as `G<int>`, but also open constructed
|
||||
* types such as the `G<T>` in `class Other<T> { G<T> g; }`. Note that such a type
|
||||
* is distinct from the `G<T>` used in the class definition, since in `G<T> g;`
|
||||
* the `T` will be the actual type parameter used for the `Other` that contains
|
||||
* `g`, whereas in `class G<T> { ... }` the `T` is a formal type parameter of `G`.
|
||||
*/
|
||||
override ConstructedType getAConstructedGeneric() {
|
||||
result = UnboundGeneric.super.getAConstructedGeneric()
|
||||
@@ -350,15 +348,16 @@ class UnboundGenericDelegateType extends DelegateType, UnboundGenericType {
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructed (bound) type. This is a generic type for which actual type arguments have been supplied,
|
||||
* for example `G<int>` or the `G<T>` in `class Other<T> { G<T> g; }`. Constructed types can be divided further into
|
||||
* those that are open (for example `G1<T>` or `G2<T,T,U,int>`), in the sense that one or more of their type arguments
|
||||
* is a type parameter, versus those that are closed (for example `G1<int>` or `G2<long,long,float,int>`). We do not
|
||||
* currently distinguish the two in this library.
|
||||
* A constructed (bound) type. This is a generic type for which actual type
|
||||
* arguments have been supplied, for example `G<int>` or the `G<T>` in
|
||||
* `class Other<T> { G<T> g; }`. Constructed types can be divided further into
|
||||
* those that are open (for example `G1<T>` or `G2<T,T,U,int>`), in the sense
|
||||
* that one or more of their type arguments is a type parameter, versus those
|
||||
* that are closed (for example `G1<int>` or `G2<long,long,float,int>`).
|
||||
*
|
||||
* Either a constructed `struct` (`ConstructedStruct`), constructed `class` (`ConstructedClass`),
|
||||
* constructed `interface` (`ConstructedInterface`), or constructed method
|
||||
* (`ConstructedMethod`).
|
||||
* Either a constructed `struct` (`ConstructedStruct`), constructed `class`
|
||||
* (`ConstructedClass`), constructed `interface` (`ConstructedInterface`),
|
||||
* or constructed method (`ConstructedMethod`).
|
||||
*/
|
||||
class ConstructedType extends ValueOrRefType, ConstructedGeneric {
|
||||
override UnboundGenericType getSourceDeclaration() {
|
||||
|
||||
@@ -16,113 +16,49 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.system.Xml
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPublic
|
||||
private import semmle.code.csharp.dataflow.internal.DelegateDataFlow
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if `source` can flow to `sink` using a call to a library
|
||||
* callable.
|
||||
*/
|
||||
cached
|
||||
predicate libraryFlow(Expr source, Expr sink, boolean preservesValue) {
|
||||
exists(LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSink csink, Call c |
|
||||
source = csource.getSource(c) and
|
||||
ltdf.callableFlow(csource, csink, c.getTarget().getSourceDeclaration(), preservesValue) and
|
||||
sink = csink.getSink(c)
|
||||
)
|
||||
}
|
||||
private newtype TAccessPath =
|
||||
TNilAccessPath() or
|
||||
TAccessPathConsNil(Content c)
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if `source` can flow to the `out`/`ref` argument `outRef` using a call to a library
|
||||
* callable.
|
||||
*/
|
||||
cached
|
||||
predicate libraryFlowOutRef(MethodCall mc, Expr source, Parameter outRef, boolean preservesValue) {
|
||||
exists(
|
||||
LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSinkArg csink, Method sm
|
||||
|
|
||||
source = csource.getSource(mc) and
|
||||
mc.getTarget().getAParameter() = outRef and
|
||||
sm = mc.getTarget().getSourceDeclaration() and
|
||||
ltdf.callableFlow(csource, csink, sm, preservesValue) and
|
||||
csink = getFlowSinkArg(sm, outRef.getPosition())
|
||||
)
|
||||
}
|
||||
/** An access path of length 0 or 1. */
|
||||
class AccessPath extends TAccessPath {
|
||||
/** Gets the head of this access path, if any. */
|
||||
Content getHead() { this = TAccessPathConsNil(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if output from the `i`th delegate argument of `call` can flow to `sink`, using
|
||||
* the library target `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate libraryFlowDelegateCallOut(
|
||||
Call call, Callable callable, Expr sink, boolean preservesValue, int i
|
||||
) {
|
||||
exists(LibraryTypeDataFlow ltdf, CallableFlowSourceDelegateArg csource, CallableFlowSink csink |
|
||||
ltdf.callableFlow(csource, csink, callable, preservesValue) and
|
||||
call.getTarget().getSourceDeclaration() = callable and
|
||||
csource = getDelegateFlowSourceArg(callable, i) and
|
||||
sink = csink.getSink(call)
|
||||
)
|
||||
}
|
||||
/** Holds if this access path contains content `c`. */
|
||||
predicate contains(Content c) { this = TAccessPathConsNil(c) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if `source` can flow to the `i`th parameter of the delegate at argument
|
||||
* `j`. The call `call` is the call in which `sink` is an argument and`callable`
|
||||
* is the library target.
|
||||
*/
|
||||
cached
|
||||
predicate libraryFlowDelegateCallIn(
|
||||
Call call, Callable callable, Expr source, boolean preservesValue, int i, int j
|
||||
) {
|
||||
exists(LibraryTypeDataFlow ltdf, CallableFlowSource csource, CallableFlowSinkDelegateArg csink |
|
||||
ltdf.callableFlow(csource, csink, callable, preservesValue) and
|
||||
call.getTarget().getSourceDeclaration() = callable and
|
||||
csink = getDelegateFlowSinkArg(callable, j, i) and
|
||||
source = csource.getSource(call)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if output from the `i`th delegate argument of `call` can flow to the `j`th parameter
|
||||
* of the of delegate at argument `k`, using the library target `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate libraryFlowDelegateCallOutIn(
|
||||
Call call, Callable callable, boolean preservesValue, int i, int j, int k
|
||||
) {
|
||||
exists(
|
||||
LibraryTypeDataFlow ltdf, CallableFlowSourceDelegateArg csource,
|
||||
CallableFlowSinkDelegateArg csink
|
||||
|
|
||||
ltdf.callableFlow(csource, csink, callable, preservesValue) and
|
||||
call.getTarget().getSourceDeclaration() = callable and
|
||||
csource = getDelegateFlowSourceArg(callable, i) and
|
||||
csink = getDelegateFlowSinkArg(callable, k, j)
|
||||
)
|
||||
/** Gets a textual representation of this access path. */
|
||||
string toString() {
|
||||
result = this.getHead().toString()
|
||||
or
|
||||
this = TNilAccessPath() and
|
||||
result = "<empty>"
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
/** Provides predicates for constructing access paths. */
|
||||
module AccessPath {
|
||||
/** Gets the empty access path. */
|
||||
AccessPath empty() { result = TNilAccessPath() }
|
||||
|
||||
/** Gets a singleton property access path. */
|
||||
AccessPath property(Property p) {
|
||||
result = TAccessPathConsNil(any(PropertyContent c | c.getProperty() = p.getSourceDeclaration()))
|
||||
}
|
||||
}
|
||||
|
||||
/** An unbound callable. */
|
||||
library class SourceDeclarationCallable extends Callable {
|
||||
SourceDeclarationCallable() { this = getSourceDeclaration() }
|
||||
class SourceDeclarationCallable extends Callable {
|
||||
SourceDeclarationCallable() { this = this.getSourceDeclaration() }
|
||||
}
|
||||
|
||||
/** An unbound method. */
|
||||
library class SourceDeclarationMethod extends SourceDeclarationCallable, Method { }
|
||||
class SourceDeclarationMethod extends SourceDeclarationCallable, Method { }
|
||||
|
||||
// Internal representation of callable flow sources
|
||||
private newtype TCallableFlowSource =
|
||||
TCallableFlowSourceQualifier() or
|
||||
TCallableFlowSourceArg(int i) { hasArgumentPosition(_, i) } or
|
||||
@@ -160,83 +96,119 @@ private predicate hasDelegateArgumentPosition2(SourceDeclarationCallable c, int
|
||||
)
|
||||
}
|
||||
|
||||
/** A flow source in a call to a library callable. */
|
||||
/** A flow source specification. */
|
||||
class CallableFlowSource extends TCallableFlowSource {
|
||||
/** Gets a textual representation of this flow source. */
|
||||
/** Gets a textual representation of this flow source specification. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the source of flow for call `c`, if any. */
|
||||
Expr getSource(Call c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the source for call `c`. Unlike `getSource()`, this
|
||||
* is defined for all flow source specifications.
|
||||
*/
|
||||
Type getSourceType(Call c) { result = this.getSource(c).getType() }
|
||||
}
|
||||
|
||||
/** A flow source in a call to a library callable: qualifier. */
|
||||
/** A flow source specification: (method call) qualifier. */
|
||||
class CallableFlowSourceQualifier extends CallableFlowSource, TCallableFlowSourceQualifier {
|
||||
override string toString() { result = "qualifier" }
|
||||
|
||||
override Expr getSource(Call c) { result = c.getChild(-1) }
|
||||
}
|
||||
|
||||
/** A flow source in a call to a library callable: argument. */
|
||||
/** A flow source specification: (method call) argument. */
|
||||
class CallableFlowSourceArg extends CallableFlowSource, TCallableFlowSourceArg {
|
||||
override string toString() { result = "argument " + this.getArgumentIndex() }
|
||||
private int i;
|
||||
|
||||
CallableFlowSourceArg() { this = TCallableFlowSourceArg(i) }
|
||||
|
||||
/** Gets the index of this argument. */
|
||||
int getArgumentIndex() { this = TCallableFlowSourceArg(result) }
|
||||
int getArgumentIndex() { result = i }
|
||||
|
||||
override Expr getSource(Call c) { result = c.getArgument(getArgumentIndex()) }
|
||||
override string toString() { result = "argument " + i }
|
||||
|
||||
override Expr getSource(Call c) { result = c.getArgument(i) }
|
||||
}
|
||||
|
||||
/** A flow source in a call to a library callable: output from delegate argument. */
|
||||
/** A flow source specification: output from delegate argument. */
|
||||
class CallableFlowSourceDelegateArg extends CallableFlowSource, TCallableFlowSourceDelegateArg {
|
||||
override string toString() { result = "output from argument " + getArgumentIndex().toString() }
|
||||
private int i;
|
||||
|
||||
CallableFlowSourceDelegateArg() { this = TCallableFlowSourceDelegateArg(i) }
|
||||
|
||||
/** Gets the index of this delegate argument. */
|
||||
int getArgumentIndex() { this = TCallableFlowSourceDelegateArg(result) }
|
||||
int getArgumentIndex() { result = i }
|
||||
|
||||
override string toString() { result = "output from argument " + i }
|
||||
|
||||
override Expr getSource(Call c) { none() }
|
||||
|
||||
override Type getSourceType(Call c) { result = c.getArgument(i).getType() }
|
||||
}
|
||||
|
||||
// Internal representation of callable flow sinks
|
||||
private newtype TCallableFlowSink =
|
||||
TCallableFlowSinkQualifier() or
|
||||
TCallableFlowSinkReturn() or
|
||||
TCallableFlowSinkArg(int i) { exists(SourceDeclarationCallable c | exists(c.getParameter(i))) } or
|
||||
TCallableFlowSinkDelegateArg(int i, int j) { hasDelegateArgumentPosition2(_, i, j) }
|
||||
|
||||
/** A flow sink in a call to a library callable. */
|
||||
/** A flow sink specification. */
|
||||
class CallableFlowSink extends TCallableFlowSink {
|
||||
/** Gets a textual representation of this flow sink. */
|
||||
/** Gets a textual representation of this flow sink specification. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the sink of flow for call `c`, if any. */
|
||||
Expr getSink(Call c) { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the sink for call `c`. Unlike `getSink()`, this is defined
|
||||
* for all flow sink specifications.
|
||||
*/
|
||||
Type getSinkType(Call c) { result = this.getSink(c).getType() }
|
||||
}
|
||||
|
||||
/** A flow sink in a call to a library callable: qualifier. */
|
||||
/** A flow sink specification: (method call) qualifier. */
|
||||
class CallableFlowSinkQualifier extends CallableFlowSink, TCallableFlowSinkQualifier {
|
||||
override string toString() { result = "qualifier" }
|
||||
|
||||
override Expr getSink(Call c) { result = c.getChild(-1) }
|
||||
}
|
||||
|
||||
/** A flow sink in a call to a library callable: return value. */
|
||||
/** A flow sink specification: return value. */
|
||||
class CallableFlowSinkReturn extends CallableFlowSink, TCallableFlowSinkReturn {
|
||||
override string toString() { result = "return" }
|
||||
|
||||
override Expr getSink(Call c) { result = c }
|
||||
}
|
||||
|
||||
/** The flow sink in an argument to a call to a library method. */
|
||||
/** A flow sink specification: (method call) argument. */
|
||||
class CallableFlowSinkArg extends CallableFlowSink, TCallableFlowSinkArg {
|
||||
override string toString() { result = "argument " + this.getArgumentIndex() }
|
||||
private int i;
|
||||
|
||||
CallableFlowSinkArg() { this = TCallableFlowSinkArg(i) }
|
||||
|
||||
/** Gets the index of this `out`/`ref` argument. */
|
||||
int getArgumentIndex() { this = TCallableFlowSinkArg(result) }
|
||||
int getArgumentIndex() { result = i }
|
||||
|
||||
/** Gets the `out`/`ref` argument of method call `mc` matching this specification. */
|
||||
Expr getArgument(MethodCall mc) {
|
||||
exists(Parameter p |
|
||||
p = mc.getTarget().getParameter(i) and
|
||||
p.isOutOrRef() and
|
||||
result = mc.getArgumentForParameter(p)
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = "argument " + i }
|
||||
|
||||
override Expr getSink(Call c) {
|
||||
// The uses of the `i`th argument are the actual sinks
|
||||
none()
|
||||
}
|
||||
|
||||
override Type getSinkType(Call c) { result = this.getArgument(c).getType() }
|
||||
}
|
||||
|
||||
/** Gets the flow source for argument `i` of callable `callable`. */
|
||||
@@ -245,12 +217,6 @@ private CallableFlowSourceArg getFlowSourceArg(SourceDeclarationCallable callabl
|
||||
hasArgumentPosition(callable, i)
|
||||
}
|
||||
|
||||
/** Gets the flow sink for argument `i` of callable `callable`. */
|
||||
private CallableFlowSinkArg getFlowSinkArg(SourceDeclarationCallable callable, int i) {
|
||||
i = result.getArgumentIndex() and
|
||||
hasArgumentPosition(callable, i)
|
||||
}
|
||||
|
||||
/** Gets the flow source for argument `i` of delegate `callable`. */
|
||||
private CallableFlowSourceDelegateArg getDelegateFlowSourceArg(
|
||||
SourceDeclarationCallable callable, int i
|
||||
@@ -267,11 +233,23 @@ private CallableFlowSinkDelegateArg getDelegateFlowSinkArg(
|
||||
hasDelegateArgumentPosition2(callable, i, j)
|
||||
}
|
||||
|
||||
/** The flow sink in a call to a library callable: parameter of a delegate argument. */
|
||||
/** A flow sink specification: parameter of a delegate argument. */
|
||||
class CallableFlowSinkDelegateArg extends CallableFlowSink, TCallableFlowSinkDelegateArg {
|
||||
private int delegateIndex;
|
||||
private int parameterIndex;
|
||||
|
||||
CallableFlowSinkDelegateArg() {
|
||||
this = TCallableFlowSinkDelegateArg(delegateIndex, parameterIndex)
|
||||
}
|
||||
|
||||
/** Gets the index of the delegate argument. */
|
||||
int getDelegateIndex() { result = delegateIndex }
|
||||
|
||||
/** Gets the index of the delegate parameter. */
|
||||
int getDelegateParameterIndex() { result = parameterIndex }
|
||||
|
||||
override string toString() {
|
||||
result =
|
||||
"parameter " + getDelegateParameterIndex() + " of argument " + getDelegateIndex().toString()
|
||||
result = "parameter " + parameterIndex + " of argument " + delegateIndex
|
||||
}
|
||||
|
||||
override Expr getSink(Call c) {
|
||||
@@ -279,18 +257,20 @@ class CallableFlowSinkDelegateArg extends CallableFlowSink, TCallableFlowSinkDel
|
||||
none()
|
||||
}
|
||||
|
||||
/** Gets the index of the delegate argument. */
|
||||
int getDelegateIndex() { this = TCallableFlowSinkDelegateArg(result, _) }
|
||||
|
||||
/** Gets the index of the delegate parameter. */
|
||||
int getDelegateParameterIndex() { this = TCallableFlowSinkDelegateArg(_, result) }
|
||||
override Type getSinkType(Call c) {
|
||||
result =
|
||||
c
|
||||
.getArgument(delegateIndex)
|
||||
.(DelegateArgumentToLibraryCallable)
|
||||
.getDelegateType()
|
||||
.getParameter(parameterIndex)
|
||||
.getType()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A specification of data flow for a library (non-source code) type.
|
||||
*/
|
||||
/** A specification of data flow for a library (non-source code) type. */
|
||||
abstract class LibraryTypeDataFlow extends Type {
|
||||
LibraryTypeDataFlow() { this = getSourceDeclaration() }
|
||||
LibraryTypeDataFlow() { this = this.getSourceDeclaration() }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `source` to `sink` when calling callable `c`.
|
||||
@@ -300,10 +280,27 @@ abstract class LibraryTypeDataFlow extends Type {
|
||||
* to `x.ToString()` when `x` is a `string`, but not from `x` to `x.ToLower()`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
abstract predicate callableFlow(
|
||||
predicate callableFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
);
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `source` to `sink` when calling callable `c`.
|
||||
*
|
||||
* `sourceAp` describes the contents of `source` that flows to `sink`
|
||||
* (if any), and `sinkContent` describes the contents of `sink` that it
|
||||
* flows to (if any).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate callableFlow(
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
SourceDeclarationCallable c
|
||||
) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/** Data flow for `System.Int32`. */
|
||||
@@ -614,38 +611,20 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB
|
||||
}
|
||||
|
||||
/** Data flow for `System.Lazy<>`. */
|
||||
class SystemLazyFlow extends LibraryTypeDataFlow {
|
||||
SystemLazyFlow() { this instanceof SystemLazyClass }
|
||||
|
||||
class SystemLazyFlow extends LibraryTypeDataFlow, SystemLazyClass {
|
||||
override predicate callableFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sink, c)
|
||||
or
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
)
|
||||
) and
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
private predicate constructorFlow(
|
||||
CallableFlowSourceDelegateArg source, CallableFlowSink sink, Constructor c
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
SourceDeclarationCallable c
|
||||
) {
|
||||
exists(SystemFuncDelegateType t, int i | t.getNumberOfTypeParameters() = 1 |
|
||||
c.getDeclaringType() = this and
|
||||
c.(Constructor).getDeclaringType() = this and
|
||||
c.getParameter(i).getType().getSourceDeclaration() = t and
|
||||
source = getDelegateFlowSourceArg(c, i) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::property(this.getValueProperty())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate propertyFlow(Property p) { p = this.(SystemLazyClass).getValueProperty() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -173,15 +173,16 @@ abstract class ControlFlowReachabilityConfiguration extends string {
|
||||
* Holds if there is a control-flow path from `cfn1` to `cfn2`, where `cfn1` is a
|
||||
* control-flow node for `e1` and `cfn2` is a control-flow node for `e2`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasExprPath(Expr e1, ControlFlow::Node cfn1, Expr e2, ControlFlow::Node cfn2) {
|
||||
exists(ControlFlow::BasicBlock bb, boolean isSuccessor, int i, int j |
|
||||
this.reachesBasicBlockExprBase(e1, e2, _, _, isSuccessor, cfn1, i, bb) and
|
||||
cfn2 = bb.getNode(j) and
|
||||
cfn2 = e2.getAControlFlowNode()
|
||||
|
|
||||
isSuccessor = true and j > i
|
||||
isSuccessor = true and j >= i
|
||||
or
|
||||
isSuccessor = false and i > j
|
||||
isSuccessor = false and i >= j
|
||||
)
|
||||
or
|
||||
exists(ControlFlow::BasicBlock bb |
|
||||
@@ -195,6 +196,7 @@ abstract class ControlFlowReachabilityConfiguration extends string {
|
||||
* Holds if there is a control-flow path from `cfn` to `cfnDef`, where `cfn` is a
|
||||
* control-flow node for `e` and `cfnDef` is a control-flow node for `def`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasDefPath(
|
||||
Expr e, ControlFlow::Node cfn, AssignableDefinition def, ControlFlow::Node cfnDef
|
||||
) {
|
||||
@@ -203,9 +205,9 @@ abstract class ControlFlowReachabilityConfiguration extends string {
|
||||
cfnDef = bb.getNode(j) and
|
||||
def.getAControlFlowNode() = cfnDef
|
||||
|
|
||||
isSuccessor = true and j > i
|
||||
isSuccessor = true and j >= i
|
||||
or
|
||||
isSuccessor = false and i > j
|
||||
isSuccessor = false and i >= j
|
||||
)
|
||||
or
|
||||
exists(ControlFlow::BasicBlock bb |
|
||||
@@ -219,6 +221,7 @@ abstract class ControlFlowReachabilityConfiguration extends string {
|
||||
* Holds if there is a control-flow path from `n1` to `n2`. `n2` is either an
|
||||
* expression node or an SSA definition node.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate hasNodePath(ExprNode n1, Node n2) {
|
||||
exists(Expr e1, ControlFlow::Node cfn1, Expr e2, ControlFlow::Node cfn2 |
|
||||
this.hasExprPath(e1, cfn1, e2, cfn2)
|
||||
|
||||
@@ -346,11 +346,14 @@ class ImplicitDelegateDataFlowCall extends DelegateDataFlowCall, TImplicitDelega
|
||||
/** Gets the number of parameters of the supplied delegate. */
|
||||
int getNumberOfDelegateParameters() { result = arg.getDelegateType().getNumberOfParameters() }
|
||||
|
||||
/** Gets the type of the `i`th parameter of the supplied delegate. */
|
||||
Type getDelegateParameterType(int i) { result = arg.getDelegateType().getParameter(i).getType() }
|
||||
|
||||
/** Gets the return type of the supplied delegate. */
|
||||
Type getDelegateReturnType() { result = arg.getDelegateType().getReturnType() }
|
||||
|
||||
override DotNet::Callable getARuntimeTarget(CallContext::CallContext cc) {
|
||||
result = cfn.getElement().(DelegateArgumentToLibraryCallable).getARuntimeTarget(cc)
|
||||
result = arg.getARuntimeTarget(cc)
|
||||
}
|
||||
|
||||
override ControlFlow::Nodes::ElementNode getControlFlowNode() { result = cfn }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -26,13 +26,30 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
pragma[nomagic]
|
||||
private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) {
|
||||
viableCallable(call) = result.getCallable() and
|
||||
kind = result.getKind()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a value at return position `pos` can be returned to `out` via `call`,
|
||||
* taking virtual dispatch into account.
|
||||
*/
|
||||
cached
|
||||
predicate viableReturnPosOut(DataFlowCall call, ReturnPosition pos, Node out) {
|
||||
exists(ReturnKindExt kind |
|
||||
pos = viableReturnPos(call, kind) and
|
||||
out = kind.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides predicates for calculating flow-through summaries. */
|
||||
private module FlowThrough {
|
||||
/**
|
||||
* The first flow-through approximation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a Boolean parameter
|
||||
* - Input access paths are abstracted with a Boolean parameter
|
||||
* that indicates (non-)emptiness.
|
||||
*/
|
||||
private module Cand {
|
||||
@@ -40,83 +57,47 @@ private module Cached {
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`,
|
||||
* and `stored` indicates whether it flows to contents of `node`.
|
||||
* `read` indicates whether it is contents of `p` that can flow to `node`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowCand(
|
||||
ParameterNode p, Node node, boolean read, boolean stored
|
||||
) {
|
||||
private predicate parameterValueFlowCand(ParameterNode p, Node node, boolean read) {
|
||||
p = node and
|
||||
read = false and
|
||||
stored = false
|
||||
read = false
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, stored) and
|
||||
parameterValueFlowCand(p, mid, read) and
|
||||
simpleLocalFlowStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, boolean readMid, boolean storedMid |
|
||||
parameterValueFlowCand(p, mid, readMid, storedMid) and
|
||||
readStep(mid, _, node) and
|
||||
stored = false
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
readMid = false and
|
||||
storedMid = false and
|
||||
read = true
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
read = readMid and
|
||||
storedMid = true
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid |
|
||||
parameterValueFlowCand(p, mid, read, false) and
|
||||
storeStep(mid, _, node) and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, mid, false) and
|
||||
readStep(mid, _, node) and
|
||||
read = true
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, false, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read, stored)
|
||||
parameterValueFlowArgCand(p, arg, false) and
|
||||
argumentValueFlowsThroughCand(arg, node, read)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArgCand(p, arg, read, stored) and
|
||||
argumentValueFlowsThroughCand(arg, node, false, false)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, boolean mid |
|
||||
parameterValueFlowArgCand(p, arg, read, mid) and
|
||||
argumentValueFlowsThroughCand(arg, node, mid, stored)
|
||||
parameterValueFlowArgCand(p, arg, read) and
|
||||
argumentValueFlowsThroughCand(arg, node, false)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArgCand(
|
||||
ParameterNode p, ArgumentNode arg, boolean read, boolean stored
|
||||
) {
|
||||
parameterValueFlowCand(p, arg, read, stored)
|
||||
private predicate parameterValueFlowArgCand(ParameterNode p, ArgumentNode arg, boolean read) {
|
||||
parameterValueFlowCand(p, arg, read)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate parameterValueFlowsToPreUpdateCand(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false, false)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdateCand(
|
||||
ParameterNode p, PostUpdateNode n, boolean read
|
||||
) {
|
||||
parameterValueFlowCand(p, n, read, true)
|
||||
parameterValueFlowCand(p, n.getPreUpdateNode(), false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,33 +106,21 @@ private module Cached {
|
||||
* into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `p` that can flow to the return
|
||||
* node, and `stored` indicates whether it flows to contents of the return
|
||||
* node.
|
||||
*/
|
||||
predicate parameterValueFlowReturnCand(
|
||||
ParameterNode p, ReturnKindExt kind, boolean read, boolean stored
|
||||
) {
|
||||
predicate parameterValueFlowReturnCand(ParameterNode p, ReturnKind kind, boolean read) {
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlowCand(p, ret, read, stored) and
|
||||
kind = TValueReturn(ret.getKind())
|
||||
)
|
||||
or
|
||||
exists(ParameterNode p2, int pos2, PostUpdateNode n |
|
||||
parameterValueFlowsToPostUpdateCand(p, n, read) and
|
||||
parameterValueFlowsToPreUpdateCand(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2 and
|
||||
stored = true
|
||||
parameterValueFlowCand(p, ret, read) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThroughCand0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, boolean read, boolean stored
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, boolean read
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturnCand(param, kind, read, stored)
|
||||
parameterValueFlowReturnCand(param, kind, read)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -159,22 +128,19 @@ private module Cached {
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`, and
|
||||
* `stored` indicates whether it flows to contents of `out`.
|
||||
* `read` indicates whether it is contents of `arg` that can flow to `out`.
|
||||
*/
|
||||
predicate argumentValueFlowsThroughCand(
|
||||
ArgumentNode arg, Node out, boolean read, boolean stored
|
||||
) {
|
||||
exists(DataFlowCall call, ReturnKindExt kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read, stored) and
|
||||
out = kind.getAnOutNode(call)
|
||||
predicate argumentValueFlowsThroughCand(ArgumentNode arg, Node out, boolean read) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThroughCand0(call, arg, kind, read) and
|
||||
out = getAnOutNode(call, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate cand(ParameterNode p, Node n) {
|
||||
parameterValueFlowCand(p, n, _, _) and
|
||||
parameterValueFlowCand(p, n, _) and
|
||||
(
|
||||
parameterValueFlowReturnCand(p, _, _, _)
|
||||
parameterValueFlowReturnCand(p, _, _)
|
||||
or
|
||||
parameterValueFlowsToPreUpdateCand(p, _)
|
||||
)
|
||||
@@ -187,7 +153,6 @@ private module Cached {
|
||||
(
|
||||
n instanceof ParameterNode or
|
||||
n instanceof OutNode or
|
||||
n instanceof PostUpdateNode or
|
||||
readStep(_, _, n) or
|
||||
n instanceof CastNode
|
||||
)
|
||||
@@ -200,10 +165,6 @@ private module Cached {
|
||||
or
|
||||
n instanceof ReturnNode
|
||||
or
|
||||
Cand::parameterValueFlowsToPreUpdateCand(_, n)
|
||||
or
|
||||
storeStep(n, _, _)
|
||||
or
|
||||
readStep(n, _, _)
|
||||
or
|
||||
n instanceof CastNode
|
||||
@@ -237,230 +198,140 @@ private module Cached {
|
||||
/**
|
||||
* The final flow-through calculation:
|
||||
*
|
||||
* - Input/output access paths are abstracted with a `ContentOption` parameter
|
||||
* - Input access paths are abstracted with a `ContentOption` parameter
|
||||
* that represents the head of the access path. `TContentNone()` means that
|
||||
* the access path is unrestricted.
|
||||
* - Types are checked using the `compatibleTypes()` relation.
|
||||
*/
|
||||
cached
|
||||
private module Final {
|
||||
/**
|
||||
* Holds if `p` can flow to `node` in the same callable using only
|
||||
* value-preserving steps, not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to `node`
|
||||
* (if any), and `contentOut` describes the content of `node` that
|
||||
* it flows to (if any).
|
||||
* (if any).
|
||||
*/
|
||||
private predicate parameterValueFlow(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow0(p, node, contentIn, contentOut) and
|
||||
predicate parameterValueFlow(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
parameterValueFlow0(p, node, contentIn) and
|
||||
if node instanceof CastingNode
|
||||
then
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), getErasedNodeTypeBound(node))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
or
|
||||
// (getter+)setter
|
||||
exists(Content fOut |
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(node))
|
||||
)
|
||||
else any()
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlow0(
|
||||
ParameterNode p, Node node, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
private predicate parameterValueFlow0(ParameterNode p, Node node, ContentOption contentIn) {
|
||||
p = node and
|
||||
Cand::cand(p, _) and
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone()
|
||||
contentIn = TContentNone()
|
||||
or
|
||||
// local flow
|
||||
exists(Node mid |
|
||||
parameterValueFlow(p, mid, contentIn, contentOut) and
|
||||
parameterValueFlow(p, mid, contentIn) and
|
||||
LocalFlowBigStep::localFlowBigStep(mid, node)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Node mid, Content f, ContentOption contentInMid, ContentOption contentOutMid |
|
||||
parameterValueFlow(p, mid, contentInMid, contentOutMid) and
|
||||
readStep(mid, f, node)
|
||||
|
|
||||
// value neither read nor stored prior to read
|
||||
contentInMid = TContentNone() and
|
||||
contentOutMid = TContentNone() and
|
||||
contentIn.getContent() = f and
|
||||
contentOut = TContentNone() and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true, _) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
or
|
||||
// value (possibly read and then) stored prior to read (same content)
|
||||
contentIn = contentInMid and
|
||||
contentOutMid.getContent() = f and
|
||||
contentOut = TContentNone()
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(Node mid, Content f |
|
||||
parameterValueFlow(p, mid, contentIn, TContentNone()) and
|
||||
storeStep(mid, f, node) and
|
||||
contentOut.getContent() = f
|
||||
|
|
||||
contentIn = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getType())
|
||||
or
|
||||
compatibleTypes(contentIn.getContent().getType(), f.getType())
|
||||
parameterValueFlow(p, mid, TContentNone()) and
|
||||
readStep(mid, f, node) and
|
||||
contentIn.getContent() = f and
|
||||
Cand::parameterValueFlowReturnCand(p, _, true) and
|
||||
compatibleTypes(getErasedNodeTypeBound(p), f.getContainerType())
|
||||
)
|
||||
or
|
||||
// flow through: no prior read or store
|
||||
// flow through: no prior read
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, TContentNone(), TContentNone()) and
|
||||
argumentValueFlowsThrough(_, arg, contentIn, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, TContentNone()) and
|
||||
argumentValueFlowsThrough(arg, contentIn, node)
|
||||
)
|
||||
or
|
||||
// flow through: no read or store inside method
|
||||
// flow through: no read inside method
|
||||
exists(ArgumentNode arg |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentOut) and
|
||||
argumentValueFlowsThrough(_, arg, TContentNone(), TContentNone(), node)
|
||||
)
|
||||
or
|
||||
// flow through: possible prior read and prior store with compatible
|
||||
// flow-through method
|
||||
exists(ArgumentNode arg, ContentOption contentMid |
|
||||
parameterValueFlowArg(p, arg, contentIn, contentMid) and
|
||||
argumentValueFlowsThrough(_, arg, contentMid, contentOut, node)
|
||||
parameterValueFlowArg(p, arg, contentIn) and
|
||||
argumentValueFlowsThrough(arg, TContentNone(), node)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowArg(
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut
|
||||
ParameterNode p, ArgumentNode arg, ContentOption contentIn
|
||||
) {
|
||||
parameterValueFlow(p, arg, contentIn, contentOut) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _, _)
|
||||
parameterValueFlow(p, arg, contentIn) and
|
||||
Cand::argumentValueFlowsThroughCand(arg, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate argumentValueFlowsThrough0(
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
DataFlowCall call, ArgumentNode arg, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
exists(ParameterNode param | viableParamArg(call, param, arg) |
|
||||
parameterValueFlowReturn(param, _, kind, contentIn, contentOut)
|
||||
parameterValueFlowReturn(param, kind, contentIn)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` flows to `out` through `call` using only value-preserving steps,
|
||||
* Holds if `arg` flows to `out` through a call using only value-preserving steps,
|
||||
* not taking call contexts into account.
|
||||
*
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any), and
|
||||
* `contentOut` describes the content of `out` that it flows to (if any).
|
||||
* `contentIn` describes the content of `arg` that can flow to `out` (if any).
|
||||
*/
|
||||
cached
|
||||
predicate argumentValueFlowsThrough(
|
||||
DataFlowCall call, ArgumentNode arg, ContentOption contentIn, ContentOption contentOut,
|
||||
Node out
|
||||
) {
|
||||
exists(ReturnKindExt kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn, contentOut) and
|
||||
out = kind.getAnOutNode(call)
|
||||
pragma[nomagic]
|
||||
predicate argumentValueFlowsThrough(ArgumentNode arg, ContentOption contentIn, Node out) {
|
||||
exists(DataFlowCall call, ReturnKind kind |
|
||||
argumentValueFlowsThrough0(call, arg, kind, contentIn) and
|
||||
out = getAnOutNode(call, kind)
|
||||
|
|
||||
// normal flow through
|
||||
contentIn = TContentNone() and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), getErasedNodeTypeBound(out))
|
||||
or
|
||||
// getter
|
||||
exists(Content fIn |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut = TContentNone() and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fIn.getType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// setter
|
||||
exists(Content fOut |
|
||||
contentIn = TContentNone() and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fOut.getType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
or
|
||||
// getter+setter
|
||||
exists(Content fIn, Content fOut |
|
||||
contentIn.getContent() = fIn and
|
||||
contentOut.getContent() = fOut and
|
||||
compatibleTypes(getErasedNodeTypeBound(arg), fIn.getContainerType()) and
|
||||
compatibleTypes(fOut.getContainerType(), getErasedNodeTypeBound(out))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone(), TContentNone())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterValueFlowsToPostUpdate(
|
||||
ParameterNode p, PostUpdateNode n, ContentOption contentIn, ContentOption contentOut
|
||||
) {
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
contentOut.hasContent()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to a return node of kind `kind` in the same
|
||||
* callable using only value-preserving steps.
|
||||
*
|
||||
* `contentIn` describes the content of `p` that can flow to the return
|
||||
* node (if any), and `contentOut` describes the content of the return
|
||||
* node that it flows to (if any).
|
||||
* node (if any).
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowReturn(
|
||||
ParameterNode p, Node ret, ReturnKindExt kind, ContentOption contentIn,
|
||||
ContentOption contentOut
|
||||
private predicate parameterValueFlowReturn(
|
||||
ParameterNode p, ReturnKind kind, ContentOption contentIn
|
||||
) {
|
||||
ret =
|
||||
any(ReturnNode n |
|
||||
parameterValueFlow(p, n, contentIn, contentOut) and
|
||||
kind = TValueReturn(n.getKind())
|
||||
)
|
||||
or
|
||||
ret =
|
||||
any(PostUpdateNode n |
|
||||
exists(ParameterNode p2, int pos2 |
|
||||
parameterValueFlowsToPostUpdate(p, n, contentIn, contentOut) and
|
||||
parameterValueFlowsToPreUpdate(p2, n) and
|
||||
p2.isParameterOf(_, pos2) and
|
||||
kind = TParamUpdate(pos2) and
|
||||
p != p2
|
||||
)
|
||||
)
|
||||
exists(ReturnNode ret |
|
||||
parameterValueFlow(p, ret, contentIn) and
|
||||
kind = ret.getKind()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Final
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` can flow to the pre-update node associated with post-update
|
||||
* node `n`, in the same callable, using only value-preserving steps.
|
||||
*/
|
||||
cached
|
||||
predicate parameterValueFlowsToPreUpdate(ParameterNode p, PostUpdateNode n) {
|
||||
parameterValueFlow(p, n.getPreUpdateNode(), TContentNone())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
@@ -469,14 +340,14 @@ private module Cached {
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate storeDirect(Node node1, Content f, Node node2) {
|
||||
predicate store(Node node1, Content f, Node node2) {
|
||||
storeStep(node1, f, node2) and readStep(_, f, _)
|
||||
or
|
||||
exists(Node n1, Node n2 |
|
||||
n1 = node1.(PostUpdateNode).getPreUpdateNode() and
|
||||
n2 = node2.(PostUpdateNode).getPreUpdateNode()
|
||||
|
|
||||
argumentValueFlowsThrough(_, n2, TContentSome(f), TContentNone(), n1)
|
||||
argumentValueFlowsThrough(n2, TContentSome(f), n1)
|
||||
or
|
||||
readStep(n2, f, n1)
|
||||
)
|
||||
@@ -520,6 +391,21 @@ private module Cached {
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParameterNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
TBooleanNone() or
|
||||
TBooleanSome(boolean b) { b = true or b = false }
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(Content f)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
TAccessPathFrontNone() or
|
||||
TAccessPathFrontSome(AccessPathFront apf)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -529,8 +415,7 @@ class CastingNode extends Node {
|
||||
CastingNode() {
|
||||
this instanceof ParameterNode or
|
||||
this instanceof CastNode or
|
||||
this instanceof OutNode or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
this instanceof OutNodeExt
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +423,7 @@ newtype TContentOption =
|
||||
TContentNone() or
|
||||
TContentSome(Content f)
|
||||
|
||||
class ContentOption extends TContentOption {
|
||||
private class ContentOption extends TContentOption {
|
||||
Content getContent() { this = TContentSome(result) }
|
||||
|
||||
predicate hasContent() { exists(this.getContent()) }
|
||||
@@ -678,6 +563,18 @@ class ReturnNodeExt extends Node {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() {
|
||||
this instanceof OutNode
|
||||
or
|
||||
this.(PostUpdateNode).getPreUpdateNode() instanceof ArgumentNode
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended return kind. A return kind describes how data can be returned
|
||||
* from a callable. This can either be through a returned value or an updated
|
||||
@@ -688,7 +585,7 @@ abstract class ReturnKindExt extends TReturnKindExt {
|
||||
abstract string toString();
|
||||
|
||||
/** Gets a node corresponding to data flow out of `call`. */
|
||||
abstract Node getAnOutNode(DataFlowCall call);
|
||||
abstract OutNodeExt getAnOutNode(DataFlowCall call);
|
||||
}
|
||||
|
||||
class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
@@ -700,7 +597,9 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
|
||||
override string toString() { result = kind.toString() }
|
||||
|
||||
override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) }
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
result = getAnOutNode(call, this.getKind())
|
||||
}
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
@@ -712,9 +611,9 @@ class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
|
||||
override PostUpdateNode getAnOutNode(DataFlowCall call) {
|
||||
override OutNodeExt getAnOutNode(DataFlowCall call) {
|
||||
exists(ArgumentNode arg |
|
||||
result.getPreUpdateNode() = arg and
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, this.getPosition())
|
||||
)
|
||||
}
|
||||
@@ -779,77 +678,58 @@ DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) {
|
||||
result = viableCallable(call) and cc instanceof CallContextReturn
|
||||
}
|
||||
|
||||
newtype TSummary =
|
||||
TSummaryVal() or
|
||||
TSummaryTaint() or
|
||||
TSummaryReadVal(Content f) or
|
||||
TSummaryReadTaint(Content f) or
|
||||
TSummaryTaintStore(Content f)
|
||||
|
||||
/**
|
||||
* A summary of flow through a callable. This can either be value-preserving
|
||||
* if no additional steps are used, taint-flow if at least one additional step
|
||||
* is used, or any one of those combined with a store or a read. Summaries
|
||||
* recorded at a return node are restricted to include at least one additional
|
||||
* step, as the value-based summaries are calculated independent of the
|
||||
* configuration.
|
||||
*/
|
||||
class Summary extends TSummary {
|
||||
string toString() {
|
||||
result = "Val" and this = TSummaryVal()
|
||||
or
|
||||
result = "Taint" and this = TSummaryTaint()
|
||||
or
|
||||
exists(Content f |
|
||||
result = "ReadVal " + f.toString() and this = TSummaryReadVal(f)
|
||||
or
|
||||
result = "ReadTaint " + f.toString() and this = TSummaryReadTaint(f)
|
||||
or
|
||||
result = "TaintStore " + f.toString() and this = TSummaryTaintStore(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with an additional step. */
|
||||
Summary additionalStep() {
|
||||
this = TSummaryVal() and result = TSummaryTaint()
|
||||
or
|
||||
this = TSummaryTaint() and result = TSummaryTaint()
|
||||
or
|
||||
exists(Content f | this = TSummaryReadVal(f) and result = TSummaryReadTaint(f))
|
||||
or
|
||||
exists(Content f | this = TSummaryReadTaint(f) and result = TSummaryReadTaint(f))
|
||||
}
|
||||
|
||||
/** Gets the summary that results from extending this with a read. */
|
||||
Summary readStep(Content f) { this = TSummaryVal() and result = TSummaryReadVal(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with a store. */
|
||||
Summary storeStep(Content f) { this = TSummaryTaint() and result = TSummaryTaintStore(f) }
|
||||
|
||||
/** Gets the summary that results from extending this with `step`. */
|
||||
bindingset[this, step]
|
||||
Summary compose(Summary step) {
|
||||
this = TSummaryVal() and result = step
|
||||
or
|
||||
this = TSummaryTaint() and
|
||||
(step = TSummaryTaint() or step = TSummaryTaintStore(_)) and
|
||||
result = step
|
||||
or
|
||||
exists(Content f |
|
||||
this = TSummaryReadVal(f) and step = TSummaryTaint() and result = TSummaryReadTaint(f)
|
||||
)
|
||||
or
|
||||
this = TSummaryReadTaint(_) and step = TSummaryTaint() and result = this
|
||||
}
|
||||
|
||||
/** Holds if this summary does not include any taint steps. */
|
||||
predicate isPartial() {
|
||||
this = TSummaryVal() or
|
||||
this = TSummaryReadVal(_)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
DataFlowType getErasedNodeTypeBound(Node n) { result = getErasedRepr(n.getTypeBound()) }
|
||||
|
||||
predicate readDirect = readStep/3;
|
||||
predicate read = readStep/3;
|
||||
|
||||
/** An optional Boolean value. */
|
||||
class BooleanOption extends TBooleanOption {
|
||||
string toString() {
|
||||
this = TBooleanNone() and result = "<none>"
|
||||
or
|
||||
this = TBooleanSome(any(boolean b | result = b.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
predicate headUsesContent(Content f) { this = TFrontHead(f) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
override string toString() {
|
||||
exists(DataFlowType t | this = TFrontNil(t) | result = ppReprType(t))
|
||||
}
|
||||
|
||||
override DataFlowType getType() { this = TFrontNil(result) }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
override string toString() { exists(Content f | this = TFrontHead(f) | result = f.toString()) }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(Content head | this = TFrontHead(head) | result = head.getContainerType())
|
||||
}
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
class AccessPathFrontOption extends TAccessPathFrontOption {
|
||||
string toString() {
|
||||
this = TAccessPathFrontNone() and result = "<none>"
|
||||
or
|
||||
this = TAccessPathFrontSome(any(AccessPathFront apf | result = apf.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,9 +81,6 @@ module LocalFlow {
|
||||
) {
|
||||
exactScope = false and
|
||||
(
|
||||
// Flow using library code
|
||||
libraryFlow(e1, e2, scope, isSuccessor, true)
|
||||
or
|
||||
e1 = e2.(ParenthesizedExpr).getExpr() and
|
||||
scope = e2 and
|
||||
isSuccessor = true
|
||||
@@ -244,39 +241,9 @@ module LocalFlow {
|
||||
nodeTo = TImplicitCapturedArgumentNode(call, def.getSourceVariable().getAssignable())
|
||||
)
|
||||
}
|
||||
|
||||
private Expr getALibraryFlowParentFrom(Expr exprFrom, Expr exprTo, boolean preservesValue) {
|
||||
libraryFlow(exprFrom, exprTo, preservesValue) and
|
||||
result = exprFrom
|
||||
or
|
||||
result.getAChildExpr() = getALibraryFlowParentFrom(exprFrom, exprTo, preservesValue)
|
||||
}
|
||||
|
||||
private Expr getALibraryFlowParentTo(Expr exprFrom, Expr exprTo, boolean preservesValue) {
|
||||
libraryFlow(exprFrom, exprTo, preservesValue) and
|
||||
result = exprTo
|
||||
or
|
||||
exists(Expr mid | mid = getALibraryFlowParentTo(exprFrom, exprTo, preservesValue) |
|
||||
result.getAChildExpr() = mid and
|
||||
not mid = getALibraryFlowParentFrom(exprFrom, exprTo, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
predicate libraryFlow(
|
||||
Expr exprFrom, Expr exprTo, Expr scope, boolean isSuccessor, boolean preservesValue
|
||||
) {
|
||||
// To not pollute the definitions in `LibraryTypeDataFlow.qll` with syntactic scope,
|
||||
// simply use the nearest common parent expression for `exprFrom` and `exprTo`
|
||||
scope = getALibraryFlowParentFrom(exprFrom, exprTo, preservesValue) and
|
||||
scope = getALibraryFlowParentTo(exprFrom, exprTo, preservesValue) and
|
||||
// Similarly, for simplicity allow following both forwards and backwards edges from
|
||||
// `exprFrom` to `exprTo`
|
||||
(isSuccessor = true or isSuccessor = false)
|
||||
}
|
||||
}
|
||||
|
||||
/** An argument of a C# call. */
|
||||
/** An argument of a C# call (including qualifier arguments). */
|
||||
private class Argument extends Expr {
|
||||
private Expr call;
|
||||
private int arg;
|
||||
@@ -292,39 +259,85 @@ private class Argument extends Expr {
|
||||
this = call.(DelegateCall).getArgument(arg)
|
||||
}
|
||||
|
||||
/** Holds if this expression is the `i`th argument of `c`. */
|
||||
/**
|
||||
* Holds if this expression is the `i`th argument of `c`.
|
||||
*
|
||||
* Qualifier arguments have index `-1`.
|
||||
*/
|
||||
predicate isArgumentOf(Expr c, int i) { c = call and i = arg }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an assignment of `src` to a non-static field or field-like
|
||||
* property `f` of `q`.
|
||||
* Holds if `e` is an assignment of `src` to field or property `c` of `q`.
|
||||
*/
|
||||
private predicate instanceFieldLikeAssign(Expr e, FieldLike f, Expr src, Expr q) {
|
||||
exists(FieldLikeAccess fa, AssignableDefinition def |
|
||||
private predicate fieldOrPropertyAssign(Expr e, Content c, Expr src, Expr q) {
|
||||
exists(FieldOrPropertyAccess fa, FieldOrProperty f, AssignableDefinition def |
|
||||
def.getTargetAccess() = fa and
|
||||
f = fa.getTarget().getSourceDeclaration() and
|
||||
not f.isStatic() and
|
||||
f = fa.getTarget() and
|
||||
c = f.getContent() and
|
||||
src = def.getSource() and
|
||||
q = fa.getQualifier() and
|
||||
e = def.getExpr()
|
||||
|
|
||||
f.isFieldLike() and
|
||||
f instanceof InstanceFieldOrProperty
|
||||
or
|
||||
exists(AccessPath ap |
|
||||
LibraryFlow::libraryFlow(_, _, ap, _, _, _) and
|
||||
ap.contains(f.getContent())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `oc` has an object initializer that assigns `src` to non-static field or
|
||||
* field-like property `f`.
|
||||
* Holds if `oc` has an object initializer that assigns `src` to field or
|
||||
* property `c`.
|
||||
*/
|
||||
private predicate instanceFieldLikeInit(ObjectCreation oc, FieldLike f, Expr src) {
|
||||
exists(MemberInitializer mi |
|
||||
private predicate fieldOrPropertyInit(ObjectCreation oc, Content c, Expr src) {
|
||||
exists(MemberInitializer mi, FieldOrProperty f |
|
||||
mi = oc.getInitializer().(ObjectInitializer).getAMemberInitializer() and
|
||||
f = mi.getInitializedMember().getSourceDeclaration() and
|
||||
not f.isStatic() and
|
||||
f = mi.getInitializedMember() and
|
||||
c = f.getContent() and
|
||||
src = mi.getRValue()
|
||||
|
|
||||
f.isFieldLike() and
|
||||
f instanceof InstanceFieldOrProperty
|
||||
or
|
||||
exists(AccessPath ap |
|
||||
LibraryFlow::libraryFlow(_, _, ap, _, _, _) and
|
||||
ap.contains(f.getContent())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Type getCSharpType(DotNet::Type t) {
|
||||
/** Holds if property `p1` overrides or implements source declaration property `p2`. */
|
||||
private predicate overridesOrImplementsSourceDecl(Property p1, Property p2) {
|
||||
p1.getOverridee*().getSourceDeclaration() = p2
|
||||
or
|
||||
p1.getAnUltimateImplementee().getSourceDeclaration() = p2
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e2` is an expression that reads field or property `c` from
|
||||
* expresion `e1`. This takes overriding into account for properties written
|
||||
* from library code.
|
||||
*/
|
||||
private predicate fieldOrPropertyRead(Expr e1, Content c, FieldOrPropertyRead e2) {
|
||||
e1 = e2.getQualifier() and
|
||||
exists(FieldOrProperty ret | c = ret.getContent() |
|
||||
ret.isFieldLike() and
|
||||
ret = e2.getTarget()
|
||||
or
|
||||
exists(AccessPath ap, Property target |
|
||||
LibraryFlow::libraryFlow(_, _, _, _, ap, _) and
|
||||
ap.contains(ret.getContent()) and
|
||||
target.getGetter() = e2.(PropertyCall).getARuntimeTarget() and
|
||||
overridesOrImplementsSourceDecl(target, ret)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
Type getCSharpType(DotNet::Type t) {
|
||||
result = t
|
||||
or
|
||||
result.matchesHandle(t)
|
||||
@@ -359,8 +372,7 @@ private module Cached {
|
||||
TSsaDefinitionNode(Ssa::Definition def) or
|
||||
TInstanceParameterNode(Callable c) { c.hasBody() and not c.(Modifiable).isStatic() } or
|
||||
TCilParameterNode(CIL::Parameter p) { p.getMethod().hasBody() } or
|
||||
TTaintedParameterNode(Parameter p) { explicitParameterNode(_, p) } or
|
||||
TTaintedReturnNode(ControlFlow::Nodes::ElementNode cfn) {
|
||||
TYieldReturnNode(ControlFlow::Nodes::ElementNode cfn) {
|
||||
any(Callable c).canYieldReturn(cfn.getElement())
|
||||
} or
|
||||
TImplicitCapturedArgumentNode(ControlFlow::Nodes::ElementNode cfn, LocalScopeVariable v) {
|
||||
@@ -374,6 +386,14 @@ private module Cached {
|
||||
cfn.getElement() instanceof DelegateArgumentToLibraryCallable and
|
||||
any(DelegateArgumentConfiguration x).hasExprPath(_, cfn, _, call)
|
||||
} or
|
||||
TImplicitDelegateArgumentNode(ControlFlow::Nodes::ElementNode cfn, int i, int j) {
|
||||
exists(Call call, CallableFlowSinkDelegateArg sink |
|
||||
LibraryFlow::libraryFlow(call, _, _, sink, _, _) and
|
||||
i = sink.getDelegateIndex() and
|
||||
j = sink.getDelegateParameterIndex() and
|
||||
call.getArgument(i).getAControlFlowNode() = cfn
|
||||
)
|
||||
} or
|
||||
TMallocNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof ObjectCreation } or
|
||||
TExprPostUpdateNode(ControlFlow::Nodes::ElementNode cfn) {
|
||||
exists(Argument a, Type t |
|
||||
@@ -386,13 +406,19 @@ private module Cached {
|
||||
t = any(TypeParameter tp | not tp.isValueType())
|
||||
)
|
||||
or
|
||||
instanceFieldLikeAssign(_, _, _, cfn.getElement())
|
||||
fieldOrPropertyAssign(_, _, _, cfn.getElement())
|
||||
or
|
||||
exists(TExprPostUpdateNode upd, FieldLikeAccess fla |
|
||||
exists(TExprPostUpdateNode upd, FieldOrPropertyAccess fla |
|
||||
upd = TExprPostUpdateNode(fla.getAControlFlowNode())
|
||||
|
|
||||
cfn.getElement() = fla.getQualifier()
|
||||
)
|
||||
} or
|
||||
TLibraryCodeNode(
|
||||
ControlFlow::Node callCfn, CallableFlowSource source, AccessPath sourceAp,
|
||||
CallableFlowSink sink, AccessPath sinkAp, boolean preservesValue
|
||||
) {
|
||||
LibraryFlow::libraryFlow(callCfn.getElement(), source, sourceAp, sink, sinkAp, preservesValue)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,11 +441,15 @@ private module Cached {
|
||||
or
|
||||
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
|
||||
or
|
||||
flowOutOfDelegateLibraryCall(nodeFrom, nodeTo, true)
|
||||
or
|
||||
flowThroughLibraryCallableOutRef(_, nodeFrom, nodeTo, true)
|
||||
or
|
||||
LocalFlow::localFlowStepCil(nodeFrom, nodeTo)
|
||||
or
|
||||
exists(LibraryCodeNode n | n.preservesValue() |
|
||||
n = nodeTo and
|
||||
nodeFrom = n.getPredecessor(AccessPath::empty())
|
||||
or
|
||||
n = nodeFrom and
|
||||
nodeTo = n.getSuccessor(AccessPath::empty())
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,25 +476,26 @@ private module Cached {
|
||||
|
||||
cached
|
||||
newtype TContent =
|
||||
TFieldLikeContent(FieldLike f) { not f.isStatic() and f.getSourceDeclaration() = f }
|
||||
TFieldContent(Field f) { f = f.getSourceDeclaration() } or
|
||||
TPropertyContent(Property p) { p = p.getSourceDeclaration() }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to
|
||||
* content `c`.
|
||||
*/
|
||||
cached
|
||||
predicate storeStepImpl(ExprNode node1, Content c, PostUpdateNode node2) {
|
||||
exists(StoreStepConfiguration x, Node preNode2 |
|
||||
preNode2 = node2.getPreUpdateNode() and
|
||||
predicate storeStepImpl(Node node1, Content c, Node node2) {
|
||||
exists(StoreStepConfiguration x, ExprNode preNode2 |
|
||||
preNode2 = node2.(PostUpdateNode).getPreUpdateNode() and
|
||||
x.hasNodePath(node1, preNode2) and
|
||||
instanceFieldLikeAssign(_, c.(FieldLikeContent).getField(), node1.asExpr(), preNode2.asExpr())
|
||||
fieldOrPropertyAssign(_, c, node1.asExpr(), preNode2.getExpr())
|
||||
)
|
||||
or
|
||||
exists(StoreStepConfiguration x |
|
||||
x.hasNodePath(node1, node2) and
|
||||
instanceFieldLikeInit(node2.(ObjectCreationNode).getExpr(), c.(FieldLikeContent).getField(),
|
||||
node1.asExpr())
|
||||
exists(StoreStepConfiguration x | x.hasNodePath(node1, node2) |
|
||||
fieldOrPropertyInit(node2.(ObjectCreationNode).getExpr(), c, node1.asExpr())
|
||||
)
|
||||
or
|
||||
node2 = node1.(LibraryCodeNode).getSuccessor(any(AccessPath ap | ap.getHead() = c))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,9 +505,10 @@ private module Cached {
|
||||
predicate readStepImpl(Node node1, Content c, Node node2) {
|
||||
exists(ReadStepConfiguration x |
|
||||
x.hasNodePath(node1, node2) and
|
||||
c.(FieldLikeContent).getField() =
|
||||
node2.asExpr().(FieldLikeRead).getTarget().getSourceDeclaration()
|
||||
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||
)
|
||||
or
|
||||
node1 = node2.(LibraryCodeNode).getPredecessor(any(AccessPath ap | ap.getHead() = c))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,19 +527,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a representative type for `t` for the purpose of pruning possible flow.
|
||||
*/
|
||||
cached
|
||||
DataFlowType getErasedRepr(DotNet::Type t) {
|
||||
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
|
||||
t0 = getCSharpType(t)
|
||||
or
|
||||
not exists(getCSharpType(t)) and
|
||||
t0 instanceof ObjectType
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if GVNs `t1` and `t2` may have a common sub type. Neither `t1` nor
|
||||
* `t2` are allowed to be type parameters.
|
||||
@@ -607,44 +626,6 @@ private module ParameterNodes {
|
||||
override string toString() { result = "this" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A tainted parameter. Tainted parameters are a mere implementation detail, used
|
||||
* to restrict tainted flow into callables to just taint tracking (just like flow
|
||||
* out of `TaintedReturnNode`s is restricted to taint tracking).
|
||||
*/
|
||||
class TaintedParameterNode extends ParameterNode, TTaintedParameterNode {
|
||||
private Parameter parameter;
|
||||
|
||||
TaintedParameterNode() { this = TTaintedParameterNode(parameter) }
|
||||
|
||||
/** Gets the underlying parameter node. */
|
||||
ExplicitParameterNode getUnderlyingNode() { explicitParameterNode(result, parameter) }
|
||||
|
||||
// `getParameter()` is explicitly *not* overriden to return `parameter`,
|
||||
// as that would otherwise enable tainted parameters to accidentally be
|
||||
// used by users of the library
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
c = parameter.getCallable() and
|
||||
// we model tainted parameters as if they had been extra parameters after
|
||||
// the actual parameters
|
||||
i = parameter.getPosition() + c.getNumberOfParameters()
|
||||
}
|
||||
|
||||
override Callable getEnclosingCallable() {
|
||||
result = this.getUnderlyingNode().getEnclosingCallable()
|
||||
}
|
||||
|
||||
override Type getType() {
|
||||
// Taint tracking steps are allowed to change the type of the tracked object,
|
||||
// so `result = this.getUnderlyingNode().getType()` is too restrictive
|
||||
result instanceof ObjectType
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getUnderlyingNode().getLocation() }
|
||||
|
||||
override string toString() { result = this.getUnderlyingNode().toString() }
|
||||
}
|
||||
|
||||
module ImplicitCapturedParameterNodeImpl {
|
||||
/** An implicit entry definition for a captured variable. */
|
||||
class SsaCapturedEntryDefinition extends Ssa::ImplicitEntryDefinition {
|
||||
@@ -688,7 +669,7 @@ private module ParameterNodes {
|
||||
* An implicit parameter is added in order to be able to track flow into
|
||||
* capturing callables, as if an explicit `ref` parameter had been used:
|
||||
*
|
||||
* ```
|
||||
* ```csharp
|
||||
* void M() { void M() {
|
||||
* int i = 0; int i = 0;
|
||||
* void In() { => void In(ref int i0) { // implicit i0 parameter
|
||||
@@ -741,47 +722,6 @@ private module ArgumentNodes {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of a call, which resolves to a library callable
|
||||
* that is known to forward `arg` into the `i`th parameter of a supplied
|
||||
* delegate `delegate`.
|
||||
*
|
||||
* For example, in
|
||||
*
|
||||
* ```
|
||||
* x.Select(Foo);
|
||||
* ```
|
||||
*
|
||||
* `arg = x`, `i = 0`, `call = x.Select(Foo)`, and `delegate = Foo`.
|
||||
*/
|
||||
private predicate flowIntoCallableLibraryCall(
|
||||
ExplicitArgumentNode arg, ImplicitDelegateDataFlowCall delegate, int i
|
||||
) {
|
||||
exists(DataFlowCall call, int j, boolean preservesValue |
|
||||
preservesValue = true and i = j
|
||||
or
|
||||
preservesValue = false and i = j + delegate.getNumberOfDelegateParameters()
|
||||
|
|
||||
exists(DelegateArgumentConfiguration x, Call callExpr, ExprNode argExpr |
|
||||
x
|
||||
.hasExprPath(argExpr.getExpr(), argExpr.getControlFlowNode(), callExpr,
|
||||
call.getControlFlowNode())
|
||||
|
|
||||
exists(int k |
|
||||
libraryFlowDelegateCallIn(callExpr, _, argExpr.getExpr(), preservesValue, j, k) and
|
||||
arg = argExpr and
|
||||
delegate.isArgumentOf(call, k)
|
||||
)
|
||||
or
|
||||
exists(int k, int l | libraryFlowDelegateCallOutIn(callExpr, _, preservesValue, k, j, l) |
|
||||
delegate.isArgumentOf(call, l) and
|
||||
arg.(ImplicitDelegateOutNode).isArgumentOf(call, k) and
|
||||
arg = TImplicitDelegateOutNode(argExpr.getControlFlowNode(), _)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private class ArgumentConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
ArgumentConfiguration() { this = "ArgumentConfiguration" }
|
||||
|
||||
@@ -801,10 +741,6 @@ private module ArgumentNodes {
|
||||
this.asExpr() instanceof Argument
|
||||
or
|
||||
this.asExpr() = any(CIL::Call call).getAnArgument()
|
||||
or
|
||||
libraryFlowDelegateCallIn(_, _, this.asExpr(), _, _, _)
|
||||
or
|
||||
this.(ImplicitDelegateOutNode).isArgumentOf(_, _)
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
@@ -821,8 +757,6 @@ private module ArgumentNodes {
|
||||
c = call.getExpr() and
|
||||
arg = c.getArgument(pos)
|
||||
)
|
||||
or
|
||||
flowIntoCallableLibraryCall(this, call, pos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -833,7 +767,7 @@ private module ArgumentNodes {
|
||||
* An implicit node is added in order to be able to track flow into capturing
|
||||
* callables, as if an explicit parameter had been used:
|
||||
*
|
||||
* ```
|
||||
* ```csharp
|
||||
* void M() { void M() {
|
||||
* int i = 0; int i = 0;
|
||||
* void Out() { i = 1; } => void Out(ref int i0) { i0 = 1; }
|
||||
@@ -913,6 +847,43 @@ private module ArgumentNodes {
|
||||
|
||||
override string toString() { result = "malloc" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that represents an implicit argument of an implicit delegate
|
||||
* call in library code. For example, in
|
||||
*
|
||||
* ```csharp
|
||||
* x.Select(Foo);
|
||||
* ```
|
||||
*
|
||||
* `x` is an implicit argument of the implicit call to `Foo`.
|
||||
*/
|
||||
class ImplicitDelegateArgumentNode extends ArgumentNode, TImplicitDelegateArgumentNode {
|
||||
private ControlFlow::Node cfn;
|
||||
private int delegateIndex;
|
||||
private int parameterIndex;
|
||||
|
||||
ImplicitDelegateArgumentNode() {
|
||||
this = TImplicitDelegateArgumentNode(cfn, delegateIndex, parameterIndex)
|
||||
}
|
||||
|
||||
private ImplicitDelegateDataFlowCall getDelegateCall() { result.getControlFlowNode() = cfn }
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
call = this.getDelegateCall() and
|
||||
pos = parameterIndex
|
||||
}
|
||||
|
||||
override Callable getEnclosingCallable() { result = cfn.getEnclosingCallable() }
|
||||
|
||||
override Type getType() {
|
||||
result = this.getDelegateCall().getDelegateParameterType(parameterIndex)
|
||||
}
|
||||
|
||||
override Location getLocation() { result = cfn.getLocation() }
|
||||
|
||||
override string toString() { result = "[implicit argument " + parameterIndex + "] " + cfn }
|
||||
}
|
||||
}
|
||||
|
||||
import ArgumentNodes
|
||||
@@ -964,31 +935,29 @@ private module ReturnNodes {
|
||||
}
|
||||
|
||||
/**
|
||||
* A tainted return node. Tainted return nodes are a mere implementation detail,
|
||||
* used to restrict tainted flow out of callables to just taint tracking (just
|
||||
* like flow in to `TaintedReturnParameter`s is restricted to taint tracking).
|
||||
* A `yield return` node. A node is synthesized in order to be able to model
|
||||
* `yield return`s as stores into collections, i.e., there is flow from `e`
|
||||
* to `yield return e [e]`.
|
||||
*/
|
||||
class TaintedReturnNode extends ReturnNode, TTaintedReturnNode {
|
||||
class YieldReturnNode extends ReturnNode, PostUpdateNode, TYieldReturnNode {
|
||||
private ControlFlow::Nodes::ElementNode cfn;
|
||||
private YieldReturnStmt yrs;
|
||||
|
||||
TaintedReturnNode() { this = TTaintedReturnNode(cfn) }
|
||||
YieldReturnNode() { this = TYieldReturnNode(cfn) and yrs.getExpr().getAControlFlowNode() = cfn }
|
||||
|
||||
/** Gets the underlying return node. */
|
||||
ExprReturnNode getUnderlyingNode() { result.getControlFlowNode() = cfn }
|
||||
YieldReturnStmt getYieldReturnStmt() { result = yrs }
|
||||
|
||||
override YieldReturnKind getKind() { any() }
|
||||
|
||||
override Callable getEnclosingCallable() {
|
||||
result = this.getUnderlyingNode().getEnclosingCallable()
|
||||
}
|
||||
override ExprNode getPreUpdateNode() { result.getControlFlowNode() = cfn }
|
||||
|
||||
override Type getType() {
|
||||
result = this.getUnderlyingNode().getEnclosingCallable().getReturnType()
|
||||
}
|
||||
override Callable getEnclosingCallable() { result = yrs.getEnclosingCallable() }
|
||||
|
||||
override Location getLocation() { result = this.getUnderlyingNode().getLocation() }
|
||||
override Type getType() { result = yrs.getEnclosingCallable().getReturnType() }
|
||||
|
||||
override string toString() { result = this.getUnderlyingNode().toString() }
|
||||
override Location getLocation() { result = yrs.getLocation() }
|
||||
|
||||
override string toString() { result = yrs.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -998,7 +967,7 @@ private module ReturnNodes {
|
||||
* An implicit node is added in order to be able to track flow out of capturing
|
||||
* callables, as if an explicit `ref` parameter had been used:
|
||||
*
|
||||
* ```
|
||||
* ```csharp
|
||||
* void M() { void M() {
|
||||
* int i = 0; int i = 0;
|
||||
* void Out() { void Out(ref int i0) {
|
||||
@@ -1188,68 +1157,290 @@ private module OutNodes {
|
||||
|
||||
import OutNodes
|
||||
|
||||
private class FlowThroughLibraryCallableOutRefConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
FlowThroughLibraryCallableOutRefConfiguration() {
|
||||
this = "FlowThroughLibraryCallableOutRefConfiguration"
|
||||
}
|
||||
|
||||
override predicate candidateDef(
|
||||
Expr e, AssignableDefinition def, ControlFlowElement scope, boolean exactScope,
|
||||
boolean isSuccessor
|
||||
/**
|
||||
* Provides predicates related to flow through library code, based on
|
||||
* the flow summaries in `LibraryTypeDataFlow.qll`.
|
||||
*/
|
||||
module LibraryFlow {
|
||||
pragma[nomagic]
|
||||
private ValueOrRefType getPreciseSourceProperty0(
|
||||
Call call, CallableFlowSource source, AccessPath sourceAp, Property p
|
||||
) {
|
||||
exists(MethodCall mc, Parameter outRef | libraryFlowOutRef(mc, e, outRef, _) |
|
||||
def.getTargetAccess() = mc.getArgumentForParameter(outRef) and
|
||||
def instanceof AssignableDefinitions::OutRefDefinition and
|
||||
scope = mc and
|
||||
isSuccessor = true and
|
||||
exactScope = false
|
||||
exists(LibraryTypeDataFlow ltdf, Property p0 |
|
||||
ltdf.callableFlow(source, sourceAp, _, _, call.getTarget().getSourceDeclaration()) and
|
||||
sourceAp = AccessPath::property(p0) and
|
||||
overridesOrImplementsSourceDecl(p, p0) and
|
||||
result = source.getSourceType(call)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a precise source property for source `source` and access path `sourceAp`,
|
||||
* in the context of `call`. For example, in
|
||||
*
|
||||
* ```csharp
|
||||
* var list = new List<string>();
|
||||
* var count = list.Count();
|
||||
* ```
|
||||
*
|
||||
* the step from `list` to `list.Count()`, which may be modeled as a read of
|
||||
* the `Count` property from `ICollection<T>`, can be strengthened to be a
|
||||
* read of the `Count` property from `List<T>`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Property getPreciseSourceProperty(
|
||||
Call call, CallableFlowSource source, AccessPath sourceAp
|
||||
) {
|
||||
getPreciseSourceProperty0(call, source, sourceAp, result).hasMember(result)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ValueOrRefType getPreciseSinkProperty0(
|
||||
Call call, CallableFlowSink sink, AccessPath sinkAp, Property p
|
||||
) {
|
||||
exists(LibraryTypeDataFlow ltdf, Property p0 |
|
||||
ltdf.callableFlow(_, _, sink, sinkAp, call.getTarget().getSourceDeclaration()) and
|
||||
sinkAp = AccessPath::property(p0) and
|
||||
overridesOrImplementsSourceDecl(p, p0) and
|
||||
result = sink.getSinkType(call)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a precise sink property for sink `sink` and access path `sinkAp`,
|
||||
* in the context of `call`. For example, in
|
||||
*
|
||||
* ```csharp
|
||||
* var list = new List<string>();
|
||||
* list.Add("taint");
|
||||
* var enumerator = list.getEnumerator();
|
||||
* ```
|
||||
*
|
||||
* the step from `list` to `list.getEnumerator()`, which may be modeled as a
|
||||
* read of a collection element followed by a store into the `Current`
|
||||
* property, can be strengthened to be a store into the `Current` property
|
||||
* from `List<T>.Enumerator`, rather than the generic `Current` property
|
||||
* from `IEnumerator<T>`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private Property getPreciseSinkProperty(Call call, CallableFlowSink sink, AccessPath sinkAp) {
|
||||
getPreciseSinkProperty0(call, sink, sinkAp, result).hasMember(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from a node of kind `source` to a node of kind `sink`,
|
||||
* using a call to a library callable.
|
||||
*
|
||||
* `sourceAp` describes the contents of the source node that flows to the sink
|
||||
* (if any), and `sinkAp` describes the contents of the sink that it flows to
|
||||
* (if any).
|
||||
*
|
||||
* `preservesValue = false` implies that both `sourceAp` and `sinkAp` are empty.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate libraryFlow(
|
||||
Call call, CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink,
|
||||
AccessPath sinkAp, boolean preservesValue
|
||||
) {
|
||||
exists(LibraryTypeDataFlow ltdf, SourceDeclarationCallable c |
|
||||
c = call.getTarget().getSourceDeclaration()
|
||||
|
|
||||
ltdf.callableFlow(source, sink, c, preservesValue) and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sinkAp = AccessPath::empty()
|
||||
or
|
||||
preservesValue = true and
|
||||
exists(AccessPath sourceAp0, AccessPath sinkAp0 |
|
||||
ltdf.callableFlow(source, sourceAp0, sink, sinkAp0, c) and
|
||||
(
|
||||
not sourceAp0 = AccessPath::property(_) and
|
||||
sourceAp = sourceAp0
|
||||
or
|
||||
exists(Property p |
|
||||
overridesOrImplementsSourceDecl(p,
|
||||
getPreciseSourceProperty(call, source, sourceAp0).getSourceDeclaration()) and
|
||||
sourceAp = AccessPath::property(p)
|
||||
)
|
||||
) and
|
||||
(
|
||||
not sinkAp0 = AccessPath::property(_) and
|
||||
sinkAp = sinkAp0
|
||||
or
|
||||
sinkAp = AccessPath::property(getPreciseSinkProperty(call, sink, sinkAp0))
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class LibrarySourceConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
LibrarySourceConfiguration() { this = "LibrarySourceConfiguration" }
|
||||
|
||||
override predicate candidate(
|
||||
Expr e1, Expr e2, ControlFlowElement scope, boolean exactScope, boolean isSuccessor
|
||||
) {
|
||||
exists(CallableFlowSource source |
|
||||
libraryFlow(e2, source, _, _, _, _) and
|
||||
e1 = source.getSource(e2) and
|
||||
scope = e2 and
|
||||
exactScope = false and
|
||||
isSuccessor = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class LibrarySinkConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
LibrarySinkConfiguration() { this = "LibrarySinkConfiguration" }
|
||||
|
||||
override predicate candidate(
|
||||
Expr e1, Expr e2, ControlFlowElement scope, boolean exactScope, boolean isSuccessor
|
||||
) {
|
||||
exists(CallableFlowSink sink |
|
||||
libraryFlow(e1, _, _, sink, _, _) and
|
||||
e2 = sink.getSink(e1) and
|
||||
scope = e1 and
|
||||
exactScope = false and
|
||||
isSuccessor = false
|
||||
)
|
||||
}
|
||||
|
||||
override predicate candidateDef(
|
||||
Expr e, AssignableDefinition def, ControlFlowElement scope, boolean exactScope,
|
||||
boolean isSuccessor
|
||||
) {
|
||||
exists(CallableFlowSinkArg sink |
|
||||
libraryFlow(e, _, _, sink, _, _) and
|
||||
scope = e and
|
||||
exactScope = false and
|
||||
isSuccessor = true and
|
||||
def.getTargetAccess() = sink.getArgument(e) and
|
||||
def instanceof AssignableDefinitions::OutRefDefinition
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of the method call `mc`, where the target
|
||||
* of `mc` is a library callable that forwards `arg` to an `out`/`ref` argument
|
||||
* `node`. Example:
|
||||
*
|
||||
* ```
|
||||
* int i;
|
||||
* Int32.TryParse("42", out i);
|
||||
* ```
|
||||
*
|
||||
* `mc = Int32.TryParse("42", out i)`, `arg = "42"`, and `node` is the access
|
||||
* to `i` in `out i`.
|
||||
*/
|
||||
predicate flowThroughLibraryCallableOutRef(
|
||||
MethodCall mc, ExprNode arg, SsaDefinitionNode node, boolean preservesValue
|
||||
) {
|
||||
libraryFlowOutRef(mc, arg.getExpr(), _, preservesValue) and
|
||||
any(FlowThroughLibraryCallableOutRefConfiguration x).hasNodePath(arg, node)
|
||||
/** A data-flow node used to model flow through library code. */
|
||||
class LibraryCodeNode extends Node, TLibraryCodeNode {
|
||||
private ControlFlow::Node callCfn;
|
||||
private CallableFlowSource source;
|
||||
private AccessPath sourceAp;
|
||||
private CallableFlowSink sink;
|
||||
private AccessPath sinkAp;
|
||||
private boolean preservesValue;
|
||||
|
||||
LibraryCodeNode() {
|
||||
this = TLibraryCodeNode(callCfn, source, sourceAp, sink, sinkAp, preservesValue)
|
||||
}
|
||||
|
||||
/** Holds if this node is part of a value-preserving library step. */
|
||||
predicate preservesValue() { preservesValue = true }
|
||||
|
||||
/**
|
||||
* Gets the predecessor of this library-code node. The head of `ap` describes
|
||||
* the content that is read from when entering this node (if any).
|
||||
*/
|
||||
Node getPredecessor(AccessPath ap) {
|
||||
ap = sourceAp and
|
||||
(
|
||||
// The source is either an argument or a qualifier, for example
|
||||
// `s` in `int.Parse(s)`
|
||||
exists(LibraryFlow::LibrarySourceConfiguration x, Call call |
|
||||
callCfn = call.getAControlFlowNode() and
|
||||
x.hasExprPath(source.getSource(call), result.(ExprNode).getControlFlowNode(), _, callCfn)
|
||||
)
|
||||
or
|
||||
// The source is the output of a supplied delegate argument, for
|
||||
// example the output of `Foo` in `new Lazy(Foo)`
|
||||
exists(DataFlowCall call, int pos |
|
||||
pos = source.(CallableFlowSourceDelegateArg).getArgumentIndex() and
|
||||
result.(ImplicitDelegateOutNode).isArgumentOf(call, pos) and
|
||||
callCfn = call.getControlFlowNode()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the successor of this library-code node. The head of `ap` describes
|
||||
* the content that is stored into when leaving this node (if any).
|
||||
*/
|
||||
Node getSuccessor(AccessPath ap) {
|
||||
ap = sinkAp and
|
||||
(
|
||||
exists(LibraryFlow::LibrarySinkConfiguration x, Call call, ExprNode e |
|
||||
callCfn = call.getAControlFlowNode() and
|
||||
x.hasExprPath(_, callCfn, sink.getSink(call), e.getControlFlowNode())
|
||||
|
|
||||
// The sink is an ordinary return value, for example `int.Parse(s)`
|
||||
sink instanceof CallableFlowSinkReturn and
|
||||
result = e
|
||||
or
|
||||
// The sink is a qualifier, for example `list` in `list.Add(x)`
|
||||
sink instanceof CallableFlowSinkQualifier and
|
||||
if sinkAp = AccessPath::empty()
|
||||
then result = e
|
||||
else result.(ExprPostUpdateNode).getPreUpdateNode() = e
|
||||
)
|
||||
or
|
||||
// The sink is an `out`/`ref` argument, for example `out i` in
|
||||
// `int.TryParse(s, out i)`
|
||||
exists(LibraryFlow::LibrarySinkConfiguration x, OutRefReturnKind k |
|
||||
result =
|
||||
any(ParamOutNode out |
|
||||
out.getCall(k).getControlFlowNode() = callCfn and
|
||||
sink.(CallableFlowSinkArg).getArgumentIndex() = k.getPosition() and
|
||||
x.hasDefPath(_, callCfn, out.getDefinition(), _)
|
||||
)
|
||||
)
|
||||
or
|
||||
// The sink is a parameter of a supplied delegate argument, for example
|
||||
// the parameter of `Foo` in `list.Select(Foo)`.
|
||||
//
|
||||
// This is implemented using a node that represents the implicit argument
|
||||
// (`ImplicitDelegateArgumentNode`) of the implicit call
|
||||
// (`ImplicitDelegateDataFlowCall`) to `Foo`.
|
||||
exists(
|
||||
DataFlowCall call, ImplicitDelegateDataFlowCall dcall, int delegateIndex, int parameterIndex
|
||||
|
|
||||
sink =
|
||||
any(CallableFlowSinkDelegateArg s |
|
||||
delegateIndex = s.getDelegateIndex() and
|
||||
parameterIndex = s.getDelegateParameterIndex()
|
||||
) and
|
||||
result = TImplicitDelegateArgumentNode(dcall.getControlFlowNode(), _, parameterIndex) and
|
||||
dcall.isArgumentOf(call, delegateIndex) and
|
||||
callCfn = call.getControlFlowNode()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Callable getEnclosingCallable() { result = callCfn.getEnclosingCallable() }
|
||||
|
||||
override DataFlowType getTypeBound() {
|
||||
preservesValue = true and
|
||||
sourceAp = AccessPath::empty() and
|
||||
result = this.getPredecessor(_).getTypeBound()
|
||||
or
|
||||
result = sourceAp.getHead().getType()
|
||||
or
|
||||
preservesValue = false and
|
||||
result = this.getSuccessor(_).getTypeBound()
|
||||
}
|
||||
|
||||
override Location getLocation() { result = callCfn.getLocation() }
|
||||
|
||||
override string toString() { result = "[library code] " + callCfn }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the output from the delegate `delegate` flows to `out`. The delegate
|
||||
* is passed as an argument to a library callable, which invokes the delegate.
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* x.Select(Foo);
|
||||
* ```
|
||||
*
|
||||
* `delegate = Foo`, `out = x.Select(Foo)`, and `preservesValue = false`.
|
||||
*/
|
||||
predicate flowOutOfDelegateLibraryCall(
|
||||
ImplicitDelegateOutNode delegate, ExprOutNode out, boolean preservesValue
|
||||
) {
|
||||
exists(DataFlowCall call, int i |
|
||||
libraryFlowDelegateCallOut(call.getExpr(), _, out.getExpr(), preservesValue, i) and
|
||||
delegate.isArgumentOf(call, i) and
|
||||
out.getControlFlowNode() = call.getControlFlowNode()
|
||||
)
|
||||
}
|
||||
/** A field or a property. */
|
||||
private class FieldOrProperty extends Assignable, Modifiable {
|
||||
FieldOrProperty() {
|
||||
this instanceof Field
|
||||
or
|
||||
this instanceof Property
|
||||
}
|
||||
|
||||
private class FieldLike extends Assignable, Modifiable {
|
||||
FieldLike() {
|
||||
/** Holds if this is either a field or a field-like property. */
|
||||
predicate isFieldLike() {
|
||||
this instanceof Field or
|
||||
this =
|
||||
any(Property p |
|
||||
@@ -1261,42 +1452,54 @@ private class FieldLike extends Assignable, Modifiable {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the content that matches this field or property. */
|
||||
Content getContent() {
|
||||
result.(FieldContent).getField() = this.getSourceDeclaration()
|
||||
or
|
||||
result.(PropertyContent).getProperty() = this.getSourceDeclaration()
|
||||
}
|
||||
}
|
||||
|
||||
private class FieldLikeAccess extends AssignableAccess, QualifiableExpr {
|
||||
FieldLikeAccess() { this.getTarget() instanceof FieldLike }
|
||||
private class InstanceFieldOrProperty extends FieldOrProperty {
|
||||
InstanceFieldOrProperty() { not this.isStatic() }
|
||||
}
|
||||
|
||||
private class FieldLikeRead extends FieldLikeAccess, AssignableRead { }
|
||||
private class FieldOrPropertyAccess extends AssignableAccess, QualifiableExpr {
|
||||
FieldOrPropertyAccess() { this.getTarget() instanceof FieldOrProperty }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the field-like read `flr` is not completely determined by explicit
|
||||
* SSA updates.
|
||||
*/
|
||||
private predicate hasNonlocalValue(FieldLikeRead flr) {
|
||||
flr = any(Ssa::ImplicitUntrackedDefinition udef).getARead()
|
||||
or
|
||||
exists(Ssa::Definition def, Ssa::ImplicitDefinition idef |
|
||||
def.getARead() = flr and
|
||||
idef = def.getAnUltimateDefinition()
|
||||
|
|
||||
idef instanceof Ssa::ImplicitEntryDefinition or
|
||||
idef instanceof Ssa::ImplicitCallDefinition
|
||||
)
|
||||
private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead {
|
||||
/**
|
||||
* Holds if this field-like read is not completely determined by explicit
|
||||
* SSA updates.
|
||||
*/
|
||||
predicate hasNonlocalValue() {
|
||||
this = any(Ssa::ImplicitUntrackedDefinition udef).getARead()
|
||||
or
|
||||
exists(Ssa::Definition def, Ssa::ImplicitDefinition idef |
|
||||
def.getARead() = this and
|
||||
idef = def.getAnUltimateDefinition()
|
||||
|
|
||||
idef instanceof Ssa::ImplicitEntryDefinition or
|
||||
idef instanceof Ssa::ImplicitCallDefinition
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A write to a static field/property. */
|
||||
private class StaticFieldLikeJumpNode extends NonLocalJumpNode, ExprNode {
|
||||
FieldLike fl;
|
||||
FieldLikeRead flr;
|
||||
FieldOrProperty fl;
|
||||
FieldOrPropertyRead flr;
|
||||
ExprNode succ;
|
||||
|
||||
StaticFieldLikeJumpNode() {
|
||||
fl.isStatic() and
|
||||
fl.isFieldLike() and
|
||||
fl.getAnAssignedValue() = this.getExpr() and
|
||||
fl.getAnAccess() = flr and
|
||||
flr = succ.getExpr() and
|
||||
hasNonlocalValue(flr)
|
||||
flr.hasNonlocalValue()
|
||||
}
|
||||
|
||||
override ExprNode getAJumpSuccessor(boolean preservesValue) {
|
||||
@@ -1306,41 +1509,6 @@ private class StaticFieldLikeJumpNode extends NonLocalJumpNode, ExprNode {
|
||||
|
||||
predicate jumpStep = jumpStepImpl/2;
|
||||
|
||||
/**
|
||||
* A reference contained in an object. Currently limited to instance fields
|
||||
* and field-like instance properties.
|
||||
*/
|
||||
class Content extends TContent {
|
||||
/** Gets a textual representation of this content. */
|
||||
abstract string toString();
|
||||
|
||||
abstract Location getLocation();
|
||||
|
||||
/** Gets the type of the object containing this content. */
|
||||
abstract DataFlowType getContainerType();
|
||||
|
||||
/** Gets the type of this content. */
|
||||
abstract DataFlowType getType();
|
||||
}
|
||||
|
||||
private class FieldLikeContent extends Content, TFieldLikeContent {
|
||||
private FieldLike f;
|
||||
|
||||
FieldLikeContent() { this = TFieldLikeContent(f) }
|
||||
|
||||
FieldLike getField() { result = f }
|
||||
|
||||
override string toString() { result = f.toString() }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
|
||||
override DataFlowType getContainerType() {
|
||||
result = Gvn::getGlobalValueNumber(f.getDeclaringType())
|
||||
}
|
||||
|
||||
override DataFlowType getType() { result = Gvn::getGlobalValueNumber(f.getType()) }
|
||||
}
|
||||
|
||||
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
StoreStepConfiguration() { this = "StoreStepConfiguration" }
|
||||
|
||||
@@ -1349,11 +1517,11 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
|
||||
) {
|
||||
exactScope = false and
|
||||
isSuccessor = false and
|
||||
instanceFieldLikeAssign(scope, _, e1, e2)
|
||||
fieldOrPropertyAssign(scope, _, e1, e2)
|
||||
or
|
||||
exactScope = false and
|
||||
isSuccessor = false and
|
||||
instanceFieldLikeInit(e2, _, e1) and
|
||||
fieldOrPropertyInit(e2, _, e1) and
|
||||
scope = e2
|
||||
}
|
||||
}
|
||||
@@ -1368,7 +1536,7 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
|
||||
) {
|
||||
exactScope = false and
|
||||
isSuccessor = true and
|
||||
e1 = e2.(FieldLikeRead).getQualifier() and
|
||||
fieldOrPropertyRead(e1, _, e2) and
|
||||
scope = e2
|
||||
}
|
||||
}
|
||||
@@ -1432,7 +1600,7 @@ private module PostUpdateNodes {
|
||||
override MallocNode getPreUpdateNode() { this = TExprNode(result.getControlFlowNode()) }
|
||||
}
|
||||
|
||||
private class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
|
||||
class ExprPostUpdateNode extends PostUpdateNode, TExprPostUpdateNode {
|
||||
private ControlFlow::Nodes::ElementNode cfn;
|
||||
|
||||
ExprPostUpdateNode() { this = TExprPostUpdateNode(cfn) }
|
||||
@@ -1508,3 +1676,6 @@ int accessPathLimit() { result = 3 }
|
||||
* This predicate is only used for consistency checks.
|
||||
*/
|
||||
predicate isImmutableOrUnobservable(Node n) { none() }
|
||||
|
||||
pragma[inline]
|
||||
DataFlowType getErasedRepr(DataFlowType t) { result = t }
|
||||
|
||||
@@ -5,6 +5,7 @@ private import DataFlowDispatch
|
||||
private import DataFlowPrivate
|
||||
private import semmle.code.csharp.Caching
|
||||
private import semmle.code.csharp.controlflow.Guards
|
||||
private import semmle.code.csharp.Unification
|
||||
|
||||
/**
|
||||
* An element, viewed as a node in a data flow graph. Either an expression
|
||||
@@ -40,8 +41,17 @@ class Node extends TNode {
|
||||
cached
|
||||
DotNet::Type getType() { none() }
|
||||
|
||||
/** Gets an upper bound on the type of this node. */
|
||||
DotNet::Type getTypeBound() { result = this.getType() } // stub implementation
|
||||
/** INTERNAL: Do not use. Gets an upper bound on the type of this node. */
|
||||
cached
|
||||
DataFlowType getTypeBound() {
|
||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
||||
exists(Type t0 | result = Gvn::getGlobalValueNumber(t0) |
|
||||
t0 = getCSharpType(this.getType())
|
||||
or
|
||||
not exists(getCSharpType(this.getType())) and
|
||||
t0 instanceof ObjectType
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the enclosing callable of this node. */
|
||||
cached
|
||||
@@ -136,8 +146,7 @@ class ParameterNode extends Node {
|
||||
this.(SsaDefinitionNode).getDefinition() instanceof
|
||||
ImplicitCapturedParameterNodeImpl::SsaCapturedEntryDefinition or
|
||||
this = TInstanceParameterNode(_) or
|
||||
this = TCilParameterNode(_) or
|
||||
this = TTaintedParameterNode(_)
|
||||
this = TCilParameterNode(_)
|
||||
}
|
||||
|
||||
/** Gets the parameter corresponding to this node, if any. */
|
||||
@@ -231,3 +240,60 @@ class BarrierGuard extends Guard {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference contained in an object. This is either a field or a property.
|
||||
*/
|
||||
class Content extends TContent {
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this content. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets the type of the object containing this content. */
|
||||
DataFlowType getContainerType() { none() }
|
||||
|
||||
/** Gets the type of this content. */
|
||||
DataFlowType getType() { none() }
|
||||
}
|
||||
|
||||
/** A reference to a field. */
|
||||
class FieldContent extends Content, TFieldContent {
|
||||
private Field f;
|
||||
|
||||
FieldContent() { this = TFieldContent(f) }
|
||||
|
||||
/** Gets the field that is referenced. */
|
||||
Field getField() { result = f }
|
||||
|
||||
override string toString() { result = f.toString() }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
|
||||
override DataFlowType getContainerType() {
|
||||
result = Gvn::getGlobalValueNumber(f.getDeclaringType())
|
||||
}
|
||||
|
||||
override DataFlowType getType() { result = Gvn::getGlobalValueNumber(f.getType()) }
|
||||
}
|
||||
|
||||
/** A reference to a property. */
|
||||
class PropertyContent extends Content, TPropertyContent {
|
||||
private Property p;
|
||||
|
||||
PropertyContent() { this = TPropertyContent(p) }
|
||||
|
||||
/** Gets the property that is referenced. */
|
||||
Property getProperty() { result = p }
|
||||
|
||||
override string toString() { result = p.toString() }
|
||||
|
||||
override Location getLocation() { result = p.getLocation() }
|
||||
|
||||
override DataFlowType getContainerType() {
|
||||
result = Gvn::getGlobalValueNumber(p.getDeclaringType())
|
||||
}
|
||||
|
||||
override DataFlowType getType() { result = Gvn::getGlobalValueNumber(p.getType()) }
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ library class DelegateArgumentToLibraryCallable extends Expr {
|
||||
/** Gets the call that this argument belongs to. */
|
||||
Call getCall() { result = call }
|
||||
|
||||
/** Gets the index of this delegate argument in the call. */
|
||||
int getArgumentIndex() { this = this.getCall().getArgument(result) }
|
||||
|
||||
/** Gets the delegate type of this argument. */
|
||||
DelegateType getDelegateType() { result = dt }
|
||||
|
||||
|
||||
@@ -45,9 +45,6 @@ private class LocalTaintExprStepConfiguration extends ControlFlowReachabilityCon
|
||||
) {
|
||||
exactScope = false and
|
||||
(
|
||||
// Taint propagation using library code
|
||||
LocalFlow::libraryFlow(e1, e2, scope, isSuccessor, false)
|
||||
or
|
||||
// Taint from assigned value to element qualifier (`x[i] = 0`)
|
||||
exists(AssignExpr ae |
|
||||
e1 = ae.getRValue() and
|
||||
@@ -162,11 +159,7 @@ module Cached {
|
||||
Stages::DataFlowStage::forceCachingInSameStage() and
|
||||
any(LocalTaintExprStepConfiguration x).hasNodePath(nodeFrom, nodeTo)
|
||||
or
|
||||
nodeTo = nodeFrom.(TaintedParameterNode).getUnderlyingNode()
|
||||
or
|
||||
nodeFrom = nodeTo.(TaintedReturnNode).getUnderlyingNode()
|
||||
or
|
||||
flowOutOfDelegateLibraryCall(nodeFrom, nodeTo, false)
|
||||
nodeFrom = nodeTo.(YieldReturnNode).getPreUpdateNode()
|
||||
or
|
||||
localTaintStepCil(nodeFrom, nodeTo)
|
||||
or
|
||||
@@ -180,7 +173,13 @@ module Cached {
|
||||
access.(PropertyRead).getQualifier() = nodeFrom.asExpr()
|
||||
)
|
||||
or
|
||||
flowThroughLibraryCallableOutRef(_, nodeFrom, nodeTo, false)
|
||||
exists(LibraryCodeNode n | not n.preservesValue() |
|
||||
n = nodeTo and
|
||||
nodeFrom = n.getPredecessor(AccessPath::empty())
|
||||
or
|
||||
n = nodeFrom and
|
||||
nodeTo = n.getSuccessor(AccessPath::empty())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -566,10 +566,10 @@ class IndexerAccess extends AssignableMemberAccess, ElementAccess, IndexerAccess
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class IndexerRead extends IndexerAccess, AssignableRead {
|
||||
override IndexerRead getANextRead() { result = AssignableRead.super.getANextRead() }
|
||||
class IndexerRead extends IndexerAccess, ElementRead {
|
||||
override IndexerRead getANextRead() { result = ElementRead.super.getANextRead() }
|
||||
|
||||
override IndexerRead getAReachableRead() { result = AssignableRead.super.getAReachableRead() }
|
||||
override IndexerRead getAReachableRead() { result = ElementRead.super.getAReachableRead() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -586,7 +586,7 @@ class IndexerRead extends IndexerAccess, AssignableRead {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class IndexerWrite extends IndexerAccess, AssignableWrite { }
|
||||
class IndexerWrite extends IndexerAccess, ElementWrite { }
|
||||
|
||||
/**
|
||||
* An access to a virtual indexer - an indexer that is virtual or defined in
|
||||
@@ -818,7 +818,7 @@ class ArrayAccess extends ElementAccess, @array_access_expr {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ArrayRead extends ArrayAccess, AssignableRead { }
|
||||
class ArrayRead extends ArrayAccess, ElementRead { }
|
||||
|
||||
/**
|
||||
* An access to an array that updates the underlying value, for example
|
||||
@@ -830,7 +830,7 @@ class ArrayRead extends ArrayAccess, AssignableRead { }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ArrayWrite extends ArrayAccess, AssignableWrite { }
|
||||
class ArrayWrite extends ArrayAccess, ElementWrite { }
|
||||
|
||||
/**
|
||||
* An access to a namespace, for example `System` in `nameof(System)`.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import semmle.code.csharp.dataflow.LibraryTypeDataFlow
|
||||
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
|
||||
|
||||
/** Definitions relating to the `Json.NET` package. */
|
||||
module JsonNET {
|
||||
|
||||
@@ -13,7 +13,7 @@ abstract class UnboundGeneric extends Generic {
|
||||
/** Gets the `i`th type parameter, if any. */
|
||||
abstract TypeParameter getTypeParameter(int i);
|
||||
|
||||
/** Gets a type parameter, if any. */
|
||||
/** Gets a type parameter. */
|
||||
TypeParameter getATypeParameter() { result = getTypeParameter(_) }
|
||||
|
||||
/**
|
||||
@@ -42,10 +42,13 @@ abstract class ConstructedGeneric extends Generic {
|
||||
/** Gets the `i`th type argument, if any. */
|
||||
abstract Type getTypeArgument(int i);
|
||||
|
||||
/** Gets a type argument, if any. */
|
||||
/** Gets a type argument. */
|
||||
Type getATypeArgument() { result = getTypeArgument(_) }
|
||||
|
||||
/** Gets the unbound generic declaration from which this declaration was constructed. */
|
||||
/**
|
||||
* Gets the unbound generic declaration from which this declaration was
|
||||
* constructed.
|
||||
*/
|
||||
UnboundGeneric getUnboundGeneric() { none() }
|
||||
|
||||
/** Gets the total number of type arguments. */
|
||||
|
||||
@@ -497,10 +497,6 @@ expr_flowstate(unique int id: @expr ref, int state: int ref);
|
||||
|
||||
@generic = @type | @method | @local_function;
|
||||
|
||||
is_generic(unique int id: @generic ref);
|
||||
|
||||
is_constructed(unique int id: @generic ref);
|
||||
|
||||
type_parameters(
|
||||
unique int id: @type_parameter ref,
|
||||
int index: int ref,
|
||||
|
||||
@@ -15479,28 +15479,6 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>is_generic</name>
|
||||
<cardinality>77320</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>77320</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>is_constructed</name>
|
||||
<cardinality>358124</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id</k>
|
||||
<v>358124</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies/>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>type_parameters</name>
|
||||
<cardinality>84292</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -7,18 +7,15 @@
|
||||
| CSharp7.cs:17:9:17:11 | this | CSharp7.cs:17:18:17:22 | this access |
|
||||
| CSharp7.cs:21:9:21:11 | this | CSharp7.cs:21:16:21:20 | this access |
|
||||
| CSharp7.cs:22:9:22:11 | this | CSharp7.cs:22:16:22:20 | this access |
|
||||
| CSharp7.cs:22:9:22:11 | value | CSharp7.cs:22:9:22:11 | value |
|
||||
| CSharp7.cs:22:9:22:11 | value | CSharp7.cs:22:24:22:28 | access to parameter value |
|
||||
| CSharp7.cs:25:5:25:27 | this | CSharp7.cs:16:9:16:13 | this access |
|
||||
| CSharp7.cs:26:6:26:28 | this | CSharp7.cs:26:35:26:39 | this access |
|
||||
| CSharp7.cs:31:19:31:19 | i | CSharp7.cs:31:19:31:19 | i |
|
||||
| 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: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:41:9:41:21 | SSA def(x) |
|
||||
| CSharp7.cs:44:19:44:19 | x | CSharp7.cs:44:19:44:19 | 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:46:9:46:13 | SSA def(y) |
|
||||
| CSharp7.cs:49:10:49:10 | this | CSharp7.cs:51:9:51:24 | this access |
|
||||
@@ -65,7 +62,6 @@
|
||||
| CSharp7.cs:78:31:78:31 | access to local variable a | CSharp7.cs:78:27:78:32 | (..., ...) |
|
||||
| CSharp7.cs:79:23:79:24 | "" | CSharp7.cs:79:22:79:28 | (..., ...) |
|
||||
| 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:82:21:82:21 | x |
|
||||
| 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:20:84:20 | access to parameter x | CSharp7.cs:84:16:84:24 | (..., ...) |
|
||||
@@ -116,19 +112,15 @@
|
||||
| CSharp7.cs:119:19:119:20 | access to local variable m2 | CSharp7.cs:119:19:119:26 | access to field Item1 |
|
||||
| CSharp7.cs:123:28:123:36 | "DefUse3" | CSharp7.cs:123:22:123:36 | ... = ... |
|
||||
| CSharp7.cs:129:9:129:12 | this | CSharp7.cs:135:24:135:25 | this access |
|
||||
| CSharp7.cs:131:20:131:20 | x | CSharp7.cs:131:20:131:20 | x |
|
||||
| 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:36:131:36 | 1 | CSharp7.cs:131:32:131:36 | ... + ... |
|
||||
| CSharp7.cs:133:22:133:22 | t | CSharp7.cs:133:22:133:22 | t |
|
||||
| CSharp7.cs:133:22:133:22 | t | CSharp7.cs:133:39:133:39 | access to parameter t |
|
||||
| CSharp7.cs:135:24:135:25 | this access | CSharp7.cs:155:16:155:17 | this access |
|
||||
| CSharp7.cs:139:29:139:29 | x | CSharp7.cs:139:29:139:29 | x |
|
||||
| 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:38:139:38 | 1 | CSharp7.cs:139:34:139:38 | ... + ... |
|
||||
| CSharp7.cs:141:9:141:51 | this | CSharp7.cs:141:38:141:39 | this access |
|
||||
| CSharp7.cs:141:20:141:20 | x | CSharp7.cs:141:20:141:20 | x |
|
||||
| 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 |
|
||||
@@ -137,17 +129,13 @@
|
||||
| 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:9:143:31 | this | CSharp7.cs:143:26:143:27 | this access |
|
||||
| CSharp7.cs:143:20:143:20 | x | CSharp7.cs:143:20:143:20 | x |
|
||||
| CSharp7.cs:143:20:143:20 | x | CSharp7.cs:143:29:143:29 | access to parameter x |
|
||||
| CSharp7.cs:145:9:149:9 | this | CSharp7.cs:148:20:148:21 | this access |
|
||||
| CSharp7.cs:147:13:147:35 | this | CSharp7.cs:147:30:147:31 | this access |
|
||||
| CSharp7.cs:147:24:147:24 | x | CSharp7.cs:147:24:147:24 | x |
|
||||
| CSharp7.cs:147:24:147:24 | x | CSharp7.cs:147:33:147:33 | access to parameter x |
|
||||
| CSharp7.cs:158:10:158:17 | this | CSharp7.cs:170:9:170:9 | this access |
|
||||
| CSharp7.cs:161:18:161:18 | t | CSharp7.cs:161:18:161:18 | t |
|
||||
| CSharp7.cs:161:18:161:18 | t | CSharp7.cs:161:24:161:24 | access to parameter t |
|
||||
| CSharp7.cs:163:9:168:9 | this | CSharp7.cs:166:13:166:16 | this access |
|
||||
| CSharp7.cs:163:26:163:26 | u | CSharp7.cs:163:26:163:26 | u |
|
||||
| CSharp7.cs:163:26:163:26 | u | CSharp7.cs:167:22:167:22 | access to parameter u |
|
||||
| CSharp7.cs:165:13:165:43 | this | CSharp7.cs:165:37:165:40 | this access |
|
||||
| CSharp7.cs:166:13:166:16 | this access | CSharp7.cs:167:20:167:20 | this access |
|
||||
@@ -156,13 +144,10 @@
|
||||
| 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:9:177:40 | this | CSharp7.cs:177:31:177:31 | this access |
|
||||
| CSharp7.cs:177:25:177:25 | s | CSharp7.cs:177:25:177:25 | s |
|
||||
| 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:38:177:39 | "" | CSharp7.cs:177:31:177:39 | ... + ... |
|
||||
| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:25:178:25 | s |
|
||||
| CSharp7.cs:178:25:178:25 | s | CSharp7.cs:178:31:178:31 | access to parameter s |
|
||||
| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:25:179:25 | s |
|
||||
| CSharp7.cs:179:25:179:25 | s | CSharp7.cs:179:37:179:37 | access to parameter s |
|
||||
| CSharp7.cs:181:21:181:21 | this access | CSharp7.cs:182:21:182:21 | this access |
|
||||
| CSharp7.cs:181:23:181:25 | [post] access to local variable src | CSharp7.cs:182:23:182:25 | access to local variable src |
|
||||
@@ -189,9 +174,7 @@
|
||||
| CSharp7.cs:199:26:199:35 | [post] this access | CSharp7.cs:200:9:200:18 | this access |
|
||||
| CSharp7.cs:199:26:199:35 | this access | CSharp7.cs:200:9:200:18 | this access |
|
||||
| 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:203:24:203:24 | p |
|
||||
| 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:28:205:28 | q |
|
||||
| CSharp7.cs:205:28:205:28 | q | CSharp7.cs:205:44:205:44 | access to parameter q |
|
||||
| CSharp7.cs:216:13:216:17 | false | CSharp7.cs:216:9:216:17 | SSA def(x) |
|
||||
| CSharp7.cs:217:17:217:17 | 0 | CSharp7.cs:217:16:217:23 | (..., ...) |
|
||||
@@ -248,13 +231,16 @@
|
||||
| CSharp7.cs:283:13:283:48 | SSA def(dict) | CSharp7.cs:284:20:284:23 | access to local variable dict |
|
||||
| CSharp7.cs:283:20:283:48 | object creation of type Dictionary<Int32,String> | CSharp7.cs:283:13:283:48 | SSA def(dict) |
|
||||
| CSharp7.cs:284:13:284:62 | SSA def(list) | CSharp7.cs:286:39:286:42 | access to local variable list |
|
||||
| CSharp7.cs:284:20:284:23 | access to local variable dict | CSharp7.cs:284:20:284:62 | [library code] call to method Select |
|
||||
| CSharp7.cs:284:20:284:62 | [library code] call to method Select | CSharp7.cs:284:20:284:62 | call to method Select |
|
||||
| CSharp7.cs:284:20:284:62 | [library code] call to method Select | CSharp7.cs:284:32:284:61 | [implicit argument 0] (...) => ... |
|
||||
| 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:32:284:35 | item |
|
||||
| CSharp7.cs:284:32:284:35 | item | CSharp7.cs:284:41:284:44 | access to parameter item |
|
||||
| CSharp7.cs:284:32:284:61 | [output] (...) => ... | CSharp7.cs:284:20:284:62 | call to method Select |
|
||||
| CSharp7.cs:284:32:284:61 | [output] (...) => ... | CSharp7.cs:284:20:284:62 | [library code] call to method Select |
|
||||
| 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 |
|
||||
| CSharp7.cs:284:51:284:54 | access to parameter item | CSharp7.cs:284:51:284:60 | [library code] access to property Value |
|
||||
| CSharp7.cs:284:51:284:60 | [library code] access to property Value | CSharp7.cs:284:51:284:60 | access to property Value |
|
||||
| CSharp7.cs:284:51:284:60 | access to property Value | CSharp7.cs:284:40:284:61 | (..., ...) |
|
||||
| CSharp7.cs:286:39:286:42 | access to local variable list | CSharp7.cs:288:36:288:39 | access to local variable list |
|
||||
| CSharp7.cs:288:36:288:39 | access to local variable list | CSharp7.cs:290:32:290:35 | access to local variable list |
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
import csharp
|
||||
private import semmle.code.csharp.controlflow.Guards
|
||||
|
||||
private predicate outRefDef(DataFlow::ExprNode ne, int outRef) {
|
||||
exists(Ssa::ExplicitDefinition def, Parameter outRefParameter |
|
||||
outRefParameter.isOutOrRef() and
|
||||
ne.getExpr() = def.getADefinition().getSource() and
|
||||
def.isLiveOutRefParameterDefinition(outRefParameter) and
|
||||
outRef = outRefParameter.getPosition()
|
||||
)
|
||||
}
|
||||
|
||||
class Configuration extends DataFlow::Configuration {
|
||||
Configuration() { this = "Configuration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { any() }
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof DataFlow::ParameterNode }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { any() }
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
any(Callable c).canReturn(sink.asExpr()) or outRefDef(sink, _)
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node) {
|
||||
exists(AbstractValues::NullValue nv | node.(GuardedDataFlowNode).mustHaveValue(nv) |
|
||||
@@ -24,15 +35,9 @@ predicate flowOutFromParameter(DataFlow::Configuration c, Parameter p) {
|
||||
}
|
||||
|
||||
predicate flowOutFromParameterOutOrRef(DataFlow::Configuration c, Parameter p, int outRef) {
|
||||
exists(
|
||||
DataFlow::ExprNode ne, Ssa::ExplicitDefinition def, DataFlow::ParameterNode np,
|
||||
Parameter outRefParameter
|
||||
|
|
||||
outRefParameter.isOutOrRef() and
|
||||
exists(DataFlow::ExprNode ne, DataFlow::ParameterNode np |
|
||||
outRefDef(ne, outRef) and
|
||||
np.getParameter() = p and
|
||||
ne.getExpr() = def.getADefinition().getSource() and
|
||||
def.isLiveOutRefParameterDefinition(outRefParameter) and
|
||||
c.hasFlow(np, ne) and
|
||||
outRef = outRefParameter.getPosition()
|
||||
c.hasFlow(np, ne)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -201,6 +201,20 @@ edges
|
||||
| H.cs:131:18:131:18 | access to local variable a [FieldA] : Object | H.cs:131:14:131:19 | call to method Get |
|
||||
| H.cs:147:17:147:32 | call to method Through : A | H.cs:148:14:148:14 | access to local variable a |
|
||||
| H.cs:147:25:147:31 | object creation of type A : A | H.cs:147:17:147:32 | call to method Through : A |
|
||||
| H.cs:155:17:155:23 | object creation of type B : B | H.cs:157:20:157:20 | access to local variable b : B |
|
||||
| H.cs:157:9:157:9 | [post] access to parameter a [FieldA] : B | H.cs:164:19:164:19 | [post] access to local variable a [FieldA] : B |
|
||||
| H.cs:157:20:157:20 | access to local variable b : B | H.cs:157:9:157:9 | [post] access to parameter a [FieldA] : B |
|
||||
| H.cs:163:17:163:28 | object creation of type Object : Object | H.cs:164:22:164:22 | access to local variable o : Object |
|
||||
| H.cs:164:19:164:19 | [post] access to local variable a [FieldA, FieldB] | H.cs:165:21:165:21 | access to local variable a [FieldA, FieldB] |
|
||||
| H.cs:164:19:164:19 | [post] access to local variable a [FieldA] : B | H.cs:165:21:165:21 | access to local variable a [FieldA] : B |
|
||||
| H.cs:164:22:164:22 | access to local variable o : Object | H.cs:164:19:164:19 | [post] access to local variable a [FieldA, FieldB] |
|
||||
| H.cs:165:17:165:28 | (...) ... : B | H.cs:166:14:166:14 | access to local variable b |
|
||||
| H.cs:165:17:165:28 | (...) ... [FieldB] : Object | H.cs:167:14:167:14 | access to local variable b [FieldB] : Object |
|
||||
| H.cs:165:21:165:21 | access to local variable a [FieldA, FieldB] | H.cs:165:21:165:28 | access to field FieldA [FieldB] : Object |
|
||||
| H.cs:165:21:165:21 | access to local variable a [FieldA] : B | H.cs:165:21:165:28 | access to field FieldA : B |
|
||||
| H.cs:165:21:165:28 | access to field FieldA : B | H.cs:165:17:165:28 | (...) ... : B |
|
||||
| H.cs:165:21:165:28 | access to field FieldA [FieldB] : Object | H.cs:165:17:165:28 | (...) ... [FieldB] : Object |
|
||||
| H.cs:167:14:167:14 | access to local variable b [FieldB] : Object | H.cs:167:14:167:21 | access to field FieldB |
|
||||
nodes
|
||||
| A.cs:5:17:5:23 | object creation of type C : C | semmle.label | object creation of type C : C |
|
||||
| A.cs:6:17:6:25 | call to method Make [c] : C | semmle.label | call to method Make [c] : C |
|
||||
@@ -434,6 +448,22 @@ nodes
|
||||
| H.cs:147:17:147:32 | call to method Through : A | semmle.label | call to method Through : A |
|
||||
| H.cs:147:25:147:31 | object creation of type A : A | semmle.label | object creation of type A : A |
|
||||
| H.cs:148:14:148:14 | access to local variable a | semmle.label | access to local variable a |
|
||||
| H.cs:155:17:155:23 | object creation of type B : B | semmle.label | object creation of type B : B |
|
||||
| H.cs:157:9:157:9 | [post] access to parameter a [FieldA] : B | semmle.label | [post] access to parameter a [FieldA] : B |
|
||||
| H.cs:157:20:157:20 | access to local variable b : B | semmle.label | access to local variable b : B |
|
||||
| H.cs:163:17:163:28 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
|
||||
| H.cs:164:19:164:19 | [post] access to local variable a [FieldA, FieldB] | semmle.label | [post] access to local variable a [FieldA, FieldB] |
|
||||
| H.cs:164:19:164:19 | [post] access to local variable a [FieldA] : B | semmle.label | [post] access to local variable a [FieldA] : B |
|
||||
| H.cs:164:22:164:22 | access to local variable o : Object | semmle.label | access to local variable o : Object |
|
||||
| H.cs:165:17:165:28 | (...) ... : B | semmle.label | (...) ... : B |
|
||||
| H.cs:165:17:165:28 | (...) ... [FieldB] : Object | semmle.label | (...) ... [FieldB] : Object |
|
||||
| H.cs:165:21:165:21 | access to local variable a [FieldA, FieldB] | semmle.label | access to local variable a [FieldA, FieldB] |
|
||||
| H.cs:165:21:165:21 | access to local variable a [FieldA] : B | semmle.label | access to local variable a [FieldA] : B |
|
||||
| H.cs:165:21:165:28 | access to field FieldA : B | semmle.label | access to field FieldA : B |
|
||||
| H.cs:165:21:165:28 | access to field FieldA [FieldB] : Object | semmle.label | access to field FieldA [FieldB] : Object |
|
||||
| H.cs:166:14:166:14 | access to local variable b | semmle.label | access to local variable b |
|
||||
| H.cs:167:14:167:14 | access to local variable b [FieldB] : Object | semmle.label | access to local variable b [FieldB] : Object |
|
||||
| H.cs:167:14:167:21 | access to field FieldB | semmle.label | access to field FieldB |
|
||||
#select
|
||||
| A.cs:7:14:7:16 | access to field c | A.cs:5:17:5:23 | object creation of type C : C | A.cs:7:14:7:16 | access to field c | $@ | A.cs:5:17:5:23 | object creation of type C : C | object creation of type C : C |
|
||||
| A.cs:14:14:14:20 | call to method Get | A.cs:13:15:13:22 | object creation of type C1 : C1 | A.cs:14:14:14:20 | call to method Get | $@ | A.cs:13:15:13:22 | object creation of type C1 : C1 | object creation of type C1 : C1 |
|
||||
@@ -481,3 +511,5 @@ nodes
|
||||
| H.cs:114:14:114:21 | access to field FieldB | H.cs:112:20:112:31 | object creation of type Object : Object | H.cs:114:14:114:21 | access to field FieldB | $@ | H.cs:112:20:112:31 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| H.cs:131:14:131:19 | call to method Get | H.cs:130:20:130:31 | object creation of type Object : Object | H.cs:131:14:131:19 | call to method Get | $@ | H.cs:130:20:130:31 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
| H.cs:148:14:148:14 | access to local variable a | H.cs:147:25:147:31 | object creation of type A : A | H.cs:148:14:148:14 | access to local variable a | $@ | H.cs:147:25:147:31 | object creation of type A : A | object creation of type A : A |
|
||||
| H.cs:166:14:166:14 | access to local variable b | H.cs:155:17:155:23 | object creation of type B : B | H.cs:166:14:166:14 | access to local variable b | $@ | H.cs:155:17:155:23 | object creation of type B : B | object creation of type B : B |
|
||||
| H.cs:167:14:167:21 | access to field FieldB | H.cs:163:17:163:28 | object creation of type Object : Object | H.cs:167:14:167:21 | access to field FieldB | $@ | H.cs:163:17:163:28 | object creation of type Object : Object | object creation of type Object : Object |
|
||||
|
||||
@@ -150,5 +150,22 @@ public class H
|
||||
Sink(b); // no flow
|
||||
}
|
||||
|
||||
void SetNested(A a, object o)
|
||||
{
|
||||
var b = new B();
|
||||
b.FieldB = o;
|
||||
a.FieldA = b;
|
||||
}
|
||||
|
||||
void M8()
|
||||
{
|
||||
var a = new A();
|
||||
var o = new object();
|
||||
SetNested(a, o);
|
||||
var b = (B) a.FieldA;
|
||||
Sink(b); // flow (from `new B()` inside `SetNested`)
|
||||
Sink(b.FieldB); // flow
|
||||
}
|
||||
|
||||
public static void Sink(object o) { }
|
||||
}
|
||||
@@ -149,7 +149,10 @@ edges
|
||||
| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 |
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String | GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String |
|
||||
| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 |
|
||||
| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String |
|
||||
| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 |
|
||||
@@ -300,6 +303,9 @@ nodes
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | semmle.label | delegate call : String |
|
||||
| GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | semmle.label | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String | semmle.label | [library code] object creation of type Lazy<String> : String |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String | semmle.label | object creation of type Lazy<String> [Value] : String |
|
||||
| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | semmle.label | access to property Value : String |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | semmle.label | [output] delegate creation of type Func<String> : String |
|
||||
| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String |
|
||||
|
||||
@@ -142,22 +142,28 @@ edges
|
||||
| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable<T> | GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 |
|
||||
| GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable<T> | GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | GlobalDataFlow.cs:80:22:80:85 | call to method SelectEven : IEnumerable<T> |
|
||||
| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T |
|
||||
| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T | GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T | GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T | GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String |
|
||||
| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | GlobalDataFlow.cs:82:76:82:86 | [implicit argument 0] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [implicit argument 0] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [implicit argument 0] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:90:83:90:101 | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | GlobalDataFlow.cs:84:117:84:127 | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:84:117:84:127 | [implicit argument 0] (...) => ... : String | GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 |
|
||||
| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | GlobalDataFlow.cs:86:117:86:127 | [implicit argument 1] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:86:117:86:127 | [implicit argument 1] (...) => ... : String | GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 |
|
||||
| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | GlobalDataFlow.cs:88:83:88:101 | [implicit argument 1] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:83:88:101 | [implicit argument 1] (...) => ... : String | GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | GlobalDataFlow.cs:88:104:88:109 | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:104:88:109 | [implicit argument 0] (...) => ... : String | GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 |
|
||||
| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:83:90:101 | [implicit argument 0] (...) => ... : String | GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | GlobalDataFlow.cs:90:104:90:109 | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [implicit argument 0] (...) => ... : String | GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | GlobalDataFlow.cs:97:15:97:20 | access to local variable sink22 |
|
||||
@@ -173,23 +179,26 @@ edges
|
||||
| GlobalDataFlow.cs:163:22:163:43 | call to method TaintedParam : String | GlobalDataFlow.cs:164:15:164:20 | access to local variable sink23 |
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | GlobalDataFlow.cs:180:21:180:26 | delegate call : String |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String | GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String | GlobalDataFlow.cs:189:22:189:48 | access to property Value : String |
|
||||
| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable<String> | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 |
|
||||
| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable<String> | GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:212:37:212:38 | [implicit argument 0] access to local variable f1 : String |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:214:37:214:38 | [implicit argument 0] access to local variable f2 : String |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | GlobalDataFlow.cs:216:37:216:48 | [implicit argument 0] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : String | GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 |
|
||||
| GlobalDataFlow.cs:211:71:211:71 | x : String | GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String |
|
||||
| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [implicit argument 0] access to local variable f1 : String | GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : String |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [implicit argument 0] access to local variable f1 : String | GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 |
|
||||
| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:211:71:211:71 | x : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String |
|
||||
| GlobalDataFlow.cs:214:37:214:38 | [implicit argument 0] access to local variable f2 : String | GlobalDataFlow.cs:211:71:211:71 | x : String |
|
||||
| GlobalDataFlow.cs:214:37:214:38 | [implicit argument 0] access to local variable f2 : String | GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String |
|
||||
| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 |
|
||||
| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : T |
|
||||
| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable<String> | GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : T | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [implicit argument 0] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [implicit argument 0] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : String |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : String | GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 |
|
||||
| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String |
|
||||
| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | GlobalDataFlow.cs:239:15:239:24 | access to parameter sinkParam0 |
|
||||
| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String |
|
||||
@@ -199,17 +208,17 @@ edges
|
||||
| GlobalDataFlow.cs:257:26:257:35 | sinkParam5 : String | GlobalDataFlow.cs:259:15:259:24 | access to parameter sinkParam5 |
|
||||
| GlobalDataFlow.cs:262:26:262:35 | sinkParam6 : String | GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 |
|
||||
| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 |
|
||||
| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 |
|
||||
| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String | GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 |
|
||||
| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 |
|
||||
| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable<String> | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 |
|
||||
| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : String | GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 |
|
||||
| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:153:21:153:25 | call to method Out : String |
|
||||
| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String |
|
||||
| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | GlobalDataFlow.cs:156:20:156:24 | SSA def(sink7) : String |
|
||||
| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String |
|
||||
| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | GlobalDataFlow.cs:159:20:159:24 | SSA def(sink8) : String |
|
||||
| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String |
|
||||
| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable<String> | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:336:9:336:36 | yield return ...; : IEnumerable<String> | GlobalDataFlow.cs:161:22:161:31 | call to method OutYield : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | GlobalDataFlow.cs:336:9:336:36 | yield return ...; : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:361:41:361:41 | x : String | GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:363:11:363:11 | access to parameter x : String | GlobalDataFlow.cs:53:15:53:15 | x : String |
|
||||
@@ -334,20 +343,26 @@ nodes
|
||||
| GlobalDataFlow.cs:80:23:80:65 | (...) ... : String[] | semmle.label | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:81:15:81:20 | access to local variable sink13 | semmle.label | access to local variable sink13 |
|
||||
| GlobalDataFlow.cs:82:23:82:66 | (...) ... : String[] | semmle.label | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : T | semmle.label | [output] delegate creation of type Func<String,String> : T |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [implicit argument 0] delegate creation of type Func<String,String> : String | semmle.label | [implicit argument 0] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:82:76:82:86 | [output] delegate creation of type Func<String,String> : String | semmle.label | [output] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:83:15:83:20 | access to local variable sink14 | semmle.label | access to local variable sink14 |
|
||||
| GlobalDataFlow.cs:84:23:84:66 | (...) ... : String[] | semmle.label | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:84:117:84:127 | [implicit argument 0] (...) => ... : String | semmle.label | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:84:117:84:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:85:15:85:20 | access to local variable sink15 | semmle.label | access to local variable sink15 |
|
||||
| GlobalDataFlow.cs:86:70:86:113 | (...) ... : String[] | semmle.label | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:86:117:86:127 | [implicit argument 1] (...) => ... : String | semmle.label | [implicit argument 1] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:86:117:86:127 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:87:15:87:20 | access to local variable sink16 | semmle.label | access to local variable sink16 |
|
||||
| GlobalDataFlow.cs:88:23:88:66 | (...) ... : String[] | semmle.label | (...) ... : String[] |
|
||||
| GlobalDataFlow.cs:88:83:88:101 | [implicit argument 1] (...) => ... : String | semmle.label | [implicit argument 1] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:83:88:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:104:88:109 | [implicit argument 0] (...) => ... : String | semmle.label | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:88:104:88:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:89:15:89:20 | access to local variable sink17 | semmle.label | access to local variable sink17 |
|
||||
| GlobalDataFlow.cs:90:75:90:80 | access to local variable sink14 : String | semmle.label | access to local variable sink14 : String |
|
||||
| GlobalDataFlow.cs:90:83:90:101 | [implicit argument 0] (...) => ... : String | semmle.label | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:83:90:101 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [implicit argument 0] (...) => ... : String | semmle.label | [implicit argument 0] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:90:104:90:109 | [output] (...) => ... : String | semmle.label | [output] (...) => ... : String |
|
||||
| GlobalDataFlow.cs:91:15:91:20 | access to local variable sink18 | semmle.label | access to local variable sink18 |
|
||||
| GlobalDataFlow.cs:94:15:94:20 | access to local variable sink21 | semmle.label | access to local variable sink21 |
|
||||
@@ -371,23 +386,26 @@ nodes
|
||||
| GlobalDataFlow.cs:179:35:179:48 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:180:21:180:26 | delegate call : String | semmle.label | delegate call : String |
|
||||
| GlobalDataFlow.cs:181:15:181:19 | access to local variable sink9 | semmle.label | access to local variable sink9 |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | [library code] object creation of type Lazy<String> : String | semmle.label | [library code] object creation of type Lazy<String> : String |
|
||||
| GlobalDataFlow.cs:189:22:189:42 | object creation of type Lazy<String> [Value] : String | semmle.label | object creation of type Lazy<String> [Value] : String |
|
||||
| GlobalDataFlow.cs:189:22:189:48 | access to property Value : String | semmle.label | access to property Value : String |
|
||||
| GlobalDataFlow.cs:189:39:189:41 | [output] delegate creation of type Func<String> : String | semmle.label | [output] delegate creation of type Func<String> : String |
|
||||
| GlobalDataFlow.cs:190:15:190:20 | access to local variable sink10 | semmle.label | access to local variable sink10 |
|
||||
| GlobalDataFlow.cs:197:22:197:32 | access to property OutProperty : String | semmle.label | access to property OutProperty : String |
|
||||
| GlobalDataFlow.cs:198:15:198:20 | access to local variable sink19 | semmle.label | access to local variable sink19 |
|
||||
| GlobalDataFlow.cs:207:46:207:59 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : IQueryable<String> | semmle.label | sinkParam10 : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:210:35:210:45 | sinkParam10 : String | semmle.label | sinkParam10 : String |
|
||||
| GlobalDataFlow.cs:210:58:210:68 | access to parameter sinkParam10 | semmle.label | access to parameter sinkParam10 |
|
||||
| GlobalDataFlow.cs:211:71:211:71 | x : IQueryable<String> | semmle.label | x : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:211:71:211:71 | x : String | semmle.label | x : String |
|
||||
| GlobalDataFlow.cs:211:89:211:89 | access to parameter x : String | semmle.label | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:212:22:212:28 | access to local variable tainted : IQueryable<String> | semmle.label | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [implicit argument 0] access to local variable f1 : String | semmle.label | [implicit argument 0] access to local variable f1 : String |
|
||||
| GlobalDataFlow.cs:212:37:212:38 | [output] access to local variable f1 : String | semmle.label | [output] access to local variable f1 : String |
|
||||
| GlobalDataFlow.cs:213:15:213:20 | access to local variable sink24 | semmle.label | access to local variable sink24 |
|
||||
| GlobalDataFlow.cs:214:22:214:28 | access to local variable tainted : IQueryable<String> | semmle.label | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:214:37:214:38 | [implicit argument 0] access to local variable f2 : String | semmle.label | [implicit argument 0] access to local variable f2 : String |
|
||||
| GlobalDataFlow.cs:214:37:214:38 | [output] access to local variable f2 : String | semmle.label | [output] access to local variable f2 : String |
|
||||
| GlobalDataFlow.cs:215:15:215:20 | access to local variable sink25 | semmle.label | access to local variable sink25 |
|
||||
| GlobalDataFlow.cs:216:22:216:28 | access to local variable tainted : IQueryable<String> | semmle.label | access to local variable tainted : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : T | semmle.label | [output] delegate creation of type Func<String,String> : T |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [implicit argument 0] delegate creation of type Func<String,String> : String | semmle.label | [implicit argument 0] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:216:37:216:48 | [output] delegate creation of type Func<String,String> : String | semmle.label | [output] delegate creation of type Func<String,String> : String |
|
||||
| GlobalDataFlow.cs:217:15:217:20 | access to local variable sink26 | semmle.label | access to local variable sink26 |
|
||||
| GlobalDataFlow.cs:236:26:236:35 | sinkParam0 : String | semmle.label | sinkParam0 : String |
|
||||
| GlobalDataFlow.cs:238:16:238:25 | access to parameter sinkParam0 : String | semmle.label | access to parameter sinkParam0 : String |
|
||||
@@ -404,18 +422,18 @@ nodes
|
||||
| GlobalDataFlow.cs:264:15:264:24 | access to parameter sinkParam6 | semmle.label | access to parameter sinkParam6 |
|
||||
| GlobalDataFlow.cs:267:26:267:35 | sinkParam7 : String | semmle.label | sinkParam7 : String |
|
||||
| GlobalDataFlow.cs:269:15:269:24 | access to parameter sinkParam7 | semmle.label | access to parameter sinkParam7 |
|
||||
| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String[] | semmle.label | sinkParam8 : String[] |
|
||||
| GlobalDataFlow.cs:294:31:294:40 | sinkParam8 : String | semmle.label | sinkParam8 : String |
|
||||
| GlobalDataFlow.cs:296:15:296:24 | access to parameter sinkParam8 | semmle.label | access to parameter sinkParam8 |
|
||||
| GlobalDataFlow.cs:300:32:300:41 | sinkParam9 : String | semmle.label | sinkParam9 : String |
|
||||
| GlobalDataFlow.cs:302:15:302:24 | access to parameter sinkParam9 | semmle.label | access to parameter sinkParam9 |
|
||||
| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : IQueryable<String> | semmle.label | sinkParam11 : IQueryable<String> |
|
||||
| GlobalDataFlow.cs:306:32:306:42 | sinkParam11 : String | semmle.label | sinkParam11 : String |
|
||||
| GlobalDataFlow.cs:308:15:308:25 | access to parameter sinkParam11 | semmle.label | access to parameter sinkParam11 |
|
||||
| GlobalDataFlow.cs:320:16:320:29 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:325:9:325:26 | SSA def(x) : String | semmle.label | SSA def(x) : String |
|
||||
| GlobalDataFlow.cs:325:13:325:26 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:330:9:330:26 | SSA def(x) : String | semmle.label | SSA def(x) : String |
|
||||
| GlobalDataFlow.cs:330:13:330:26 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:336:22:336:35 | "taint source" : IEnumerable<String> | semmle.label | "taint source" : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:336:9:336:36 | yield return ...; : IEnumerable<String> | semmle.label | yield return ...; : IEnumerable<String> |
|
||||
| GlobalDataFlow.cs:336:22:336:35 | "taint source" : String | semmle.label | "taint source" : String |
|
||||
| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String |
|
||||
| GlobalDataFlow.cs:361:41:361:41 | x : String | semmle.label | x : String |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
callableFlow
|
||||
| LibraryTypeDataFlow.DataContract.get_AString() | qualifier -> return | false |
|
||||
| System.Array.Add(object) | argument 0 -> qualifier | false |
|
||||
| System.Array.AsReadOnly<T>(T[]) | qualifier -> return | false |
|
||||
@@ -661,10 +662,6 @@
|
||||
| System.Int32.TryParse(string, NumberStyles, IFormatProvider, out int) | argument 0 -> return | false |
|
||||
| System.Int32.TryParse(string, out int) | argument 0 -> argument 1 | false |
|
||||
| System.Int32.TryParse(string, out int) | argument 0 -> return | false |
|
||||
| System.Lazy<>.Lazy(Func<T>) | output from argument 0 -> return | true |
|
||||
| System.Lazy<>.Lazy(Func<T>, LazyThreadSafetyMode) | output from argument 0 -> return | true |
|
||||
| System.Lazy<>.Lazy(Func<T>, bool) | output from argument 0 -> return | true |
|
||||
| System.Lazy<>.get_Value() | qualifier -> return | true |
|
||||
| System.Linq.Enumerable.Aggregate<TSource, TAccumulate, TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate, TSource, TAccumulate>, Func<TAccumulate, TResult>) | argument 0 -> parameter 1 of argument 2 | false |
|
||||
| System.Linq.Enumerable.Aggregate<TSource, TAccumulate, TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate, TSource, TAccumulate>, Func<TAccumulate, TResult>) | argument 1 -> parameter 0 of argument 2 | false |
|
||||
| System.Linq.Enumerable.Aggregate<TSource, TAccumulate, TResult>(IEnumerable<TSource>, TAccumulate, Func<TAccumulate, TSource, TAccumulate>, Func<TAccumulate, TResult>) | output from argument 2 -> parameter 0 of argument 3 | false |
|
||||
@@ -1686,3 +1683,7 @@
|
||||
| System.Web.HttpUtility.HtmlEncode(string) | argument 0 -> return | false |
|
||||
| System.Web.HttpUtility.UrlEncode(string) | argument 0 -> return | false |
|
||||
| System.Web.UI.WebControls.TextBox.get_Text() | qualifier -> return | false |
|
||||
callableFlowAccessPath
|
||||
| System.Lazy<>.Lazy(Func<T>) | output from argument 0 [<empty>] -> return [Value] |
|
||||
| System.Lazy<>.Lazy(Func<T>, LazyThreadSafetyMode) | output from argument 0 [<empty>] -> return [Value] |
|
||||
| System.Lazy<>.Lazy(Func<T>, bool) | output from argument 0 [<empty>] -> return [Value] |
|
||||
|
||||
@@ -1,22 +1,27 @@
|
||||
import semmle.code.csharp.dataflow.LibraryTypeDataFlow
|
||||
|
||||
predicate callableFlow(string callable, string flow, boolean preservesValue) {
|
||||
query predicate callableFlow(string callable, string flow, boolean preservesValue) {
|
||||
exists(LibraryTypeDataFlow x, CallableFlowSource source, CallableFlowSink sink, Callable c |
|
||||
c.(Modifiable).isPublic() and
|
||||
c.getDeclaringType().isPublic() and
|
||||
x.callableFlow(source, sink, c, preservesValue) and
|
||||
callable = c.getQualifiedNameWithTypes() and
|
||||
flow = source.toString() + " -> " + sink.toString()
|
||||
flow = source + " -> " + sink and
|
||||
// Remove certain results to make the test output consistent
|
||||
// between different versions of .NET Core.
|
||||
not callable = "System.IO.FileStream.CopyToAsync(Stream, int, CancellationToken)"
|
||||
)
|
||||
}
|
||||
|
||||
from string entity, string flow, boolean preservesValue
|
||||
where
|
||||
callableFlow(entity, flow, preservesValue) and
|
||||
/*
|
||||
* Remove certain results to make the test output consistent
|
||||
* between different versions of .NET Core.
|
||||
*/
|
||||
|
||||
not entity = "System.IO.FileStream.CopyToAsync(Stream, int, CancellationToken)"
|
||||
select entity, flow, preservesValue
|
||||
query predicate callableFlowAccessPath(string callable, string flow) {
|
||||
exists(
|
||||
LibraryTypeDataFlow x, CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink,
|
||||
AccessPath sinkAp, Callable c
|
||||
|
|
||||
c.(Modifiable).isPublic() and
|
||||
c.getDeclaringType().isPublic() and
|
||||
x.callableFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
callable = c.getQualifiedNameWithTypes() and
|
||||
flow = source + " [" + sourceAp + "] -> " + sink + " [" + sinkAp + "]"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -143,8 +143,9 @@
|
||||
| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 |
|
||||
| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 |
|
||||
| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:129:22:129:40 | [library code] call to method Copy | LocalDataFlow.cs:129:22:129:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) |
|
||||
| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | [library code] call to method Copy |
|
||||
| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 |
|
||||
@@ -189,8 +190,9 @@
|
||||
| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:153:20:153:40 | [library code] call to method Copy | LocalDataFlow.cs:153:20:153:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | [library code] call to method Copy |
|
||||
| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 |
|
||||
@@ -284,7 +286,8 @@
|
||||
| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) |
|
||||
| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone | LocalDataFlow.cs:219:30:219:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... |
|
||||
| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 |
|
||||
@@ -294,7 +297,8 @@
|
||||
| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) |
|
||||
| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone | LocalDataFlow.cs:225:28:225:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... |
|
||||
| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 |
|
||||
@@ -358,16 +362,18 @@
|
||||
| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:274:22:274:51 | [library code] call to method Run | LocalDataFlow.cs:274:22:274:51 | call to method Run |
|
||||
| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) |
|
||||
| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run |
|
||||
| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | [library code] call to method Run |
|
||||
| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 |
|
||||
| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) |
|
||||
| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... |
|
||||
| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:280:25:280:42 | [library code] call to method Run | LocalDataFlow.cs:280:25:280:42 | call to method Run |
|
||||
| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) |
|
||||
| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run |
|
||||
| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | [library code] call to method Run |
|
||||
| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 |
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
| 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:49:30:49:30 | b | LocalDataFlow.cs:49:30:49:30 | b |
|
||||
| LocalDataFlow.cs:49:30:49:30 | b | LocalDataFlow.cs:85:21:85: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) |
|
||||
@@ -108,142 +107,184 @@
|
||||
| LocalDataFlow.cs:106:15:106:22 | [post] access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 |
|
||||
| LocalDataFlow.cs:106:15:106:22 | access to local variable nonSink3 | LocalDataFlow.cs:171:33:171:40 | access to local variable nonSink3 |
|
||||
| LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) | LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 |
|
||||
| LocalDataFlow.cs:109:22:109:39 | [library code] call to method Parse | LocalDataFlow.cs:109:22:109:39 | call to method Parse |
|
||||
| LocalDataFlow.cs:109:22:109:39 | call to method Parse | LocalDataFlow.cs:109:13:109:39 | SSA def(sink15) |
|
||||
| LocalDataFlow.cs:109:34:109:38 | [post] access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:109:22:109:39 | call to method Parse |
|
||||
| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:109:22:109:39 | [library code] call to method Parse |
|
||||
| LocalDataFlow.cs:109:34:109:38 | access to local variable sink9 | LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:110:15:110:20 | access to local variable sink15 | LocalDataFlow.cs:161:22:161:27 | access to local variable sink15 |
|
||||
| LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) | LocalDataFlow.cs:113:15:113:20 | access to local variable sink16 |
|
||||
| LocalDataFlow.cs:112:22:112:56 | [library code] call to method TryParse | LocalDataFlow.cs:112:22:112:56 | call to method TryParse |
|
||||
| LocalDataFlow.cs:112:22:112:56 | call to method TryParse | LocalDataFlow.cs:112:13:112:56 | SSA def(sink16) |
|
||||
| LocalDataFlow.cs:112:37:112:41 | [post] access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:112:22:112:56 | call to method TryParse |
|
||||
| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:112:22:112:56 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:112:22:112:56 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:112:37:112:41 | access to local variable sink9 | LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) | LocalDataFlow.cs:115:15:115:20 | access to local variable sink17 |
|
||||
| LocalDataFlow.cs:114:22:114:29 | [post] access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:49 | call to method Replace |
|
||||
| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:114:22:114:49 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:114:22:114:29 | access to local variable nonSink0 | LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:114:22:114:49 | [library code] call to method Replace | LocalDataFlow.cs:114:22:114:49 | call to method Replace |
|
||||
| LocalDataFlow.cs:114:22:114:49 | [library code] call to method Replace | LocalDataFlow.cs:114:22:114:49 | call to method Replace |
|
||||
| LocalDataFlow.cs:114:22:114:49 | call to method Replace | LocalDataFlow.cs:114:13:114:49 | SSA def(sink17) |
|
||||
| LocalDataFlow.cs:114:44:114:48 | [post] access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:114:22:114:49 | call to method Replace |
|
||||
| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:114:22:114:49 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:114:44:114:48 | access to local variable sink9 | LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) | LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 |
|
||||
| LocalDataFlow.cs:116:22:116:51 | [library code] call to method Format | LocalDataFlow.cs:116:22:116:51 | call to method Format |
|
||||
| LocalDataFlow.cs:116:22:116:51 | [library code] call to method Format | LocalDataFlow.cs:116:22:116:51 | call to method Format |
|
||||
| LocalDataFlow.cs:116:22:116:51 | call to method Format | LocalDataFlow.cs:116:13:116:51 | SSA def(sink18) |
|
||||
| LocalDataFlow.cs:116:36:116:43 | [post] access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:116:22:116:51 | call to method Format |
|
||||
| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:116:22:116:51 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:116:36:116:43 | access to local variable nonSink0 | LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:116:46:116:50 | [post] access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:116:22:116:51 | call to method Format |
|
||||
| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:116:22:116:51 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:116:46:116:50 | access to local variable sink9 | LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:117:15:117:20 | [post] access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 |
|
||||
| LocalDataFlow.cs:117:15:117:20 | access to local variable sink18 | LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 |
|
||||
| LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) | LocalDataFlow.cs:119:15:119:20 | access to local variable sink19 |
|
||||
| LocalDataFlow.cs:118:22:118:52 | [library code] call to method Format | LocalDataFlow.cs:118:22:118:52 | call to method Format |
|
||||
| LocalDataFlow.cs:118:22:118:52 | [library code] call to method Format | LocalDataFlow.cs:118:22:118:52 | call to method Format |
|
||||
| LocalDataFlow.cs:118:22:118:52 | call to method Format | LocalDataFlow.cs:118:13:118:52 | SSA def(sink19) |
|
||||
| LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | LocalDataFlow.cs:118:22:118:52 | call to method Format |
|
||||
| LocalDataFlow.cs:118:36:118:41 | access to local variable sink18 | LocalDataFlow.cs:118:22:118:52 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:118:44:118:51 | [post] access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:118:22:118:52 | call to method Format |
|
||||
| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:118:22:118:52 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:118:44:118:51 | access to local variable nonSink0 | LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) | LocalDataFlow.cs:121:15:121:20 | access to local variable sink45 |
|
||||
| LocalDataFlow.cs:120:22:120:38 | [library code] call to method Parse | LocalDataFlow.cs:120:22:120:38 | call to method Parse |
|
||||
| LocalDataFlow.cs:120:22:120:38 | call to method Parse | LocalDataFlow.cs:120:13:120:38 | SSA def(sink45) |
|
||||
| LocalDataFlow.cs:120:33:120:37 | [post] access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:38 | call to method Parse |
|
||||
| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:120:22:120:38 | [library code] call to method Parse |
|
||||
| LocalDataFlow.cs:120:33:120:37 | access to local variable sink9 | LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) | LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 |
|
||||
| LocalDataFlow.cs:123:22:123:56 | [library code] call to method TryParse | LocalDataFlow.cs:123:22:123:56 | call to method TryParse |
|
||||
| LocalDataFlow.cs:123:22:123:56 | call to method TryParse | LocalDataFlow.cs:123:13:123:56 | SSA def(sink46) |
|
||||
| LocalDataFlow.cs:123:36:123:40 | [post] access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:123:22:123:56 | call to method TryParse |
|
||||
| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:123:22:123:56 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:123:22:123:56 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:123:36:123:40 | access to local variable sink9 | LocalDataFlow.cs:163:22:163:26 | access to local variable sink9 |
|
||||
| LocalDataFlow.cs:124:15:124:20 | access to local variable sink46 | LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 |
|
||||
| LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) | LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 |
|
||||
| LocalDataFlow.cs:125:22:125:43 | [library code] call to method ToByte | LocalDataFlow.cs:125:22:125:43 | call to method ToByte |
|
||||
| LocalDataFlow.cs:125:22:125:43 | call to method ToByte | LocalDataFlow.cs:125:13:125:43 | SSA def(sink47) |
|
||||
| LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | LocalDataFlow.cs:125:22:125:43 | call to method ToByte |
|
||||
| LocalDataFlow.cs:125:37:125:42 | access to local variable sink46 | LocalDataFlow.cs:125:22:125:43 | [library code] call to method ToByte |
|
||||
| LocalDataFlow.cs:126:15:126:20 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 |
|
||||
| LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) | LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 |
|
||||
| LocalDataFlow.cs:127:22:127:46 | [library code] call to method Concat | LocalDataFlow.cs:127:22:127:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:127:22:127:46 | [library code] call to method Concat | LocalDataFlow.cs:127:22:127:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:127:22:127:46 | call to method Concat | LocalDataFlow.cs:127:13:127:46 | SSA def(sink49) |
|
||||
| LocalDataFlow.cs:127:36:127:37 | "" | LocalDataFlow.cs:127:22:127:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:127:40:127:45 | (...) ... | LocalDataFlow.cs:127:22:127:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:127:36:127:37 | "" | LocalDataFlow.cs:127:22:127:46 | [library code] call to method Concat |
|
||||
| LocalDataFlow.cs:127:40:127:45 | (...) ... | LocalDataFlow.cs:127:22:127:46 | [library code] call to method Concat |
|
||||
| LocalDataFlow.cs:127:40:127:45 | access to local variable sink47 | LocalDataFlow.cs:127:40:127:45 | (...) ... |
|
||||
| LocalDataFlow.cs:128:15:128:20 | [post] access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 |
|
||||
| LocalDataFlow.cs:128:15:128:20 | access to local variable sink49 | LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 |
|
||||
| LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) | LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:129:22:129:40 | [library code] call to method Copy | LocalDataFlow.cs:129:22:129:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:129:22:129:40 | call to method Copy | LocalDataFlow.cs:129:13:129:40 | SSA def(sink50) |
|
||||
| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:129:34:129:39 | access to local variable sink49 | LocalDataFlow.cs:129:22:129:40 | [library code] call to method Copy |
|
||||
| LocalDataFlow.cs:130:15:130:20 | [post] access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:130:15:130:20 | access to local variable sink50 | LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 |
|
||||
| LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) | LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 |
|
||||
| LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:22:131:54 | call to method Join | LocalDataFlow.cs:131:13:131:54 | SSA def(sink51) |
|
||||
| LocalDataFlow.cs:131:34:131:37 | ", " | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:40:131:41 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:52:131:53 | "" | LocalDataFlow.cs:131:22:131:54 | call to method Join |
|
||||
| LocalDataFlow.cs:131:34:131:37 | ", " | LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:131:40:131:41 | "" | LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:131:44:131:49 | access to local variable sink50 | LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:131:52:131:53 | "" | LocalDataFlow.cs:131:22:131:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:132:15:132:20 | [post] access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 |
|
||||
| LocalDataFlow.cs:132:15:132:20 | access to local variable sink51 | LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 |
|
||||
| LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) | LocalDataFlow.cs:134:15:134:20 | access to local variable sink52 |
|
||||
| LocalDataFlow.cs:133:22:133:23 | "" | LocalDataFlow.cs:133:22:133:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:133:22:133:23 | "" | LocalDataFlow.cs:133:22:133:41 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:133:22:133:41 | [library code] call to method Insert | LocalDataFlow.cs:133:22:133:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:133:22:133:41 | [library code] call to method Insert | LocalDataFlow.cs:133:22:133:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:133:22:133:41 | call to method Insert | LocalDataFlow.cs:133:13:133:41 | SSA def(sink52) |
|
||||
| LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | LocalDataFlow.cs:133:22:133:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:133:35:133:40 | access to local variable sink51 | LocalDataFlow.cs:133:22:133:41 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) | LocalDataFlow.cs:138:15:138:22 | access to local variable nonSink2 |
|
||||
| LocalDataFlow.cs:137:20:137:40 | [library code] call to method Parse | LocalDataFlow.cs:137:20:137:40 | call to method Parse |
|
||||
| LocalDataFlow.cs:137:20:137:40 | call to method Parse | LocalDataFlow.cs:137:9:137:40 | SSA def(nonSink2) |
|
||||
| LocalDataFlow.cs:137:32:137:39 | [post] access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:137:20:137:40 | call to method Parse |
|
||||
| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:137:20:137:40 | [library code] call to method Parse |
|
||||
| LocalDataFlow.cs:137:32:137:39 | access to local variable nonSink0 | LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) | LocalDataFlow.cs:140:15:140:22 | access to local variable nonSink7 |
|
||||
| LocalDataFlow.cs:139:24:139:61 | [library code] call to method TryParse | LocalDataFlow.cs:139:24:139:61 | call to method TryParse |
|
||||
| LocalDataFlow.cs:139:24:139:61 | call to method TryParse | LocalDataFlow.cs:139:13:139:61 | SSA def(nonSink7) |
|
||||
| LocalDataFlow.cs:139:39:139:46 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:139:24:139:61 | call to method TryParse |
|
||||
| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:139:24:139:61 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:139:24:139:61 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:139:39:139:46 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) | LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:141:20:141:27 | [post] access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace |
|
||||
| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:141:20:141:27 | access to local variable nonSink0 | LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:141:20:141:50 | [library code] call to method Replace | LocalDataFlow.cs:141:20:141:50 | call to method Replace |
|
||||
| LocalDataFlow.cs:141:20:141:50 | [library code] call to method Replace | LocalDataFlow.cs:141:20:141:50 | call to method Replace |
|
||||
| LocalDataFlow.cs:141:20:141:50 | call to method Replace | LocalDataFlow.cs:141:9:141:50 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | call to method Replace |
|
||||
| LocalDataFlow.cs:141:42:141:49 | access to local variable nonSink0 | LocalDataFlow.cs:141:20:141:50 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:142:15:142:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:142:15:142:22 | access to local variable nonSink0 | LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) | LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:143:20:143:52 | [library code] call to method Format | LocalDataFlow.cs:143:20:143:52 | call to method Format |
|
||||
| LocalDataFlow.cs:143:20:143:52 | [library code] call to method Format | LocalDataFlow.cs:143:20:143:52 | call to method Format |
|
||||
| LocalDataFlow.cs:143:20:143:52 | call to method Format | LocalDataFlow.cs:143:9:143:52 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:143:34:143:41 | [post] access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format |
|
||||
| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:143:34:143:41 | access to local variable nonSink0 | LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | call to method Format |
|
||||
| LocalDataFlow.cs:143:44:143:51 | access to local variable nonSink0 | LocalDataFlow.cs:143:20:143:52 | [library code] call to method Format |
|
||||
| LocalDataFlow.cs:144:15:144:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:144:15:144:22 | access to local variable nonSink0 | LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) | LocalDataFlow.cs:146:15:146:22 | access to local variable nonSink7 |
|
||||
| LocalDataFlow.cs:145:20:145:39 | [library code] call to method Parse | LocalDataFlow.cs:145:20:145:39 | call to method Parse |
|
||||
| LocalDataFlow.cs:145:20:145:39 | call to method Parse | LocalDataFlow.cs:145:9:145:39 | SSA def(nonSink7) |
|
||||
| LocalDataFlow.cs:145:31:145:38 | [post] access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:145:20:145:39 | call to method Parse |
|
||||
| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:145:20:145:39 | [library code] call to method Parse |
|
||||
| LocalDataFlow.cs:145:31:145:38 | access to local variable nonSink0 | LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) | LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 |
|
||||
| LocalDataFlow.cs:147:20:147:57 | [library code] call to method TryParse | LocalDataFlow.cs:147:20:147:57 | call to method TryParse |
|
||||
| LocalDataFlow.cs:147:20:147:57 | call to method TryParse | LocalDataFlow.cs:147:9:147:57 | SSA def(nonSink7) |
|
||||
| LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | LocalDataFlow.cs:147:20:147:57 | call to method TryParse |
|
||||
| LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | LocalDataFlow.cs:147:20:147:57 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:147:34:147:41 | access to local variable nonSink0 | LocalDataFlow.cs:147:20:147:57 | [library code] call to method TryParse |
|
||||
| LocalDataFlow.cs:148:15:148:22 | access to local variable nonSink7 | LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 |
|
||||
| LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) | LocalDataFlow.cs:150:15:150:23 | access to local variable nonSink14 |
|
||||
| LocalDataFlow.cs:149:25:149:48 | [library code] call to method ToByte | LocalDataFlow.cs:149:25:149:48 | call to method ToByte |
|
||||
| LocalDataFlow.cs:149:25:149:48 | call to method ToByte | LocalDataFlow.cs:149:13:149:48 | SSA def(nonSink14) |
|
||||
| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:149:25:149:48 | call to method ToByte |
|
||||
| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:149:25:149:48 | [library code] call to method ToByte |
|
||||
| LocalDataFlow.cs:149:40:149:47 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 |
|
||||
| LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) | LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:151:20:151:46 | [library code] call to method Concat | LocalDataFlow.cs:151:20:151:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:151:20:151:46 | [library code] call to method Concat | LocalDataFlow.cs:151:20:151:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:151:20:151:46 | call to method Concat | LocalDataFlow.cs:151:9:151:46 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:151:34:151:35 | "" | LocalDataFlow.cs:151:20:151:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:151:38:151:45 | (...) ... | LocalDataFlow.cs:151:20:151:46 | call to method Concat |
|
||||
| LocalDataFlow.cs:151:34:151:35 | "" | LocalDataFlow.cs:151:20:151:46 | [library code] call to method Concat |
|
||||
| LocalDataFlow.cs:151:38:151:45 | (...) ... | LocalDataFlow.cs:151:20:151:46 | [library code] call to method Concat |
|
||||
| LocalDataFlow.cs:151:38:151:45 | access to local variable nonSink7 | LocalDataFlow.cs:151:38:151:45 | (...) ... |
|
||||
| LocalDataFlow.cs:152:15:152:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:152:15:152:22 | access to local variable nonSink0 | LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) | LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:153:20:153:40 | [library code] call to method Copy | LocalDataFlow.cs:153:20:153:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:153:20:153:40 | call to method Copy | LocalDataFlow.cs:153:9:153:40 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | call to method Copy |
|
||||
| LocalDataFlow.cs:153:32:153:39 | access to local variable nonSink0 | LocalDataFlow.cs:153:20:153:40 | [library code] call to method Copy |
|
||||
| LocalDataFlow.cs:154:15:154:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:154:15:154:22 | access to local variable nonSink0 | LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) | LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:20:155:54 | call to method Join | LocalDataFlow.cs:155:9:155:54 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:155:32:155:35 | ", " | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:38:155:39 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:52:155:53 | "" | LocalDataFlow.cs:155:20:155:54 | call to method Join |
|
||||
| LocalDataFlow.cs:155:32:155:35 | ", " | LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:155:38:155:39 | "" | LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:155:42:155:49 | access to local variable nonSink0 | LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:155:52:155:53 | "" | LocalDataFlow.cs:155:20:155:54 | [library code] call to method Join |
|
||||
| LocalDataFlow.cs:156:15:156:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:156:15:156:22 | access to local variable nonSink0 | LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) | LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:157:20:157:21 | "" | LocalDataFlow.cs:157:20:157:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:157:20:157:21 | "" | LocalDataFlow.cs:157:20:157:41 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:157:20:157:41 | [library code] call to method Insert | LocalDataFlow.cs:157:20:157:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:157:20:157:41 | [library code] call to method Insert | LocalDataFlow.cs:157:20:157:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:157:20:157:41 | call to method Insert | LocalDataFlow.cs:157:9:157:41 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | LocalDataFlow.cs:157:20:157:41 | call to method Insert |
|
||||
| LocalDataFlow.cs:157:33:157:40 | access to local variable nonSink0 | LocalDataFlow.cs:157:20:157:41 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:158:15:158:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:158:15:158:22 | access to local variable nonSink0 | LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:161:13:161:32 | SSA def(sink20) | LocalDataFlow.cs:162:15:162:20 | access to local variable sink20 |
|
||||
@@ -279,199 +320,262 @@
|
||||
| LocalDataFlow.cs:179:20:179:36 | ... \|\| ... | LocalDataFlow.cs:179:9:179:36 | SSA def(nonSink7) |
|
||||
| LocalDataFlow.cs:179:32:179:36 | false | LocalDataFlow.cs:179:20:179:36 | ... \|\| ... |
|
||||
| LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) | LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:183:22:183:42 | [library code] object creation of type Uri | LocalDataFlow.cs:183:22:183:42 | object creation of type Uri |
|
||||
| LocalDataFlow.cs:183:22:183:42 | object creation of type Uri | LocalDataFlow.cs:183:13:183:42 | SSA def(sink26) |
|
||||
| LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | LocalDataFlow.cs:183:22:183:42 | object creation of type Uri |
|
||||
| LocalDataFlow.cs:183:37:183:41 | access to local variable sink9 | LocalDataFlow.cs:183:22:183:42 | [library code] object creation of type Uri |
|
||||
| LocalDataFlow.cs:184:15:184:20 | [post] access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:184:15:184:20 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) | LocalDataFlow.cs:186:15:186:20 | access to local variable sink27 |
|
||||
| LocalDataFlow.cs:185:22:185:27 | [post] access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:185:22:185:38 | [library code] call to method ToString |
|
||||
| LocalDataFlow.cs:185:22:185:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:185:22:185:38 | [library code] call to method ToString | LocalDataFlow.cs:185:22:185:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:185:22:185:38 | call to method ToString | LocalDataFlow.cs:185:13:185:38 | SSA def(sink27) |
|
||||
| LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) | LocalDataFlow.cs:188:15:188:20 | access to local variable sink28 |
|
||||
| LocalDataFlow.cs:187:22:187:27 | [post] access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:187:22:187:40 | [library code] access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:187:22:187:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:187:22:187:40 | [library code] access to property PathAndQuery | LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:187:22:187:40 | access to property PathAndQuery | LocalDataFlow.cs:187:13:187:40 | SSA def(sink28) |
|
||||
| LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) | LocalDataFlow.cs:190:15:190:20 | access to local variable sink29 |
|
||||
| LocalDataFlow.cs:189:22:189:27 | [post] access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:33 | access to property Query |
|
||||
| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:189:22:189:33 | [library code] access to property Query |
|
||||
| LocalDataFlow.cs:189:22:189:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 |
|
||||
| LocalDataFlow.cs:189:22:189:33 | [library code] access to property Query | LocalDataFlow.cs:189:22:189:33 | access to property Query |
|
||||
| LocalDataFlow.cs:189:22:189:33 | access to property Query | LocalDataFlow.cs:189:13:189:33 | SSA def(sink29) |
|
||||
| LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) | LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 |
|
||||
| LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:42 | access to property OriginalString |
|
||||
| LocalDataFlow.cs:191:22:191:27 | access to local variable sink26 | LocalDataFlow.cs:191:22:191:42 | [library code] access to property OriginalString |
|
||||
| LocalDataFlow.cs:191:22:191:42 | [library code] access to property OriginalString | LocalDataFlow.cs:191:22:191:42 | access to property OriginalString |
|
||||
| LocalDataFlow.cs:191:22:191:42 | access to property OriginalString | LocalDataFlow.cs:191:13:191:42 | SSA def(sink30) |
|
||||
| LocalDataFlow.cs:192:15:192:20 | [post] access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 |
|
||||
| LocalDataFlow.cs:192:15:192:20 | access to local variable sink30 | LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 |
|
||||
| LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) | LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:195:24:195:47 | [library code] object creation of type Uri | LocalDataFlow.cs:195:24:195:47 | object creation of type Uri |
|
||||
| LocalDataFlow.cs:195:24:195:47 | object creation of type Uri | LocalDataFlow.cs:195:13:195:47 | SSA def(nonSink8) |
|
||||
| LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | LocalDataFlow.cs:195:24:195:47 | object creation of type Uri |
|
||||
| LocalDataFlow.cs:195:39:195:46 | access to local variable nonSink0 | LocalDataFlow.cs:195:24:195:47 | [library code] object creation of type Uri |
|
||||
| LocalDataFlow.cs:196:15:196:22 | [post] access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:196:15:196:22 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) | LocalDataFlow.cs:198:15:198:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:197:20:197:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:197:20:197:38 | [library code] call to method ToString |
|
||||
| LocalDataFlow.cs:197:20:197:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:197:20:197:38 | [library code] call to method ToString | LocalDataFlow.cs:197:20:197:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:197:20:197:38 | call to method ToString | LocalDataFlow.cs:197:9:197:38 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) | LocalDataFlow.cs:200:15:200:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:199:20:199:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:199:20:199:40 | [library code] access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:199:20:199:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:199:20:199:40 | [library code] access to property PathAndQuery | LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery |
|
||||
| LocalDataFlow.cs:199:20:199:40 | access to property PathAndQuery | LocalDataFlow.cs:199:9:199:40 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) | LocalDataFlow.cs:202:15:202:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:201:20:201:27 | [post] access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:33 | access to property Query |
|
||||
| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:201:20:201:33 | [library code] access to property Query |
|
||||
| LocalDataFlow.cs:201:20:201:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 |
|
||||
| LocalDataFlow.cs:201:20:201:33 | [library code] access to property Query | LocalDataFlow.cs:201:20:201:33 | access to property Query |
|
||||
| LocalDataFlow.cs:201:20:201:33 | access to property Query | LocalDataFlow.cs:201:9:201:33 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) | LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:42 | access to property OriginalString |
|
||||
| LocalDataFlow.cs:203:20:203:27 | access to local variable nonSink8 | LocalDataFlow.cs:203:20:203:42 | [library code] access to property OriginalString |
|
||||
| LocalDataFlow.cs:203:20:203:42 | [library code] access to property OriginalString | LocalDataFlow.cs:203:20:203:42 | access to property OriginalString |
|
||||
| LocalDataFlow.cs:203:20:203:42 | access to property OriginalString | LocalDataFlow.cs:203:9:203:42 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:204:15:204:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:204:15:204:22 | access to local variable nonSink0 | LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) | LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 |
|
||||
| LocalDataFlow.cs:207:22:207:55 | [library code] object creation of type StringReader | LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader |
|
||||
| LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader | LocalDataFlow.cs:207:13:207:55 | SSA def(sink31) |
|
||||
| LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | LocalDataFlow.cs:207:22:207:55 | object creation of type StringReader |
|
||||
| LocalDataFlow.cs:207:49:207:54 | access to local variable sink30 | LocalDataFlow.cs:207:22:207:55 | [library code] object creation of type StringReader |
|
||||
| LocalDataFlow.cs:208:15:208:20 | [post] access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 |
|
||||
| LocalDataFlow.cs:208:15:208:20 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 |
|
||||
| LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) | LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 |
|
||||
| LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:209:22:209:27 | access to local variable sink31 | LocalDataFlow.cs:209:22:209:39 | [library code] call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:209:22:209:39 | [library code] call to method ReadToEnd | LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:209:22:209:39 | call to method ReadToEnd | LocalDataFlow.cs:209:13:209:39 | SSA def(sink32) |
|
||||
| LocalDataFlow.cs:210:15:210:20 | [post] access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 |
|
||||
| LocalDataFlow.cs:210:15:210:20 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 |
|
||||
| LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) | LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 |
|
||||
| LocalDataFlow.cs:213:24:213:59 | [library code] object creation of type StringReader | LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader |
|
||||
| LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader | LocalDataFlow.cs:213:13:213:59 | SSA def(nonSink9) |
|
||||
| LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | LocalDataFlow.cs:213:24:213:59 | object creation of type StringReader |
|
||||
| LocalDataFlow.cs:213:51:213:58 | access to local variable nonSink0 | LocalDataFlow.cs:213:24:213:59 | [library code] object creation of type StringReader |
|
||||
| LocalDataFlow.cs:214:15:214:22 | [post] access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 |
|
||||
| LocalDataFlow.cs:214:15:214:22 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 |
|
||||
| LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) | LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:215:20:215:27 | access to local variable nonSink9 | LocalDataFlow.cs:215:20:215:39 | [library code] call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:215:20:215:39 | [library code] call to method ReadToEnd | LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd |
|
||||
| LocalDataFlow.cs:215:20:215:39 | call to method ReadToEnd | LocalDataFlow.cs:215:9:215:39 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:216:15:216:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:216:15:216:22 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) | LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:219:22:219:127 | (...) ... | LocalDataFlow.cs:219:13:219:127 | SSA def(sink33) |
|
||||
| LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:48 | call to method Substring |
|
||||
| LocalDataFlow.cs:219:30:219:48 | call to method Substring | LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | LocalDataFlow.cs:219:30:219:77 | call to method ToUpper |
|
||||
| LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | LocalDataFlow.cs:219:30:219:87 | call to method Trim |
|
||||
| LocalDataFlow.cs:219:30:219:87 | call to method Trim | LocalDataFlow.cs:219:30:219:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:219:30:219:105 | call to method Replace | LocalDataFlow.cs:219:30:219:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:35 | access to local variable sink32 | LocalDataFlow.cs:219:30:219:48 | [library code] call to method Substring |
|
||||
| LocalDataFlow.cs:219:30:219:48 | [library code] call to method Substring | LocalDataFlow.cs:219:30:219:48 | call to method Substring |
|
||||
| LocalDataFlow.cs:219:30:219:48 | call to method Substring | LocalDataFlow.cs:219:30:219:67 | [library code] call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:219:30:219:67 | [library code] call to method ToLowerInvariant | LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:219:30:219:67 | call to method ToLowerInvariant | LocalDataFlow.cs:219:30:219:77 | [library code] call to method ToUpper |
|
||||
| LocalDataFlow.cs:219:30:219:77 | [library code] call to method ToUpper | LocalDataFlow.cs:219:30:219:77 | call to method ToUpper |
|
||||
| LocalDataFlow.cs:219:30:219:77 | call to method ToUpper | LocalDataFlow.cs:219:30:219:87 | [library code] call to method Trim |
|
||||
| LocalDataFlow.cs:219:30:219:87 | [library code] call to method Trim | LocalDataFlow.cs:219:30:219:87 | call to method Trim |
|
||||
| LocalDataFlow.cs:219:30:219:87 | call to method Trim | LocalDataFlow.cs:219:30:219:105 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:219:30:219:105 | [library code] call to method Replace | LocalDataFlow.cs:219:30:219:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:219:30:219:105 | [library code] call to method Replace | LocalDataFlow.cs:219:30:219:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:219:30:219:105 | call to method Replace | LocalDataFlow.cs:219:30:219:119 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:219:30:219:119 | [library code] call to method Insert | LocalDataFlow.cs:219:30:219:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:219:30:219:119 | [library code] call to method Insert | LocalDataFlow.cs:219:30:219:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:119 | call to method Insert | LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone | LocalDataFlow.cs:219:30:219:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:127 | [library code] call to method Clone | LocalDataFlow.cs:219:30:219:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:219:30:219:127 | call to method Clone | LocalDataFlow.cs:219:22:219:127 | (...) ... |
|
||||
| LocalDataFlow.cs:219:102:219:104 | "b" | LocalDataFlow.cs:219:30:219:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:219:117:219:118 | "" | LocalDataFlow.cs:219:30:219:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:219:102:219:104 | "b" | LocalDataFlow.cs:219:30:219:105 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:219:117:219:118 | "" | LocalDataFlow.cs:219:30:219:119 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:220:15:220:20 | [post] access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:220:15:220:20 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) | LocalDataFlow.cs:222:15:222:20 | access to local variable sink48 |
|
||||
| LocalDataFlow.cs:221:22:221:27 | [post] access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:39 | call to method Normalize |
|
||||
| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:221:22:221:39 | [library code] call to method Normalize |
|
||||
| LocalDataFlow.cs:221:22:221:27 | access to local variable sink33 | LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 |
|
||||
| LocalDataFlow.cs:221:22:221:39 | call to method Normalize | LocalDataFlow.cs:221:22:221:52 | call to method Remove |
|
||||
| LocalDataFlow.cs:221:22:221:52 | call to method Remove | LocalDataFlow.cs:221:22:221:63 | call to method Split |
|
||||
| LocalDataFlow.cs:221:22:221:39 | [library code] call to method Normalize | LocalDataFlow.cs:221:22:221:39 | call to method Normalize |
|
||||
| LocalDataFlow.cs:221:22:221:39 | call to method Normalize | LocalDataFlow.cs:221:22:221:52 | [library code] call to method Remove |
|
||||
| LocalDataFlow.cs:221:22:221:52 | [library code] call to method Remove | LocalDataFlow.cs:221:22:221:52 | call to method Remove |
|
||||
| LocalDataFlow.cs:221:22:221:52 | call to method Remove | LocalDataFlow.cs:221:22:221:63 | [library code] call to method Split |
|
||||
| LocalDataFlow.cs:221:22:221:63 | [library code] call to method Split | LocalDataFlow.cs:221:22:221:63 | call to method Split |
|
||||
| LocalDataFlow.cs:221:22:221:63 | call to method Split | LocalDataFlow.cs:221:13:221:63 | SSA def(sink48) |
|
||||
| LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) | LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:225:20:225:127 | (...) ... | LocalDataFlow.cs:225:9:225:127 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:48 | call to method Substring |
|
||||
| LocalDataFlow.cs:225:28:225:48 | call to method Substring | LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | LocalDataFlow.cs:225:28:225:77 | call to method ToUpper |
|
||||
| LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | LocalDataFlow.cs:225:28:225:87 | call to method Trim |
|
||||
| LocalDataFlow.cs:225:28:225:87 | call to method Trim | LocalDataFlow.cs:225:28:225:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:225:28:225:105 | call to method Replace | LocalDataFlow.cs:225:28:225:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:35 | access to local variable nonSink0 | LocalDataFlow.cs:225:28:225:48 | [library code] call to method Substring |
|
||||
| LocalDataFlow.cs:225:28:225:48 | [library code] call to method Substring | LocalDataFlow.cs:225:28:225:48 | call to method Substring |
|
||||
| LocalDataFlow.cs:225:28:225:48 | call to method Substring | LocalDataFlow.cs:225:28:225:67 | [library code] call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:225:28:225:67 | [library code] call to method ToLowerInvariant | LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant |
|
||||
| LocalDataFlow.cs:225:28:225:67 | call to method ToLowerInvariant | LocalDataFlow.cs:225:28:225:77 | [library code] call to method ToUpper |
|
||||
| LocalDataFlow.cs:225:28:225:77 | [library code] call to method ToUpper | LocalDataFlow.cs:225:28:225:77 | call to method ToUpper |
|
||||
| LocalDataFlow.cs:225:28:225:77 | call to method ToUpper | LocalDataFlow.cs:225:28:225:87 | [library code] call to method Trim |
|
||||
| LocalDataFlow.cs:225:28:225:87 | [library code] call to method Trim | LocalDataFlow.cs:225:28:225:87 | call to method Trim |
|
||||
| LocalDataFlow.cs:225:28:225:87 | call to method Trim | LocalDataFlow.cs:225:28:225:105 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:225:28:225:105 | [library code] call to method Replace | LocalDataFlow.cs:225:28:225:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:225:28:225:105 | [library code] call to method Replace | LocalDataFlow.cs:225:28:225:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:225:28:225:105 | call to method Replace | LocalDataFlow.cs:225:28:225:119 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:225:28:225:119 | [library code] call to method Insert | LocalDataFlow.cs:225:28:225:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:225:28:225:119 | [library code] call to method Insert | LocalDataFlow.cs:225:28:225:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:119 | call to method Insert | LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone | LocalDataFlow.cs:225:28:225:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:127 | [library code] call to method Clone | LocalDataFlow.cs:225:28:225:127 | call to method Clone |
|
||||
| LocalDataFlow.cs:225:28:225:127 | call to method Clone | LocalDataFlow.cs:225:20:225:127 | (...) ... |
|
||||
| LocalDataFlow.cs:225:102:225:104 | "b" | LocalDataFlow.cs:225:28:225:105 | call to method Replace |
|
||||
| LocalDataFlow.cs:225:117:225:118 | "" | LocalDataFlow.cs:225:28:225:119 | call to method Insert |
|
||||
| LocalDataFlow.cs:225:102:225:104 | "b" | LocalDataFlow.cs:225:28:225:105 | [library code] call to method Replace |
|
||||
| LocalDataFlow.cs:225:117:225:118 | "" | LocalDataFlow.cs:225:28:225:119 | [library code] call to method Insert |
|
||||
| LocalDataFlow.cs:226:15:226:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:226:15:226:22 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) | LocalDataFlow.cs:228:15:228:23 | access to local variable nonSink15 |
|
||||
| LocalDataFlow.cs:227:25:227:32 | [post] access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:44 | call to method Normalize |
|
||||
| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:227:25:227:44 | [library code] call to method Normalize |
|
||||
| LocalDataFlow.cs:227:25:227:32 | access to local variable nonSink0 | LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:227:25:227:44 | call to method Normalize | LocalDataFlow.cs:227:25:227:57 | call to method Remove |
|
||||
| LocalDataFlow.cs:227:25:227:57 | call to method Remove | LocalDataFlow.cs:227:25:227:68 | call to method Split |
|
||||
| LocalDataFlow.cs:227:25:227:44 | [library code] call to method Normalize | LocalDataFlow.cs:227:25:227:44 | call to method Normalize |
|
||||
| LocalDataFlow.cs:227:25:227:44 | call to method Normalize | LocalDataFlow.cs:227:25:227:57 | [library code] call to method Remove |
|
||||
| LocalDataFlow.cs:227:25:227:57 | [library code] call to method Remove | LocalDataFlow.cs:227:25:227:57 | call to method Remove |
|
||||
| LocalDataFlow.cs:227:25:227:57 | call to method Remove | LocalDataFlow.cs:227:25:227:68 | [library code] call to method Split |
|
||||
| LocalDataFlow.cs:227:25:227:68 | [library code] call to method Split | LocalDataFlow.cs:227:25:227:68 | call to method Split |
|
||||
| LocalDataFlow.cs:227:25:227:68 | call to method Split | LocalDataFlow.cs:227:13:227:68 | SSA def(nonSink15) |
|
||||
| LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) | LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 |
|
||||
| LocalDataFlow.cs:231:22:231:46 | [library code] object creation of type StringBuilder | LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder | LocalDataFlow.cs:231:13:231:46 | SSA def(sink34) |
|
||||
| LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | LocalDataFlow.cs:231:22:231:46 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:231:40:231:45 | access to local variable sink33 | LocalDataFlow.cs:231:22:231:46 | [library code] object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:232:15:232:20 | [post] access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 |
|
||||
| LocalDataFlow.cs:232:15:232:20 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 |
|
||||
| LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) | LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 |
|
||||
| LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:233:22:233:27 | access to local variable sink34 | LocalDataFlow.cs:233:22:233:38 | [library code] call to method ToString |
|
||||
| LocalDataFlow.cs:233:22:233:38 | [library code] call to method ToString | LocalDataFlow.cs:233:22:233:38 | call to method ToString |
|
||||
| LocalDataFlow.cs:233:22:233:38 | call to method ToString | LocalDataFlow.cs:233:13:233:38 | SSA def(sink35) |
|
||||
| LocalDataFlow.cs:234:15:234:20 | [post] access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 |
|
||||
| LocalDataFlow.cs:234:15:234:20 | access to local variable sink35 | LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 |
|
||||
| LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 |
|
||||
| LocalDataFlow.cs:235:22:235:42 | [library code] object creation of type StringBuilder | LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder | LocalDataFlow.cs:235:13:235:42 | SSA def(sink36) |
|
||||
| LocalDataFlow.cs:235:40:235:41 | "" | LocalDataFlow.cs:235:22:235:42 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:235:40:235:41 | "" | LocalDataFlow.cs:235:22:235:42 | [library code] object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:236:9:236:14 | [post] access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 |
|
||||
| LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 | LocalDataFlow.cs:237:15:237:20 | access to local variable sink36 |
|
||||
| LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 |
|
||||
| LocalDataFlow.cs:236:9:236:33 | [library code] call to method AppendLine | LocalDataFlow.cs:236:9:236:14 | access to local variable sink36 |
|
||||
| LocalDataFlow.cs:236:27:236:32 | access to local variable sink35 | LocalDataFlow.cs:236:9:236:33 | [library code] call to method AppendLine |
|
||||
| LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) | LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:240:25:240:51 | [library code] object creation of type StringBuilder | LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder | LocalDataFlow.cs:240:13:240:51 | SSA def(nonSink10) |
|
||||
| LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | LocalDataFlow.cs:240:25:240:51 | object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:240:43:240:50 | access to local variable nonSink0 | LocalDataFlow.cs:240:25:240:51 | [library code] object creation of type StringBuilder |
|
||||
| LocalDataFlow.cs:241:15:241:23 | [post] access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:241:15:241:23 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) | LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:242:20:242:28 | [post] access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:39 | call to method ToString |
|
||||
| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:242:20:242:39 | [library code] call to method ToString |
|
||||
| LocalDataFlow.cs:242:20:242:28 | access to local variable nonSink10 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:242:20:242:39 | [library code] call to method ToString | LocalDataFlow.cs:242:20:242:39 | call to method ToString |
|
||||
| LocalDataFlow.cs:242:20:242:39 | call to method ToString | LocalDataFlow.cs:242:9:242:39 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:243:15:243:22 | [post] access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:243:15:243:22 | access to local variable nonSink0 | LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:244:9:244:17 | [post] access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 | LocalDataFlow.cs:245:15:245:23 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:244:9:244:38 | [library code] call to method AppendLine | LocalDataFlow.cs:244:9:244:17 | access to local variable nonSink10 |
|
||||
| LocalDataFlow.cs:244:30:244:37 | access to local variable nonSink0 | LocalDataFlow.cs:244:9:244:38 | [library code] call to method AppendLine |
|
||||
| LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) | LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:248:13:248:52 | SSA qualifier def(taintedDataContract.AList) | LocalDataFlow.cs:251:22:251:46 | access to property AList |
|
||||
| LocalDataFlow.cs:248:35:248:52 | object creation of type DataContract | LocalDataFlow.cs:248:13:248:52 | SSA def(taintedDataContract) |
|
||||
| LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) | LocalDataFlow.cs:250:15:250:20 | access to local variable sink53 |
|
||||
| LocalDataFlow.cs:249:22:249:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:249:22:249:48 | [library code] access to property AString |
|
||||
| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:249:22:249:48 | access to property AString |
|
||||
| LocalDataFlow.cs:249:22:249:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:249:22:249:48 | [library code] access to property AString | LocalDataFlow.cs:249:22:249:48 | access to property AString |
|
||||
| LocalDataFlow.cs:249:22:249:48 | access to property AString | LocalDataFlow.cs:249:13:249:48 | SSA def(sink53) |
|
||||
| LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) | LocalDataFlow.cs:252:15:252:20 | access to local variable sink54 |
|
||||
| LocalDataFlow.cs:251:22:251:40 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:46 | [library code] access to property AList |
|
||||
| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:251:22:251:46 | access to property AList |
|
||||
| LocalDataFlow.cs:251:22:251:40 | access to local variable taintedDataContract | LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:251:22:251:46 | [library code] access to property AList | LocalDataFlow.cs:251:22:251:46 | access to property AList |
|
||||
| LocalDataFlow.cs:251:22:251:46 | [post] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList |
|
||||
| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:251:22:251:49 | access to indexer |
|
||||
| LocalDataFlow.cs:251:22:251:46 | access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList |
|
||||
| LocalDataFlow.cs:251:22:251:49 | access to indexer | LocalDataFlow.cs:251:22:251:57 | [library code] access to property AString |
|
||||
| LocalDataFlow.cs:251:22:251:49 | access to indexer | LocalDataFlow.cs:251:22:251:57 | access to property AString |
|
||||
| LocalDataFlow.cs:251:22:251:57 | [library code] access to property AString | LocalDataFlow.cs:251:22:251:57 | access to property AString |
|
||||
| LocalDataFlow.cs:251:22:251:57 | access to property AString | LocalDataFlow.cs:251:13:251:57 | SSA def(sink54) |
|
||||
| LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) | LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract |
|
||||
| LocalDataFlow.cs:255:38:255:55 | object creation of type DataContract | LocalDataFlow.cs:255:13:255:55 | SSA def(nonTaintedDataContract) |
|
||||
| LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) | LocalDataFlow.cs:257:15:257:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:256:20:256:49 | [library code] access to property AString |
|
||||
| LocalDataFlow.cs:256:20:256:41 | access to local variable nonTaintedDataContract | LocalDataFlow.cs:256:20:256:49 | access to property AString |
|
||||
| LocalDataFlow.cs:256:20:256:49 | [library code] access to property AString | LocalDataFlow.cs:256:20:256:49 | access to property AString |
|
||||
| LocalDataFlow.cs:256:20:256:49 | access to property AString | LocalDataFlow.cs:256:9:256:49 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) | LocalDataFlow.cs:259:15:259:22 | access to local variable nonSink2 |
|
||||
| LocalDataFlow.cs:258:20:258:38 | [post] access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:258:20:258:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract |
|
||||
| LocalDataFlow.cs:258:20:258:44 | access to property AnInt | LocalDataFlow.cs:258:9:258:44 | SSA def(nonSink2) |
|
||||
| LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) | LocalDataFlow.cs:261:15:261:22 | access to local variable nonSink2 |
|
||||
| LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:44 | [library code] access to property AList |
|
||||
| LocalDataFlow.cs:260:20:260:38 | access to local variable taintedDataContract | LocalDataFlow.cs:260:20:260:44 | access to property AList |
|
||||
| LocalDataFlow.cs:260:20:260:44 | [library code] access to property AList | LocalDataFlow.cs:260:20:260:44 | access to property AList |
|
||||
| LocalDataFlow.cs:260:20:260:44 | access to property AList | LocalDataFlow.cs:260:20:260:47 | access to indexer |
|
||||
| LocalDataFlow.cs:260:20:260:53 | access to property AnInt | LocalDataFlow.cs:260:9:260:53 | SSA def(nonSink2) |
|
||||
| LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) | LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox |
|
||||
| LocalDataFlow.cs:264:34:264:37 | null | LocalDataFlow.cs:264:17:264:37 | SSA def(taintedTextBox) |
|
||||
| LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) | LocalDataFlow.cs:266:15:266:20 | access to local variable sink60 |
|
||||
| LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | LocalDataFlow.cs:265:22:265:40 | access to property Text |
|
||||
| LocalDataFlow.cs:265:22:265:35 | access to local variable taintedTextBox | LocalDataFlow.cs:265:22:265:40 | [library code] access to property Text |
|
||||
| LocalDataFlow.cs:265:22:265:40 | [library code] access to property Text | LocalDataFlow.cs:265:22:265:40 | access to property Text |
|
||||
| LocalDataFlow.cs:265:22:265:40 | access to property Text | LocalDataFlow.cs:265:13:265:40 | SSA def(sink60) |
|
||||
| LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) | LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox |
|
||||
| LocalDataFlow.cs:269:37:269:40 | null | LocalDataFlow.cs:269:17:269:40 | SSA def(nonTaintedTextBox) |
|
||||
| LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) | LocalDataFlow.cs:271:15:271:22 | access to local variable nonSink0 |
|
||||
| LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:270:20:270:41 | access to property Text |
|
||||
| LocalDataFlow.cs:270:20:270:36 | access to local variable nonTaintedTextBox | LocalDataFlow.cs:270:20:270:41 | [library code] access to property Text |
|
||||
| LocalDataFlow.cs:270:20:270:41 | [library code] access to property Text | LocalDataFlow.cs:270:20:270:41 | access to property Text |
|
||||
| LocalDataFlow.cs:270:20:270:41 | access to property Text | LocalDataFlow.cs:270:9:270:41 | SSA def(nonSink0) |
|
||||
| LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) | LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:274:22:274:51 | [library code] call to method Run | LocalDataFlow.cs:274:22:274:51 | call to method Run |
|
||||
| LocalDataFlow.cs:274:22:274:51 | call to method Run | LocalDataFlow.cs:274:13:274:51 | SSA def(sink67) |
|
||||
| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | call to method Run |
|
||||
| LocalDataFlow.cs:274:31:274:50 | [output] (...) => ... | LocalDataFlow.cs:274:22:274:51 | [library code] call to method Run |
|
||||
| LocalDataFlow.cs:275:15:275:20 | [post] access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:275:15:275:20 | access to local variable sink67 | LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 |
|
||||
| LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) | LocalDataFlow.cs:277:15:277:20 | access to local variable sink68 |
|
||||
| LocalDataFlow.cs:276:22:276:33 | await ... | LocalDataFlow.cs:276:13:276:33 | SSA def(sink68) |
|
||||
| LocalDataFlow.cs:276:28:276:33 | access to local variable sink67 | LocalDataFlow.cs:276:22:276:33 | await ... |
|
||||
| LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) | LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:280:25:280:42 | [library code] call to method Run | LocalDataFlow.cs:280:25:280:42 | call to method Run |
|
||||
| LocalDataFlow.cs:280:25:280:42 | call to method Run | LocalDataFlow.cs:280:13:280:42 | SSA def(nonSink21) |
|
||||
| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | call to method Run |
|
||||
| LocalDataFlow.cs:280:34:280:41 | [output] (...) => ... | LocalDataFlow.cs:280:25:280:42 | [library code] call to method Run |
|
||||
| LocalDataFlow.cs:281:15:281:23 | [post] access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:281:15:281:23 | access to local variable nonSink21 | LocalDataFlow.cs:282:26:282:34 | access to local variable nonSink21 |
|
||||
| LocalDataFlow.cs:282:9:282:34 | SSA def(nonSink0) | LocalDataFlow.cs:283:15:283:22 | access to local variable nonSink0 |
|
||||
@@ -525,28 +629,20 @@
|
||||
| LocalDataFlow.cs:327:31:327:38 | access to local variable nonSink0 | LocalDataFlow.cs:327:22:327:38 | ... ?? ... |
|
||||
| LocalDataFlow.cs:347:28:347:30 | this | LocalDataFlow.cs:347:41:347:45 | this access |
|
||||
| LocalDataFlow.cs:347:50:347:52 | this | LocalDataFlow.cs:347:56:347:60 | this access |
|
||||
| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:50:347:52 | value |
|
||||
| LocalDataFlow.cs:347:50:347:52 | value | LocalDataFlow.cs:347:64:347:68 | access to parameter value |
|
||||
| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:353:41:353:47 | tainted |
|
||||
| LocalDataFlow.cs:353:41:353:47 | tainted | LocalDataFlow.cs:355:15:355:21 | access to parameter tainted |
|
||||
| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:358:44:358:53 | nonTainted |
|
||||
| LocalDataFlow.cs:358:44:358:53 | nonTainted | LocalDataFlow.cs:360:15:360:24 | access to parameter nonTainted |
|
||||
| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:363:44:363:44 | x |
|
||||
| LocalDataFlow.cs:363:44:363:44 | x | LocalDataFlow.cs:366:21:366:21 | access to parameter x |
|
||||
| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:363:67:363:68 | os |
|
||||
| LocalDataFlow.cs:363:67:363:68 | os | LocalDataFlow.cs:369:32:369:33 | access to parameter os |
|
||||
| LocalDataFlow.cs:366:21:366:21 | access to parameter x | LocalDataFlow.cs:366:16:366:21 | ... = ... |
|
||||
| LocalDataFlow.cs:369:32:369:33 | access to parameter os | LocalDataFlow.cs:369:26:369:33 | ... = ... |
|
||||
| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:374:41:374:44 | args |
|
||||
| LocalDataFlow.cs:374:41:374:44 | args | LocalDataFlow.cs:376:29:376:32 | access to parameter args |
|
||||
| LocalDataFlow.cs:376:29:376:32 | [post] access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args |
|
||||
| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:376:29:376:32 | call to operator implicit conversion |
|
||||
| LocalDataFlow.cs:376:29:376:32 | access to parameter args | LocalDataFlow.cs:377:27:377:30 | access to parameter args |
|
||||
| SSA.cs:5:17:5:17 | SSA entry def(this.S) | SSA.cs:67:9:67:14 | access to field S |
|
||||
| SSA.cs:5:17:5:17 | this | SSA.cs:67:9:67:12 | this access |
|
||||
| SSA.cs:5:26:5:32 | tainted | SSA.cs:5:26:5:32 | tainted |
|
||||
| SSA.cs:5:26:5:32 | tainted | SSA.cs:8:24:8:30 | access to parameter tainted |
|
||||
| SSA.cs:5:42:5:51 | nonTainted | SSA.cs:5:42:5:51 | nonTainted |
|
||||
| SSA.cs:5:42:5:51 | nonTainted | SSA.cs:12:24:12:33 | access to parameter nonTainted |
|
||||
| SSA.cs:8:13:8:30 | SSA def(ssaSink0) | SSA.cs:9:15:9:22 | access to local variable ssaSink0 |
|
||||
| SSA.cs:8:24:8:30 | access to parameter tainted | SSA.cs:8:13:8:30 | SSA def(ssaSink0) |
|
||||
@@ -826,7 +922,6 @@
|
||||
| SSA.cs:136:23:136:28 | SSA def(this.S) | SSA.cs:137:15:137:20 | access to field S |
|
||||
| SSA.cs:136:23:136:28 | SSA qualifier def(this.S.SsaFieldNonSink0) | SSA.cs:137:15:137:37 | access to field SsaFieldNonSink0 |
|
||||
| SSA.cs:136:23:136:28 | access to field S | SSA.cs:136:23:136:28 | SSA def(this.S) |
|
||||
| SSA.cs:144:34:144:34 | t | SSA.cs:144:34:144:34 | t |
|
||||
| SSA.cs:144:34:144:34 | t | SSA.cs:146:13:146:13 | access to parameter t |
|
||||
| SSA.cs:146:13:146:13 | (...) ... | SSA.cs:146:13:146:21 | ... == ... |
|
||||
| SSA.cs:146:13:146:13 | access to parameter t | SSA.cs:146:13:146:13 | (...) ... |
|
||||
@@ -835,7 +930,6 @@
|
||||
| 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:149:13:149:17 | SSA def(t) |
|
||||
| SSA.cs:152:36:152:36 | t | SSA.cs:152:36:152:36 | 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 | ... == ... |
|
||||
| SSA.cs:154:13:154:13 | access to parameter t | SSA.cs:152:17:152:28 | SSA phi(t) |
|
||||
@@ -844,9 +938,7 @@
|
||||
| SSA.cs:155:25:155:25 | SSA def(t) | SSA.cs:152:17:152:28 | SSA phi(t) |
|
||||
| SSA.cs:155:25:155:25 | access to parameter t | SSA.cs:152:17:152:28 | SSA phi(t) |
|
||||
| SSA.cs:166:10:166:13 | this | SSA.cs:166:19:166:22 | this access |
|
||||
| SSA.cs:168:22:168:28 | tainted | SSA.cs:168:22:168:28 | tainted |
|
||||
| SSA.cs:168:22:168:28 | tainted | SSA.cs:173:24:173:30 | access to parameter tainted |
|
||||
| SSA.cs:168:35:168:35 | i | SSA.cs:168:35:168:35 | i |
|
||||
| SSA.cs:168:35:168:35 | i | SSA.cs:171:13:171:13 | access to parameter i |
|
||||
| SSA.cs:170:16:170:28 | SSA def(ssaSink5) | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
|
||||
| SSA.cs:170:27:170:28 | "" | SSA.cs:170:16:170:28 | SSA def(ssaSink5) |
|
||||
@@ -863,9 +955,7 @@
|
||||
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:176:21:176:28 | access to local variable ssaSink5 |
|
||||
| SSA.cs:177:21:177:28 | access to local variable ssaSink5 | SSA.cs:180:9:180:24 | SSA phi(ssaSink5) |
|
||||
| SSA.cs:180:9:180:24 | SSA phi(ssaSink5) | SSA.cs:180:15:180:22 | access to local variable ssaSink5 |
|
||||
| Splitting.cs:3:18:3:18 | b | Splitting.cs:3:18:3:18 | b |
|
||||
| Splitting.cs:3:18:3:18 | b | Splitting.cs:6:13:6:13 | access to parameter b |
|
||||
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:3:28:3:34 | tainted |
|
||||
| Splitting.cs:3:28:3:34 | tainted | Splitting.cs:5:17:5:23 | access to parameter tainted |
|
||||
| Splitting.cs:5:13:5:23 | SSA def(x) | Splitting.cs:8:19:8:19 | [b (line 3): true] access to local variable x |
|
||||
| Splitting.cs:5:13:5:23 | SSA def(x) | Splitting.cs:12:15:12:15 | [b (line 3): false] access to local variable x |
|
||||
@@ -878,7 +968,6 @@
|
||||
| Splitting.cs:9:17:9:17 | [b (line 3): true] access to local variable x | Splitting.cs:12:15:12:15 | [b (line 3): true] access to local variable x |
|
||||
| Splitting.cs:12:15:12:15 | [b (line 3): true] access to local variable x | Splitting.cs:14:19:14:19 | access to local variable x |
|
||||
| Splitting.cs:12:15:12:15 | [post] [b (line 3): true] access to local variable x | Splitting.cs:14:19:14:19 | access to local variable x |
|
||||
| Splitting.cs:17:18:17:18 | b | Splitting.cs:17:18:17:18 | b |
|
||||
| Splitting.cs:17:18:17:18 | b | Splitting.cs:20:13:20:13 | access to parameter b |
|
||||
| Splitting.cs:19:13:19:18 | SSA def(x) | Splitting.cs:22:19:22:19 | [b (line 17): true] access to local variable x |
|
||||
| Splitting.cs:19:13:19:18 | SSA def(x) | Splitting.cs:25:15:25:15 | [b (line 17): false] access to local variable x |
|
||||
@@ -891,7 +980,6 @@
|
||||
| Splitting.cs:25:15:25:15 | [b (line 17): true] access to local variable x | Splitting.cs:27:19:27:19 | access to local variable x |
|
||||
| Splitting.cs:25:15:25:15 | [post] [b (line 17): false] access to local variable x | Splitting.cs:29:19:29:19 | access to local variable x |
|
||||
| Splitting.cs:25:15:25:15 | [post] [b (line 17): true] access to local variable x | Splitting.cs:27:19:27:19 | access to local variable x |
|
||||
| Splitting.cs:32:18:32:18 | b | Splitting.cs:32:18:32:18 | b |
|
||||
| Splitting.cs:32:18:32:18 | b | Splitting.cs:35:13:35:13 | access to parameter b |
|
||||
| Splitting.cs:35:13:35:13 | access to parameter b | Splitting.cs:39:15:39:15 | [b (line 32): false] access to parameter b |
|
||||
| Splitting.cs:35:13:35:13 | access to parameter b | Splitting.cs:39:15:39:15 | [b (line 32): true] access to parameter b |
|
||||
@@ -912,7 +1000,6 @@
|
||||
| Splitting.cs:40:23:40:23 | [b (line 32): true] access to local variable x | Splitting.cs:40:15:40:23 | [b (line 32): true] (...) ... |
|
||||
| Splitting.cs:41:19:41:21 | [b (line 32): false] "d" | Splitting.cs:41:15:41:21 | [b (line 32): false] ... = ... |
|
||||
| Splitting.cs:41:19:41:21 | [b (line 32): true] "d" | Splitting.cs:41:15:41:21 | [b (line 32): true] ... = ... |
|
||||
| Splitting.cs:46:18:46:18 | b | Splitting.cs:46:18:46:18 | b |
|
||||
| Splitting.cs:46:18:46:18 | b | Splitting.cs:49:13:49:13 | access to parameter b |
|
||||
| Splitting.cs:48:13:48:18 | SSA def(x) | Splitting.cs:53:13:53:13 | [b (line 46): false] access to local variable x |
|
||||
| Splitting.cs:48:17:48:18 | "" | Splitting.cs:48:13:48:18 | SSA def(x) |
|
||||
|
||||
@@ -114,6 +114,18 @@ class Types
|
||||
{
|
||||
Sink(this.Field);
|
||||
}
|
||||
|
||||
void M10()
|
||||
{
|
||||
var a = new A();
|
||||
var e2 = new E2();
|
||||
Sink(Through(a)); // flow
|
||||
Sink(Through(e2)); // flow
|
||||
Sink((E2)Through(a)); // no flow
|
||||
Sink((A)Through(e2)); // no flow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static object Through(object x) => x;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,10 @@ edges
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:90:22:90:22 | e : E2 |
|
||||
| Types.cs:113:34:113:34 | this [Field] : E2 | Types.cs:115:22:115:25 | this access [Field] : E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : E2 | Types.cs:115:22:115:31 | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:30:122:30 | access to local variable a : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:30:123:31 | access to local variable e2 : E2 |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | Types.cs:122:22:122:31 | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | Types.cs:123:22:123:32 | call to method Through |
|
||||
nodes
|
||||
| Types.cs:7:21:7:25 | this : D | semmle.label | this : D |
|
||||
| Types.cs:7:32:7:35 | this access : D | semmle.label | this access : D |
|
||||
@@ -90,6 +94,12 @@ nodes
|
||||
| Types.cs:113:34:113:34 | this [Field] : E2 | semmle.label | this [Field] : E2 |
|
||||
| Types.cs:115:22:115:25 | this access [Field] : E2 | semmle.label | this access [Field] : E2 |
|
||||
| Types.cs:115:22:115:31 | access to field Field | semmle.label | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | semmle.label | object creation of type A : A |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | semmle.label | object creation of type E2 : E2 |
|
||||
| Types.cs:122:22:122:31 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:122:30:122:30 | access to local variable a : A | semmle.label | access to local variable a : A |
|
||||
| Types.cs:123:22:123:32 | call to method Through | semmle.label | call to method Through |
|
||||
| Types.cs:123:30:123:31 | access to local variable e2 : E2 | semmle.label | access to local variable e2 : E2 |
|
||||
#select
|
||||
| Types.cs:23:12:23:18 | object creation of type C : C | Types.cs:50:18:50:18 | access to local variable c | Types.cs:50:18:50:18 | access to local variable c | $@ | Types.cs:50:18:50:18 | access to local variable c | access to local variable c |
|
||||
| Types.cs:25:12:25:18 | object creation of type C : C | Types.cs:63:33:63:36 | (...) ... | Types.cs:63:33:63:36 | (...) ... | $@ | Types.cs:63:33:63:36 | (...) ... | (...) ... |
|
||||
@@ -106,3 +116,5 @@ nodes
|
||||
| Types.cs:40:12:40:18 | object creation of type D : D | Types.cs:16:42:16:45 | this access | Types.cs:16:42:16:45 | this access | $@ | Types.cs:16:42:16:45 | this access | this access |
|
||||
| Types.cs:43:20:43:23 | null : null | Types.cs:44:14:44:14 | access to local variable o | Types.cs:44:14:44:14 | access to local variable o | $@ | Types.cs:44:14:44:14 | access to local variable o | access to local variable o |
|
||||
| Types.cs:110:25:110:32 | object creation of type E2 : E2 | Types.cs:115:22:115:31 | access to field Field | Types.cs:115:22:115:31 | access to field Field | $@ | Types.cs:115:22:115:31 | access to field Field | access to field Field |
|
||||
| Types.cs:120:25:120:31 | object creation of type A : A | Types.cs:122:22:122:31 | call to method Through | Types.cs:122:22:122:31 | call to method Through | $@ | Types.cs:122:22:122:31 | call to method Through | call to method Through |
|
||||
| Types.cs:121:26:121:33 | object creation of type E2 : E2 | Types.cs:123:22:123:32 | call to method Through | Types.cs:123:22:123:32 | call to method Through | $@ | Types.cs:123:22:123:32 | call to method Through | call to method Through |
|
||||
|
||||
178
csharp/ql/test/library-tests/generics/Generics.expected
Normal file
178
csharp/ql/test/library-tests/generics/Generics.expected
Normal file
@@ -0,0 +1,178 @@
|
||||
test1
|
||||
| generics.cs:7:23:7:40 | GenericDelegate<> |
|
||||
test2
|
||||
| generics.cs:9:18:9:18 | A |
|
||||
test3
|
||||
| generics.cs:13:18:13:21 | A<X> | generics.cs:13:18:13:21 | A<> |
|
||||
test4
|
||||
test5
|
||||
test6
|
||||
| generics.cs:13:18:13:21 | A<T> | generics.cs:22:18:22:21 | B<> | generics.cs:22:18:22:21 | B<X> | generics.cs:25:23:25:24 | at |
|
||||
test7
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:6:18:6:22 | B<String> |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | generics.cs:22:18:22:21 | B<String> |
|
||||
| generics.cs:13:18:13:21 | A<String> | Nesting.cs:6:18:6:22 | B<String> |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:22:18:22:21 | B<String> |
|
||||
test8
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:31:21:31:29 | fooParams |
|
||||
test9
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:35:51:35:53 | set_Name | generics.cs:35:51:35:53 | set_Name |
|
||||
test10
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:37:41:37:47 | myEvent |
|
||||
test11
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:39:37:39:38 | ++ |
|
||||
test12
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:73:18:73:21 | Item |
|
||||
test13
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:68:20:68:23 | Item |
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:73:18:73:21 | Item |
|
||||
test14
|
||||
| generics.cs:60:18:60:24 | Grid<> | generics.cs:68:20:68:23 | Item |
|
||||
test15
|
||||
| generics.cs:7:23:7:40 | GenericDelegate<String> |
|
||||
test16
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:137:21:137:25 | fs |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:139:21:139:25 | fs |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:141:21:141:22 | fs |
|
||||
test17
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:137:24:137:24 | X | generics.cs:137:21:137:25 | fs | generics.cs:139:24:139:24 | X | generics.cs:139:21:139:25 | fs | 1 |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:139:24:139:24 | X | generics.cs:139:21:139:25 | fs | generics.cs:137:24:137:24 | X | generics.cs:137:21:137:25 | fs | 2 |
|
||||
test18
|
||||
| Nesting.cs:1:14:1:18 | A<> | Nesting.cs:3:17:3:19 | MA1 | Nesting.cs:3:24:3:24 | x | 0 | T1 | 1 | 1 |
|
||||
| Nesting.cs:1:14:1:18 | A<> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:28:4:28 | x | 0 | T1 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:34:4:34 | y | 0 | T2 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<Int32> | Nesting.cs:3:17:3:19 | MA1 | Nesting.cs:3:24:3:24 | x | 0 | Int32 | 1 | 1 |
|
||||
| Nesting.cs:1:14:1:18 | A<Int32> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:28:4:28 | x | 0 | Int32 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<Int32> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:28:4:28 | x | 1 | Int32 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<Int32> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:34:4:34 | y | 0 | T2 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<Int32> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:34:4:34 | y | 1 | String | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:3:17:3:19 | MA1 | Nesting.cs:3:24:3:24 | x | 0 | String | 1 | 1 |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:28:4:28 | x | 0 | String | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:28:4:28 | x | 1 | String | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:34:4:34 | y | 0 | T2 | 2 | 2 |
|
||||
| Nesting.cs:1:14:1:18 | A<String> | Nesting.cs:4:17:4:23 | MA2 | Nesting.cs:4:34:4:34 | y | 1 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | T | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 1 | Test | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 1 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 1 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | String | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 1 | String | 2 | 2 |
|
||||
test19
|
||||
| generics.cs:137:21:137:25 | fs | generics.cs:137:24:137:24 | X | 1 |
|
||||
| generics.cs:139:21:139:25 | fs | generics.cs:139:24:139:24 | X | 1 |
|
||||
test20
|
||||
test21
|
||||
| generics.cs:147:14:147:14 | E | generics.cs:145:11:145:18 | Param<> |
|
||||
test22
|
||||
| generics.cs:152:14:152:19 | CM1 | Double |
|
||||
| generics.cs:152:14:152:19 | CM1 | Int32 |
|
||||
| generics.cs:153:11:153:16 | CM2 | Double |
|
||||
| generics.cs:153:11:153:16 | CM2 | Int32 |
|
||||
| generics.cs:157:23:157:29 | CM3 | Double |
|
||||
| generics.cs:157:23:157:29 | CM3 | Double |
|
||||
test23
|
||||
| generics.cs:178:11:178:24 | Inheritance<> | generics.cs:173:15:173:26 | Interface<T> |
|
||||
| generics.cs:178:11:178:24 | Inheritance<Int32> | generics.cs:173:15:173:26 | Interface<Int32> |
|
||||
test24
|
||||
| generics.cs:188:15:188:39 | Interface2<,> | generics.cs:188:29:188:30 | T1 | in |
|
||||
| generics.cs:188:15:188:39 | Interface2<,> | generics.cs:188:37:188:38 | T2 | out |
|
||||
test25
|
||||
| generics.cs:157:23:157:29 | CM3 |
|
||||
test26
|
||||
test27
|
||||
| Nesting.cs:6:18:6:22 | B<Int32> | Nesting.cs:6:18:6:22 | B<> | Nesting.cs:6:18:6:22 | B<> |
|
||||
| Nesting.cs:6:18:6:22 | B<String> | Nesting.cs:6:18:6:22 | B<> | Nesting.cs:6:18:6:22 | B<> |
|
||||
| Nesting.cs:17:22:17:26 | D<Boolean> | Nesting.cs:17:22:17:26 | D<> | Nesting.cs:17:22:17:26 | D<> |
|
||||
| Nesting.cs:17:22:17:26 | D<Decimal> | Nesting.cs:17:22:17:26 | D<> | Nesting.cs:17:22:17:26 | D<> |
|
||||
| generics.cs:51:22:51:29 | Inner<String> | generics.cs:51:22:51:29 | Inner<> | generics.cs:51:22:51:29 | Inner<> |
|
||||
test28
|
||||
| Nesting.cs:4:17:4:23 | MA2 | A<>.MA2<T2>(T1, T2) |
|
||||
| Nesting.cs:4:17:4:23 | MA2 | A<Int32>.MA2<T2>(int, T2) |
|
||||
| Nesting.cs:4:17:4:23 | MA2 | A<String>.MA2<T2>(string, T2) |
|
||||
| Nesting.cs:6:18:6:22 | B<> | A<>.B<T3> |
|
||||
| Nesting.cs:6:18:6:22 | B<> | A<Int32>.B<T3> |
|
||||
| Nesting.cs:6:18:6:22 | B<> | A<String>.B<T3> |
|
||||
| Nesting.cs:9:21:9:27 | MB2 | A<>.B<>.MB2<T4>(T1, T3, T4) |
|
||||
| Nesting.cs:9:21:9:27 | MB2 | A<Int32>.B<String>.MB2<T4>(int, string, T4) |
|
||||
| Nesting.cs:9:21:9:27 | MB2 | A<String>.B<Int32>.MB2<T4>(string, int, T4) |
|
||||
| Nesting.cs:15:21:15:27 | MC2 | A<>.C.MC2<T5>(T1, T5) |
|
||||
| Nesting.cs:15:21:15:27 | MC2 | A<Int32>.C.MC2<T5>(int, T5) |
|
||||
| Nesting.cs:15:21:15:27 | MC2 | A<String>.C.MC2<T5>(string, T5) |
|
||||
| Nesting.cs:17:22:17:26 | D<> | A<>.C.D<T6> |
|
||||
| Nesting.cs:17:22:17:26 | D<> | A<Int32>.C.D<T6> |
|
||||
| Nesting.cs:17:22:17:26 | D<> | A<String>.C.D<T6> |
|
||||
| Nesting.cs:20:25:20:31 | MD2 | A<>.C.D<>.MD2<T7>(T1, T6, T7) |
|
||||
| Nesting.cs:20:25:20:31 | MD2 | A<Int32>.C.D<Boolean>.MD2<T7>(int, bool, T7) |
|
||||
| Nesting.cs:20:25:20:31 | MD2 | A<String>.C.D<Decimal>.MD2<T7>(string, decimal, T7) |
|
||||
| generics.cs:16:27:16:58 | GenericDelegateInGenericClass<> | generics.A<>.GenericDelegateInGenericClass<U>(T, U) |
|
||||
| generics.cs:16:27:16:58 | GenericDelegateInGenericClass<> | generics.A<Int32>.GenericDelegateInGenericClass<U>(int, U) |
|
||||
| generics.cs:16:27:16:58 | GenericDelegateInGenericClass<> | generics.A<String>.GenericDelegateInGenericClass<U>(string, U) |
|
||||
| generics.cs:18:18:18:23 | bar | generics.A<>.bar<X>(X, T) |
|
||||
| generics.cs:18:18:18:23 | bar | generics.A<Int32>.bar<X>(X, int) |
|
||||
| generics.cs:18:18:18:23 | bar | generics.A<String>.bar<X>(X, string) |
|
||||
| generics.cs:45:14:45:17 | f | generics.B<>.f<X>() |
|
||||
| generics.cs:45:14:45:17 | f | generics.B<Object>.f<X>() |
|
||||
| generics.cs:45:14:45:17 | f | generics.B<String>.f<X>() |
|
||||
| generics.cs:45:14:45:17 | f | generics.B<X>.f<X>() |
|
||||
| generics.cs:51:22:51:29 | Inner<> | generics.Outer<>.Inner<U> |
|
||||
| generics.cs:51:22:51:29 | Inner<> | generics.Outer<Object>.Inner<U> |
|
||||
| generics.cs:137:21:137:25 | fs | generics.Subtle.fs<X>(int) |
|
||||
| generics.cs:139:21:139:25 | fs | generics.Subtle.fs<X>(int, int) |
|
||||
| generics.cs:152:14:152:19 | CM1 | generics.ConstructedMethods.CM1<T>() |
|
||||
| generics.cs:153:11:153:16 | CM2 | generics.ConstructedMethods.CM2<T>(T) |
|
||||
| generics.cs:155:15:155:23 | Class<> | generics.ConstructedMethods.Class<T1> |
|
||||
| generics.cs:157:23:157:29 | CM3 | generics.ConstructedMethods.Class<>.CM3<T2>(T2, T1) |
|
||||
| generics.cs:157:23:157:29 | CM3 | generics.ConstructedMethods.Class<Double>.CM3<T2>(T2, double) |
|
||||
| generics.cs:157:23:157:29 | CM3 | generics.ConstructedMethods.Class<Int32>.CM3<T2>(T2, int) |
|
||||
test29
|
||||
| Nesting.cs:4:17:4:23 | MA2 | A<Int32>.MA2<string>(int, string) |
|
||||
| Nesting.cs:4:17:4:23 | MA2 | A<String>.MA2<int>(string, int) |
|
||||
| Nesting.cs:6:18:6:22 | B<Int32> | A<String>.B<Int32> |
|
||||
| Nesting.cs:6:18:6:22 | B<String> | A<Int32>.B<String> |
|
||||
| Nesting.cs:9:21:9:27 | MB2 | A<Int32>.B<String>.MB2<bool>(int, string, bool) |
|
||||
| Nesting.cs:9:21:9:27 | MB2 | A<String>.B<Int32>.MB2<bool>(string, int, bool) |
|
||||
| Nesting.cs:15:21:15:27 | MC2 | A<Int32>.C.MC2<bool>(int, bool) |
|
||||
| Nesting.cs:15:21:15:27 | MC2 | A<String>.C.MC2<bool>(string, bool) |
|
||||
| Nesting.cs:17:22:17:26 | D<Boolean> | A<Int32>.C.D<Boolean> |
|
||||
| Nesting.cs:17:22:17:26 | D<Decimal> | A<String>.C.D<Decimal> |
|
||||
| Nesting.cs:20:25:20:31 | MD2 | A<Int32>.C.D<Boolean>.MD2<string>(int, bool, string) |
|
||||
| Nesting.cs:20:25:20:31 | MD2 | A<String>.C.D<Decimal>.MD2<bool>(string, decimal, bool) |
|
||||
| generics.cs:18:18:18:23 | bar | generics.A<Int32>.bar<Test>(Test, int) |
|
||||
| generics.cs:18:18:18:23 | bar | generics.A<String>.bar<int>(int, string) |
|
||||
| generics.cs:51:22:51:29 | Inner<String> | generics.Outer<Object>.Inner<String> |
|
||||
| generics.cs:152:14:152:19 | CM1 | generics.ConstructedMethods.CM1<double>() |
|
||||
| generics.cs:152:14:152:19 | CM1 | generics.ConstructedMethods.CM1<int>() |
|
||||
| generics.cs:153:11:153:16 | CM2 | generics.ConstructedMethods.CM2<double>(double) |
|
||||
| generics.cs:153:11:153:16 | CM2 | generics.ConstructedMethods.CM2<int>(int) |
|
||||
| generics.cs:155:15:155:23 | Class<Double> | generics.ConstructedMethods.Class<Double> |
|
||||
| generics.cs:155:15:155:23 | Class<Int32> | generics.ConstructedMethods.Class<Int32> |
|
||||
| generics.cs:157:23:157:29 | CM3 | generics.ConstructedMethods.Class<Double>.CM3<double>(double, double) |
|
||||
| generics.cs:157:23:157:29 | CM3 | generics.ConstructedMethods.Class<Int32>.CM3<double>(double, int) |
|
||||
test30
|
||||
| Nesting.cs:3:17:3:19 | MA1 | A<Int32>.MA1(int) |
|
||||
| Nesting.cs:3:17:3:19 | MA1 | A<String>.MA1(string) |
|
||||
| Nesting.cs:8:21:8:23 | MB1 | A<Int32>.B<String>.MB1(int, string) |
|
||||
| Nesting.cs:8:21:8:23 | MB1 | A<String>.B<Int32>.MB1(string, int) |
|
||||
| Nesting.cs:12:18:12:18 | C | A<Int32>.C |
|
||||
| Nesting.cs:12:18:12:18 | C | A<String>.C |
|
||||
| Nesting.cs:14:21:14:23 | MC1 | A<Int32>.C.MC1(int) |
|
||||
| Nesting.cs:14:21:14:23 | MC1 | A<String>.C.MC1(string) |
|
||||
| Nesting.cs:19:25:19:27 | MD1 | A<Int32>.C.D<Boolean>.MD1(int, bool) |
|
||||
| Nesting.cs:19:25:19:27 | MD1 | A<String>.C.D<Decimal>.MD1(string, decimal) |
|
||||
| Nesting.cs:24:10:24:18 | Construct | A<Int32>.Construct() |
|
||||
| Nesting.cs:24:10:24:18 | Construct | A<String>.Construct() |
|
||||
| generics.cs:29:21:29:23 | foo | generics.B<Object>.foo() |
|
||||
| generics.cs:29:21:29:23 | foo | generics.B<String>.foo() |
|
||||
| generics.cs:29:21:29:23 | foo | generics.B<X>.foo() |
|
||||
| generics.cs:31:21:31:29 | fooParams | generics.B<Object>.fooParams(params Object[]) |
|
||||
| generics.cs:31:21:31:29 | fooParams | generics.B<String>.fooParams(params String[]) |
|
||||
| generics.cs:31:21:31:29 | fooParams | generics.B<X>.fooParams(params X[]) |
|
||||
| generics.cs:33:28:33:36 | staticFoo | generics.B<Object>.staticFoo() |
|
||||
| generics.cs:33:28:33:36 | staticFoo | generics.B<String>.staticFoo() |
|
||||
| generics.cs:33:28:33:36 | staticFoo | generics.B<X>.staticFoo() |
|
||||
| generics.cs:175:14:175:16 | set | generics.Interface<T>.set(T) |
|
||||
test31
|
||||
252
csharp/ql/test/library-tests/generics/Generics.ql
Normal file
252
csharp/ql/test/library-tests/generics/Generics.ql
Normal file
@@ -0,0 +1,252 @@
|
||||
import csharp
|
||||
|
||||
query predicate test1(UnboundGenericDelegateType d) {
|
||||
d.hasName("GenericDelegate<>") and
|
||||
d.getTypeParameter(0).hasName("T") and
|
||||
d.getParameter(0).getType().hasName("T")
|
||||
}
|
||||
|
||||
query predicate test2(Class c) {
|
||||
c.hasName("A") and
|
||||
not c instanceof UnboundGenericClass
|
||||
}
|
||||
|
||||
query predicate test3(ConstructedClass c, UnboundGenericClass d) {
|
||||
d.hasName("A<>") and
|
||||
c.getTypeArgument(0).hasName("X") and
|
||||
c.getTypeArgument(0) instanceof TypeParameter and
|
||||
c.getUnboundGeneric() = d
|
||||
}
|
||||
|
||||
query predicate test4(UnboundGenericClass c, string s) {
|
||||
c.fromSource() and
|
||||
not c.getName().matches("%<%>") and
|
||||
s = "Unbound generic class with inconsistent name"
|
||||
}
|
||||
|
||||
query predicate test5(ConstructedClass c, string s) {
|
||||
c.fromSource() and
|
||||
not c.getName().matches("%<%>") and
|
||||
s = "Constructed class with inconsistent name"
|
||||
}
|
||||
|
||||
query predicate test6(ConstructedClass at, UnboundGenericClass b, ConstructedClass bt, Field f) {
|
||||
at.hasName("A<T>") and
|
||||
b.hasName("B<>") and
|
||||
bt.hasName("B<X>") and
|
||||
at.getTypeArgument(0).hasName("T") and
|
||||
at.getTypeArgument(0) instanceof TypeParameter and
|
||||
at.getTypeArgument(0) = b.getTypeParameter(0) and
|
||||
bt.getUnboundGeneric() = b and
|
||||
f.getDeclaringType() = b and
|
||||
f.getType() = at
|
||||
}
|
||||
|
||||
query predicate test7(ConstructedClass aString, ConstructedClass bString) {
|
||||
aString.hasName("A<String>") and
|
||||
bString.hasName("B<String>") and
|
||||
aString.getSourceDeclaration().hasName("A<>") and
|
||||
bString.getSourceDeclaration().hasName("B<>")
|
||||
}
|
||||
|
||||
query predicate test8(ConstructedClass bString, Method m) {
|
||||
bString.hasName("B<String>") and
|
||||
m.getDeclaringType() = bString and
|
||||
m.hasName("fooParams") and
|
||||
m.getParameter(0).getType().(ArrayType).getElementType() instanceof StringType and
|
||||
m.getSourceDeclaration().getDeclaringType() = m.getDeclaringType().getSourceDeclaration()
|
||||
}
|
||||
|
||||
query predicate test9(ConstructedClass bString, Setter sourceSetter, Setter setter) {
|
||||
exists(Property p |
|
||||
bString.hasName("B<String>") and
|
||||
p.getDeclaringType() = bString and
|
||||
p.hasName("Name") and
|
||||
p.getSourceDeclaration().getDeclaringType() = p.getDeclaringType().getSourceDeclaration() and
|
||||
p.getSetter().getParameter(0).getType() instanceof StringType and
|
||||
p.getSetter().getSourceDeclaration() = p.getSourceDeclaration().getSetter() and
|
||||
p.getGetter().getSourceDeclaration() = p.getSourceDeclaration().getGetter() and
|
||||
sourceSetter = p.getSourceDeclaration().getSetter() and
|
||||
setter = p.getSetter()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate test10(ConstructedClass bString, Event e) {
|
||||
bString.hasName("B<String>") and
|
||||
e.getDeclaringType() = bString and
|
||||
e.hasName("myEvent") and
|
||||
e.getSourceDeclaration().getDeclaringType() = e.getDeclaringType().getSourceDeclaration() and
|
||||
e.getType().(ConstructedDelegateType).getTypeArgument(0) instanceof StringType and
|
||||
e.getAddEventAccessor().getSourceDeclaration() = e.getSourceDeclaration().getAddEventAccessor() and
|
||||
e.getRemoveEventAccessor().getSourceDeclaration() =
|
||||
e.getSourceDeclaration().getRemoveEventAccessor()
|
||||
}
|
||||
|
||||
query predicate test11(ConstructedClass bString, Operator o) {
|
||||
bString.hasName("B<String>") and
|
||||
o.getDeclaringType() = bString and
|
||||
o instanceof IncrementOperator and
|
||||
o.getSourceDeclaration().getDeclaringType() = o.getDeclaringType().getSourceDeclaration()
|
||||
}
|
||||
|
||||
query predicate test12(ConstructedClass gridInt, Indexer i) {
|
||||
gridInt.hasName("Grid<Int32>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getSourceDeclaration().getDeclaringType() = i.getDeclaringType().getSourceDeclaration() and
|
||||
i.getGetter().getSourceDeclaration() = i.getSourceDeclaration().getGetter() and
|
||||
i.getSetter().getSourceDeclaration() = i.getSourceDeclaration().getSetter()
|
||||
}
|
||||
|
||||
query predicate test13(ConstructedClass gridInt, Indexer i) {
|
||||
gridInt.hasName("Grid<Int32>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getType() instanceof IntType
|
||||
}
|
||||
|
||||
query predicate test14(UnboundGenericClass gridInt, Indexer i) {
|
||||
gridInt.hasName("Grid<>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getType() instanceof IntType
|
||||
}
|
||||
|
||||
query predicate test15(ConstructedDelegateType d) {
|
||||
d.hasName("GenericDelegate<String>") and
|
||||
d.getTypeArgument(0) instanceof StringType and
|
||||
d.getParameter(0).getType() instanceof StringType
|
||||
}
|
||||
|
||||
query predicate test16(Class c, Method m) {
|
||||
c.hasName("Subtle") and
|
||||
count(c.getAMethod()) = 3 and
|
||||
m = c.getAMethod()
|
||||
}
|
||||
|
||||
query predicate test17(
|
||||
Class c, TypeParameter p, UnboundGenericMethod m, TypeParameter q, UnboundGenericMethod n,
|
||||
int numParams
|
||||
) {
|
||||
c.hasName("Subtle") and
|
||||
m = c.getAMethod() and
|
||||
m.getATypeParameter() = p and
|
||||
n = c.getAMethod() and
|
||||
n.getATypeParameter() = q and
|
||||
m != n and
|
||||
p != q and
|
||||
numParams = m.getNumberOfParameters()
|
||||
}
|
||||
|
||||
query predicate test18(
|
||||
Class c, Method m, Parameter p, int numArgs, string typeName, int numParams, int numTypes
|
||||
) {
|
||||
c.getName().matches("A<%") and
|
||||
m = c.getAMethod() and
|
||||
p = m.getAParameter() and
|
||||
numArgs = count(m.(ConstructedMethod).getATypeArgument()) and
|
||||
typeName = p.getType().getName() and
|
||||
numParams = count(m.getAParameter()) and
|
||||
numTypes = count(m.getAParameter().getType())
|
||||
}
|
||||
|
||||
/** Test that locations are populated for the type parameters of generic methods. */
|
||||
query predicate test19(UnboundGenericMethod m, TypeParameter tp, int hasLoc) {
|
||||
m.hasName("fs") and
|
||||
tp = m.getATypeParameter() and
|
||||
if exists(tp.getLocation()) then hasLoc = 1 else hasLoc = 0
|
||||
}
|
||||
|
||||
/** Test that locations are populated for unbound generic types. */
|
||||
query predicate test20(UnboundGenericType t, string s) {
|
||||
not type_location(t, _) and s = "Missing location"
|
||||
}
|
||||
|
||||
/**
|
||||
* This tests a regression in the extractor where the following failed to extract:
|
||||
*
|
||||
* class Foo<T>
|
||||
* {
|
||||
* enum E { a };
|
||||
* }
|
||||
*/
|
||||
query predicate test21(Enum e, Class c) {
|
||||
c.hasName("Param<>") and
|
||||
e.hasName("E") and
|
||||
e.getDeclaringType() = c
|
||||
}
|
||||
|
||||
query predicate test22(ConstructedMethod m, string tpName) {
|
||||
m.getName().matches("CM%") and
|
||||
tpName = m.getATypeArgument().getName()
|
||||
}
|
||||
|
||||
query predicate test23(Class c, Interface i) {
|
||||
c.getName().matches("Inheritance%") and
|
||||
i = c.getABaseInterface()
|
||||
}
|
||||
|
||||
query predicate test24(UnboundGenericInterface ugi, TypeParameter tp, string s) {
|
||||
ugi.fromSource() and
|
||||
ugi.getATypeParameter() = tp and
|
||||
(
|
||||
tp.isOut() and s = "out"
|
||||
or
|
||||
tp.isIn() and s = "in"
|
||||
)
|
||||
}
|
||||
|
||||
query predicate test25(ConstructedMethod cm) {
|
||||
cm.hasName("CM3") and
|
||||
cm.getParameter(0).getType() instanceof DoubleType and
|
||||
cm.getParameter(1).getType() instanceof IntType and
|
||||
cm.getReturnType() instanceof DoubleType and
|
||||
exists(Method sourceDeclaration |
|
||||
sourceDeclaration = cm.getSourceDeclaration() and
|
||||
sourceDeclaration.getParameter(0).getType().(TypeParameter).hasName("T2") and
|
||||
sourceDeclaration.getParameter(1).getType().(TypeParameter).hasName("T1") and
|
||||
sourceDeclaration.getReturnType().(TypeParameter).hasName("T2")
|
||||
) and
|
||||
exists(Method unbound |
|
||||
unbound = cm.getUnboundGeneric() and
|
||||
unbound.getParameter(0).getType().(TypeParameter).hasName("T2") and
|
||||
unbound.getParameter(1).getType() instanceof IntType and
|
||||
unbound.getReturnType().(TypeParameter).hasName("T2")
|
||||
)
|
||||
}
|
||||
|
||||
query predicate test26(ConstructedGeneric cg, string s) {
|
||||
// Source declaration and unbound generic must be unique
|
||||
(
|
||||
strictcount(cg.getSourceDeclaration+()) > 1 or
|
||||
strictcount(cg.getUnboundGeneric()) > 1
|
||||
) and
|
||||
s = "Non-unique source decl or unbound generic"
|
||||
}
|
||||
|
||||
query predicate test27(ConstructedType ct, UnboundGenericType ugt, UnboundGenericType sourceDecl) {
|
||||
ct instanceof NestedType and
|
||||
ugt = ct.getUnboundGeneric() and
|
||||
sourceDecl = ct.getSourceDeclaration() and
|
||||
ugt != sourceDecl
|
||||
}
|
||||
|
||||
query predicate test28(UnboundGeneric ug, string s) {
|
||||
ug.fromSource() and
|
||||
s = ug.getQualifiedNameWithTypes()
|
||||
}
|
||||
|
||||
query predicate test29(ConstructedGeneric cg, string s) {
|
||||
cg.fromSource() and
|
||||
s = cg.getQualifiedNameWithTypes()
|
||||
}
|
||||
|
||||
query predicate test30(Declaration d, string s) {
|
||||
d.fromSource() and
|
||||
d instanceof @generic and
|
||||
s = d.getQualifiedNameWithTypes() and
|
||||
d != d.getSourceDeclaration() and
|
||||
not d instanceof Generic
|
||||
}
|
||||
|
||||
query predicate test31(ConstructedGeneric cg, string s) {
|
||||
not exists(cg.getUnboundGeneric()) and
|
||||
s = "Missing unbound generic"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:7:23:7:40 | GenericDelegate<> |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from UnboundGenericDelegateType d
|
||||
where
|
||||
d.hasName("GenericDelegate<>") and
|
||||
d.getTypeParameter(0).hasName("T") and
|
||||
d.getParameter(0).getType().hasName("T")
|
||||
select d
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:37:41:37:47 | myEvent |
|
||||
@@ -1,17 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ConstructedClass bString, Event e
|
||||
where
|
||||
bString.hasName("B<String>") and
|
||||
e.getDeclaringType() = bString and
|
||||
e.hasName("myEvent") and
|
||||
e.getSourceDeclaration().getDeclaringType() = e.getDeclaringType().getSourceDeclaration() and
|
||||
e.getType().(ConstructedDelegateType).getTypeArgument(0) instanceof StringType and
|
||||
e.getAddEventAccessor().getSourceDeclaration() = e.getSourceDeclaration().getAddEventAccessor() and
|
||||
e.getRemoveEventAccessor().getSourceDeclaration() =
|
||||
e.getSourceDeclaration().getRemoveEventAccessor()
|
||||
select bString, e
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:22:18:22:21 | B<String> | generics.cs:39:37:39:38 | ++ |
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ConstructedClass bString, Operator o
|
||||
where
|
||||
bString.hasName("B<String>") and
|
||||
o.getDeclaringType() = bString and
|
||||
o instanceof IncrementOperator and
|
||||
o.getSourceDeclaration().getDeclaringType() = o.getDeclaringType().getSourceDeclaration()
|
||||
select bString, o
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:73:18:73:21 | Item |
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ConstructedClass gridInt, Indexer i
|
||||
where
|
||||
gridInt.hasName("Grid<Int32>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getSourceDeclaration().getDeclaringType() = i.getDeclaringType().getSourceDeclaration() and
|
||||
i.getGetter().getSourceDeclaration() = i.getSourceDeclaration().getGetter() and
|
||||
i.getSetter().getSourceDeclaration() = i.getSourceDeclaration().getSetter()
|
||||
select gridInt, i
|
||||
@@ -1,2 +0,0 @@
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:68:20:68:23 | Item |
|
||||
| generics.cs:60:18:60:24 | Grid<Int32> | generics.cs:73:18:73:21 | Item |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ConstructedClass gridInt, Indexer i
|
||||
where
|
||||
gridInt.hasName("Grid<Int32>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getType() instanceof IntType
|
||||
select gridInt, i
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:60:18:60:24 | Grid<> | generics.cs:68:20:68:23 | Item |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from UnboundGenericClass gridInt, Indexer i
|
||||
where
|
||||
gridInt.hasName("Grid<>") and
|
||||
i.getDeclaringType() = gridInt and
|
||||
i.getType() instanceof IntType
|
||||
select gridInt, i
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:7:23:7:40 | GenericDelegate<String> |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from ConstructedDelegateType d
|
||||
where
|
||||
d.hasName("GenericDelegate<String>") and
|
||||
d.getTypeArgument(0) instanceof StringType and
|
||||
d.getParameter(0).getType() instanceof StringType
|
||||
select d
|
||||
@@ -1,3 +0,0 @@
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:137:21:137:25 | fs |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:139:21:139:25 | fs |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:141:21:141:22 | fs |
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from Class c
|
||||
where
|
||||
c.hasName("Subtle") and
|
||||
count(c.getAMethod()) = 3
|
||||
select c, c.getAMethod()
|
||||
@@ -1,2 +0,0 @@
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:137:21:137:25 | fs | 1 | generics.cs:137:24:137:24 | X | generics.cs:139:21:139:25 | fs | generics.cs:139:24:139:24 | X |
|
||||
| generics.cs:134:11:134:16 | Subtle | generics.cs:139:21:139:25 | fs | 2 | generics.cs:139:24:139:24 | X | generics.cs:137:21:137:25 | fs | generics.cs:137:24:137:24 | X |
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from Class c, TypeParameter p, UnboundGenericMethod m, TypeParameter q, UnboundGenericMethod n
|
||||
where
|
||||
c.hasName("Subtle") and
|
||||
m = c.getAMethod() and
|
||||
m.getATypeParameter() = p and
|
||||
n = c.getAMethod() and
|
||||
n.getATypeParameter() = q and
|
||||
m != n and
|
||||
p != q
|
||||
select c, m, m.getNumberOfParameters(), p, n, q
|
||||
@@ -1,10 +0,0 @@
|
||||
| generics.cs:13:18:13:21 | A<> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | T | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 1 | Test | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<Int32> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 1 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 0 | X | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:27:18:27 | x | 1 | Int32 | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 0 | String | 2 | 2 |
|
||||
| generics.cs:13:18:13:21 | A<String> | generics.cs:18:18:18:23 | bar | generics.cs:18:32:18:32 | t | 1 | String | 2 | 2 |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test for generic parameter types
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from Class c, Method m
|
||||
where
|
||||
c.getName().matches("A<%") and
|
||||
m = c.getAMethod()
|
||||
select c, m, m.getAParameter() as p, count(m.(ConstructedMethod).getATypeArgument()),
|
||||
p.getType().getName(), count(m.getAParameter()), count(m.getAParameter().getType())
|
||||
@@ -1,2 +0,0 @@
|
||||
| generics.cs:137:21:137:25 | fs | generics.cs:137:24:137:24 | X | 1 |
|
||||
| generics.cs:139:21:139:25 | fs | generics.cs:139:24:139:24 | X | 1 |
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* @name Test that locations are populated for the type parameters of generic methods
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from UnboundGenericMethod m, TypeParameter tp, int hasLoc
|
||||
where
|
||||
m.hasName("fs") and
|
||||
tp = m.getATypeParameter() and
|
||||
if exists(tp.getLocation()) then hasLoc = 1 else hasLoc = 0
|
||||
select m, tp, hasLoc
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:9:18:9:18 | A |
|
||||
@@ -1,11 +0,0 @@
|
||||
/**
|
||||
* @name Test for generics
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from Class c
|
||||
where
|
||||
c.hasName("A") and
|
||||
not c instanceof UnboundGenericClass
|
||||
select c
|
||||
@@ -1 +0,0 @@
|
||||
| 1 |
|
||||
@@ -1,9 +0,0 @@
|
||||
/**
|
||||
* @name Test that locations are populated for unbound generic types
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
from UnboundGenericType t
|
||||
where type_location(t, _)
|
||||
select 1
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:145:11:145:18 | Param<> | generics.cs:147:14:147:14 | E |
|
||||
@@ -1,17 +0,0 @@
|
||||
import csharp
|
||||
|
||||
/*
|
||||
* This tests a regression in the extractor where the following failed to extract:
|
||||
*
|
||||
* class Foo<T>
|
||||
* {
|
||||
* enum E { a };
|
||||
* }
|
||||
*/
|
||||
|
||||
from Enum e, Class c
|
||||
where
|
||||
c.hasName("Param<>") and
|
||||
e.hasName("E") and
|
||||
e.getDeclaringType() = c
|
||||
select c, e
|
||||
@@ -1,6 +0,0 @@
|
||||
| generics.cs:152:14:152:19 | CM1 | Double |
|
||||
| generics.cs:152:14:152:19 | CM1 | Int32 |
|
||||
| generics.cs:153:11:153:16 | CM2 | Double |
|
||||
| generics.cs:153:11:153:16 | CM2 | Int32 |
|
||||
| generics.cs:157:23:157:29 | CM3 | Double |
|
||||
| generics.cs:157:23:157:29 | CM3 | Double |
|
||||
@@ -1,7 +0,0 @@
|
||||
import csharp
|
||||
|
||||
from ConstructedMethod m, ValueOrRefType tp
|
||||
where
|
||||
m.getName().matches("CM%") and
|
||||
tp = m.getATypeArgument()
|
||||
select m, tp.getName()
|
||||
@@ -1,2 +0,0 @@
|
||||
| generics.cs:178:11:178:24 | Inheritance<> | generics.cs:173:15:173:26 | Interface<T> |
|
||||
| generics.cs:178:11:178:24 | Inheritance<Int32> | generics.cs:173:15:173:26 | Interface<Int32> |
|
||||
@@ -1,7 +0,0 @@
|
||||
import csharp
|
||||
|
||||
from Class c, Interface i
|
||||
where
|
||||
c.getName().matches("Inheritance%") and
|
||||
i = c.getABaseInterface()
|
||||
select c, i
|
||||
@@ -1,2 +0,0 @@
|
||||
| generics.cs:188:15:188:39 | Interface2<,> | generics.cs:188:29:188:30 | T1 | in |
|
||||
| generics.cs:188:15:188:39 | Interface2<,> | generics.cs:188:37:188:38 | T2 | out |
|
||||
@@ -1,12 +0,0 @@
|
||||
import csharp
|
||||
|
||||
from UnboundGenericInterface ugi, TypeParameter tp, string s
|
||||
where
|
||||
ugi.fromSource() and
|
||||
ugi.getATypeParameter() = tp and
|
||||
(
|
||||
tp.isOut() and s = "out"
|
||||
or
|
||||
tp.isIn() and s = "in"
|
||||
)
|
||||
select ugi, tp, s
|
||||
@@ -1 +0,0 @@
|
||||
| generics.cs:157:23:157:29 | CM3 |
|
||||
@@ -1,21 +0,0 @@
|
||||
import csharp
|
||||
|
||||
from ConstructedMethod cm
|
||||
where
|
||||
cm.hasName("CM3") and
|
||||
cm.getParameter(0).getType() instanceof DoubleType and
|
||||
cm.getParameter(1).getType() instanceof IntType and
|
||||
cm.getReturnType() instanceof DoubleType and
|
||||
exists(Method sourceDeclaration |
|
||||
sourceDeclaration = cm.getSourceDeclaration() and
|
||||
sourceDeclaration.getParameter(0).getType().(TypeParameter).hasName("T2") and
|
||||
sourceDeclaration.getParameter(1).getType().(TypeParameter).hasName("T1") and
|
||||
sourceDeclaration.getReturnType().(TypeParameter).hasName("T2")
|
||||
) and
|
||||
exists(Method unbound |
|
||||
unbound = cm.getUnboundGeneric() and
|
||||
unbound.getParameter(0).getType().(TypeParameter).hasName("T2") and
|
||||
unbound.getParameter(1).getType() instanceof IntType and
|
||||
unbound.getReturnType().(TypeParameter).hasName("T2")
|
||||
)
|
||||
select cm
|
||||
@@ -1 +0,0 @@
|
||||
| Test passed |
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user