Merge branch 'main' into jwt

This commit is contained in:
Erik Krogh Kristensen
2020-11-12 21:36:09 +01:00
260 changed files with 4189 additions and 1598 deletions

View File

@@ -409,5 +409,12 @@
"java/ql/src/Metrics/Files/CommentedOutCodeReferences.qhelp",
"javascript/ql/src/Comments/CommentedOutCodeReferences.qhelp",
"python/ql/src/Lexical/CommentedOutCodeReferences.qhelp"
],
"IDE Contextual Queries": [
"cpp/ql/src/IDEContextual.qll",
"csharp/ql/src/IDEContextual.qll",
"java/ql/src/IDEContextual.qll",
"javascript/ql/src/IDEContextual.qll",
"python/ql/src/analysis/IDEContextual.qll"
]
}

View File

@@ -0,0 +1,22 @@
/**
* Provides shared predicates related to contextual queries in the code viewer.
*/
import semmle.files.FileSystem
/**
* Returns the `File` matching the given source file name as encoded by the VS
* Code extension.
*/
cached
File getFileBySourceArchiveName(string name) {
// The name provided for a file in the source archive by the VS Code extension
// has some differences from the absolute path in the database:
// 1. colons are replaced by underscores
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
// "/C_/foo/bar"
// 3. double slashes in UNC prefixes are replaced with a single slash
// We can handle 2 and 3 together by unconditionally adding a leading slash
// before replacing double slashes.
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
}

View File

@@ -50,10 +50,12 @@ class SafeTimeGatheringFunction extends Function {
class TimeConversionFunction extends Function {
TimeConversionFunction() {
this.getQualifiedName() =
["FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
"RtlTimeToSecondsSince1970", "_mkgmtime"]
[
"FileTimeToSystemTime", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime",
"SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime",
"TzSpecificLocalTimeToSystemTimeEx", "RtlLocalTimeToSystemTime",
"RtlTimeToSecondsSince1970", "_mkgmtime"
]
}
}

View File

@@ -4,6 +4,7 @@
*/
import cpp
import IDEContextual
/**
* Any element that might be the source or target of a jump-to-definition
@@ -207,11 +208,3 @@ Top definitionOf(Top e, string kind) {
// later on.
strictcount(result.getLocation()) < 10
}
/**
* Returns an appropriately encoded version of a filename `name`
* passed by the VS Code extension in order to coincide with the
* output of `.getFile()` on locatable entities.
*/
cached
File getEncodedFile(string name) { result.getAbsolutePath().replaceAll(":", "_") = name }

View File

@@ -7,7 +7,6 @@ import semmle.code.cpp.dataflow.TaintTracking
import experimental.semmle.code.cpp.security.PrivateData
import semmle.code.cpp.security.FileWrite
import semmle.code.cpp.security.BufferWrite
import semmle.code.cpp.dataflow.TaintTracking
module PrivateCleartextWrite {
/**

View File

@@ -12,5 +12,5 @@ import definitions
external string selectedSourceFile();
from Top e, Top def, string kind
where def = definitionOf(e, kind) and e.getFile() = getEncodedFile(selectedSourceFile())
where def = definitionOf(e, kind) and e.getFile() = getFileBySourceArchiveName(selectedSourceFile())
select e, def, kind

View File

@@ -12,5 +12,6 @@ import definitions
external string selectedSourceFile();
from Top e, Top def, string kind
where def = definitionOf(e, kind) and def.getFile() = getEncodedFile(selectedSourceFile())
where
def = definitionOf(e, kind) and def.getFile() = getFileBySourceArchiveName(selectedSourceFile())
select e, def, kind

View File

@@ -22,6 +22,6 @@ class Cfg extends PrintASTConfiguration {
* Print All functions from the selected file.
*/
override predicate shouldPrintFunction(Function func) {
func.getFile() = getEncodedFile(selectedSourceFile())
func.getFile() = getFileBySourceArchiveName(selectedSourceFile())
}
}

View File

@@ -9,12 +9,14 @@ import cpp
class StrcatFunction extends Function {
StrcatFunction() {
getName() =
["strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l"] // _mbsncat_l(dst, src, max_amount, locale)
[
"strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
]
}
}

View File

@@ -677,6 +677,11 @@ private predicate exprToExprStep_nocfg(Expr fromExpr, Expr toExpr) {
exists(DataFlowFunction f, FunctionInput inModel, FunctionOutput outModel |
f.hasDataFlow(inModel, outModel) and
(
exists(int iIn |
inModel.isParameterDeref(iIn) and
call.passesByReference(iIn, fromExpr)
)
or
exists(int iIn |
inModel.isParameter(iIn) and
fromExpr = call.getArgument(iIn)

View File

@@ -441,40 +441,6 @@ class ConstructorCall extends FunctionCall {
override Constructor getTarget() { result = super.getTarget() }
}
/**
* A C++ `throw` expression.
* ```
* throw Exc(2);
* ```
*/
class ThrowExpr extends Expr, @throw_expr {
/**
* Gets the expression that will be thrown, if any. There is no result if
* `this` is a `ReThrowExpr`.
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
override string toString() { result = "throw ..." }
override int getPrecedence() { result = 1 }
}
/**
* A C++ `throw` expression with no argument (which causes the current exception to be re-thrown).
* ```
* throw;
* ```
*/
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
override string toString() { result = "re-throw exception " }
}
/**
* A call to a destructor.
* ```

View File

@@ -1146,6 +1146,40 @@ class BlockExpr extends Literal {
Function getFunction() { code_block(underlyingElement(this), unresolveElement(result)) }
}
/**
* A C++ `throw` expression.
* ```
* throw Exc(2);
* ```
*/
class ThrowExpr extends Expr, @throw_expr {
/**
* Gets the expression that will be thrown, if any. There is no result if
* `this` is a `ReThrowExpr`.
*/
Expr getExpr() { result = this.getChild(0) }
override string getAPrimaryQlClass() { result = "ThrowExpr" }
override string toString() { result = "throw ..." }
override int getPrecedence() { result = 1 }
}
/**
* A C++ `throw` expression with no argument (which causes the current exception to be re-thrown).
* ```
* throw;
* ```
*/
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
override string getAPrimaryQlClass() { result = "ReThrowExpr" }
override string toString() { result = "re-throw exception " }
}
/**
* A C++11 `noexcept` expression, returning `true` if its subexpression is guaranteed
* not to `throw` exceptions. For example:

View File

@@ -228,7 +228,7 @@ private class ArrayContent extends Content, TArrayContent {
private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(StoreInstruction store, Class c |
store = node2.asInstruction() and
store.getSourceValue() = node1.asInstruction() and
store.getSourceValueOperand() = node1.asOperand() and
getWrittenField(store, f.(FieldContent).getAField(), c) and
f.hasOffset(c, _, _)
)
@@ -243,18 +243,20 @@ pragma[noinline]
private predicate getWrittenField(Instruction instr, Field f, Class c) {
exists(FieldAddressInstruction fa |
fa =
getFieldInstruction([instr.(StoreInstruction).getDestinationAddress(),
instr.(WriteSideEffectInstruction).getDestinationAddress()]) and
getFieldInstruction([
instr.(StoreInstruction).getDestinationAddress(),
instr.(WriteSideEffectInstruction).getDestinationAddress()
]) and
f = fa.getField() and
c = f.getDeclaringType()
)
}
private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(StoreInstruction store, ChiInstruction chi |
node1.asInstruction() = store and
exists(ChiPartialOperand operand, ChiInstruction chi |
chi.getPartialOperand() = operand and
node1.asOperand() = operand and
node2.asInstruction() = chi and
chi.getPartial() = store and
exists(Class c |
c = chi.getResultType() and
exists(int startBit, int endBit |
@@ -262,7 +264,7 @@ private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode n
f.hasOffset(c, startBit, endBit)
)
or
getWrittenField(store, f.getAField(), c) and
getWrittenField(operand.getDef(), f.getAField(), c) and
f.hasOffset(c, _, _)
)
)
@@ -270,8 +272,13 @@ private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode n
private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode node2) {
a = TArrayContent() and
exists(StoreInstruction store |
node1.asInstruction() = store and
exists(ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store |
chi.getPartialOperand() = operand and
store = operand.getDef() and
node1.asOperand() = operand and
// This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
// and `PointerStoreNode` require it in their characteristic predicates.
node2.asInstruction() = chi and
(
// `x[i] = taint()`
// This matches the characteristic predicate in `ArrayStoreNode`.
@@ -280,10 +287,7 @@ private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode n
// `*p = taint()`
// This matches the characteristic predicate in `PointerStoreNode`.
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
) and
// This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
// and `PointerStoreNode` require it in their characteristic predicates.
node2.asInstruction().(ChiInstruction).getPartial() = store
)
)
}
@@ -304,7 +308,7 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
private predicate fieldStoreStepAfterArraySuppression(
Node node1, FieldContent f, PostUpdateNode node2
) {
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi, Class c |
exists(WriteSideEffectInstruction write, ChiInstruction chi, Class c |
not chi.isResultConflated() and
node1.asInstruction() = chi and
node2.asInstruction() = chi and
@@ -332,17 +336,17 @@ private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
* `node2`.
*/
private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
exists(LoadInstruction load |
node2.asInstruction() = load and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
exists(LoadOperand operand |
node2.asOperand() = operand and
node1.asInstruction() = operand.getAnyDef() and
exists(Class c |
c = load.getSourceValueOperand().getAnyDef().getResultType() and
c = operand.getAnyDef().getResultType() and
exists(int startBit, int endBit |
load.getSourceValueOperand().getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
f.hasOffset(c, startBit, endBit)
)
or
getLoadedField(load, f.getAField(), c) and
getLoadedField(operand.getUse(), f.getAField(), c) and
f.hasOffset(c, _, _)
)
)
@@ -363,7 +367,7 @@ private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
*/
predicate suppressArrayRead(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi |
exists(WriteSideEffectInstruction write, ChiInstruction chi |
node1.asInstruction() = write and
node2.asInstruction() = chi and
chi.getPartial() = write and
@@ -384,20 +388,20 @@ private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) {
result = skipOneCopyValueInstructionRec(copy.getUnary())
}
private Instruction skipCopyValueInstructions(Instruction instr) {
not result instanceof CopyValueInstruction and result = instr
private Instruction skipCopyValueInstructions(Operand op) {
not result instanceof CopyValueInstruction and result = op.getDef()
or
result = skipOneCopyValueInstructionRec(instr)
result = skipOneCopyValueInstructionRec(op.getDef())
}
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
// Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
exists(LoadInstruction load, Instruction address |
load.getSourceValueOperand().isDefinitionInexact() and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
load = node2.asInstruction() and
address = skipCopyValueInstructions(load.getSourceAddress()) and
exists(LoadOperand operand, Instruction address |
operand.isDefinitionInexact() and
node1.asInstruction() = operand.getAnyDef() and
operand = node2.asOperand() and
address = skipCopyValueInstructions(operand.getAddressOperand()) and
(
address instanceof LoadInstruction or
address instanceof ArrayToPointerConvertInstruction or
@@ -418,18 +422,18 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
* use(x);
* ```
* the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition
* is a `BufferMayWriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
* is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
* from the access path.
*/
private predicate exactReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi |
exists(WriteSideEffectInstruction write, ChiInstruction chi |
not chi.isResultConflated() and
chi.getPartial() = write and
node1.asInstruction() = write and
node2.asInstruction() = chi and
// To distinquish this case from the `arrayReadStep` case we require that the entire variable was
// overwritten by the `BufferMayWriteSideEffectInstruction` (i.e., there is a load that reads the
// overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the
// entire variable).
exists(LoadInstruction load | load.getSourceValue() = chi)
)

View File

@@ -396,16 +396,16 @@ private FieldAddressInstruction getFieldInstruction(Instruction instr) {
/**
* The target of a `fieldStoreStepAfterArraySuppression` store step, which is used to convert
* an `ArrayContent` to a `FieldContent` when the `BufferMayWriteSideEffect` instruction stores
* an `ArrayContent` to a `FieldContent` when the `WriteSideEffect` instruction stores
* into a field. See the QLDoc for `suppressArrayRead` for an example of where such a conversion
* is inserted.
*/
private class BufferMayWriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode {
private class WriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
BufferMayWriteSideEffectInstruction write;
WriteSideEffectInstruction write;
FieldAddressInstruction field;
BufferMayWriteSideEffectFieldStoreQualifierNode() {
WriteSideEffectFieldStoreQualifierNode() {
not instr.isResultConflated() and
instr.getPartial() = write and
field = getFieldInstruction(write.getDestinationAddress())

View File

@@ -308,8 +308,10 @@ class IteratorAssignmentMemberOperator extends MemberFunction, TaintFunction {
class BeginOrEndFunction extends MemberFunction, TaintFunction, GetIteratorFunction {
BeginOrEndFunction() {
this
.hasName(["begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend",
"before_begin", "cbefore_begin"]) and
.hasName([
"begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
"cbefore_begin"
]) and
this.getType().getUnspecifiedType() instanceof Iterator
}

View File

@@ -35,11 +35,7 @@ class ConversionConstructorModel extends Constructor, TaintFunction {
class CopyConstructorModel extends CopyConstructor, DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// data flow from the first constructor argument to the returned object
(
input.isParameter(0)
or
input.isParameterDeref(0)
) and
input.isParameterDeref(0) and
(
output.isReturnValue()
or
@@ -54,11 +50,7 @@ class CopyConstructorModel extends CopyConstructor, DataFlowFunction {
class MoveConstructorModel extends MoveConstructor, DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// data flow from the first constructor argument to the returned object
(
input.isParameter(0)
or
input.isParameterDeref(0)
) and
input.isParameterDeref(0) and
(
output.isReturnValue()
or

View File

@@ -5,9 +5,11 @@ import semmle.code.cpp.models.interfaces.SideEffect
class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction {
PureStrFunction() {
hasGlobalOrStdName(["atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr",
"strchrnul", "strstr", "strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn",
"strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"])
hasGlobalOrStdName([
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
"strtol", "strtoll", "strtoq", "strtoul"
])
}
override predicate hasArrayInput(int bufParam) {

View File

@@ -14,20 +14,24 @@ import semmle.code.cpp.models.interfaces.SideEffect
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() {
getName() =
["strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src)
"_mbscpy", // _mbscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"wcsncpy", // wcsncpy(dst, src, max_amount)
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
"_mbsncpy_l"] // _mbsncpy_l(dst, src, max_amount, locale)
[
"strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src)
"_mbscpy", // _mbscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"wcsncpy", // wcsncpy(dst, src, max_amount)
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
"_mbsncpy_l" // _mbsncpy_l(dst, src, max_amount, locale)
]
or
getName() =
["strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
"_mbscpy_s"] and // _mbscpy_s(dst, max_amount, src)
[
"strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
"_mbscpy_s" // _mbscpy_s(dst, max_amount, src)
] and
// exclude the 2-parameter template versions
// that find the size of a fixed size destination buffer.
getNumberOfParameters() = 3

View File

@@ -22,7 +22,7 @@ abstract class IteratorReferenceFunction extends Function { }
abstract class GetIteratorFunction extends Function {
/**
* Holds if the return value or buffer represented by `output` is an iterator over the container
* passd in the argument, qualifier, or buffer represented by `input`.
* passed in the argument, qualifier, or buffer represented by `input`.
*/
abstract predicate getsIterator(FunctionInput input, FunctionOutput output);
}

View File

@@ -355,9 +355,11 @@ class SnprintfBW extends BufferWriteCall {
class GetsBW extends BufferWriteCall {
GetsBW() {
getTarget().(TopLevelFunction).getName() =
["gets", // gets(dst)
"fgets", // fgets(dst, max_amount, src_stream)
"fgetws"] // fgetws(dst, max_amount, src_stream)
[
"gets", // gets(dst)
"fgets", // fgets(dst, max_amount, src_stream)
"fgetws" // fgetws(dst, max_amount, src_stream)
]
}
/**

View File

@@ -678,7 +678,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
override string getAPrimaryQlClass() { result = "CoReturnStmt" }
/**
* Gets the operand of this 'co_return' statement.
* Gets the operand of this `co_return` statement.
*
* For example, for
* ```
@@ -693,7 +693,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
FunctionCall getOperand() { result = this.getChild(0) }
/**
* Gets the expression of this 'co_return' statement, if any.
* Gets the expression of this `co_return` statement, if any.
*
* For example, for
* ```
@@ -707,7 +707,7 @@ class CoReturnStmt extends Stmt, @stmt_co_return {
Expr getExpr() { result = this.getOperand().getArgument(0) }
/**
* Holds if this 'co_return' statement has an expression.
* Holds if this `co_return` statement has an expression.
*
* For example, this holds for
* ```

View File

@@ -121,6 +121,14 @@ postWithInFlow
| complex.cpp:12:22:12:27 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:33:14:33 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:22:11:22:17 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:25:7:25:7 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:42:16:42:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:43:16:43:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:53:12:53:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:54:12:54:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:55:12:55:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:56:12:56:12 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -4,9 +4,8 @@ edges
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] |
| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:100:5:100:13 | Chi [a] | A.cpp:103:14:103:14 | *c [a] |
| A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] |
@@ -14,11 +13,9 @@ edges
| A.cpp:131:8:131:8 | Chi [c] | A.cpp:132:13:132:13 | c |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:131:8:131:8 | Chi [c] |
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:143:7:143:31 | Store | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Store |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b |
| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] |
@@ -27,20 +24,16 @@ edges
| C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] |
| C.cpp:22:12:22:21 | Store | C.cpp:22:12:22:21 | Chi [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Store |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Chi [s1] |
| C.cpp:24:5:24:25 | Chi [s1] | C.cpp:18:12:18:18 | C output argument [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | C.cpp:18:12:18:18 | C output argument [s3] |
| C.cpp:24:5:24:25 | Store | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Store |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
@@ -48,15 +41,13 @@ edges
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | aliasing.cpp:100:14:100:14 | Store [m1] |
| aliasing.cpp:98:3:98:21 | Store | aliasing.cpp:98:3:98:21 | Chi [m1] |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Store |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Chi [m1] |
| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] |
@@ -67,8 +58,7 @@ edges
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Store | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Store |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:121:15:121:16 | Chi [array content] | aliasing.cpp:122:8:122:12 | access to array |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | aliasing.cpp:121:15:121:16 | Chi [array content] |
| aliasing.cpp:126:15:126:20 | Chi [array content] | aliasing.cpp:127:8:127:16 | * ... |
@@ -106,20 +96,16 @@ edges
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Store |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Store | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Store |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | Store | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Store |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | Store | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Store |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] |
| by_reference.cpp:104:15:104:22 | Chi | by_reference.cpp:104:15:104:22 | Chi [a] |
@@ -141,18 +127,34 @@ edges
| by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | Chi |
| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | Chi [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | Chi [a_] |
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] |
| complex.cpp:54:12:54:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | Chi [b_] |
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] |
| complex.cpp:56:12:56:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | Chi [b_] |
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] |
| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] |
@@ -184,19 +186,16 @@ edges
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
| simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Store |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Store |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
nodes
| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] |
@@ -208,7 +207,6 @@ nodes
| A.cpp:57:28:57:30 | call to get | semmle.label | call to get |
| A.cpp:98:12:98:18 | new | semmle.label | new |
| A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] |
| A.cpp:100:5:100:13 | Store | semmle.label | Store |
| A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:126:5:126:5 | Chi [c] | semmle.label | Chi [c] |
@@ -218,10 +216,8 @@ nodes
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:13:132:13 | c | semmle.label | c |
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] |
| A.cpp:143:7:143:31 | Store | semmle.label | Store |
| A.cpp:143:25:143:31 | new | semmle.label | new |
| A.cpp:150:12:150:18 | new | semmle.label | new |
| A.cpp:151:12:151:24 | Chi [b] | semmle.label | Chi [b] |
@@ -233,21 +229,17 @@ nodes
| C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | semmle.label | C output argument [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:22:12:22:21 | Store | semmle.label | Store |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:25 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | semmle.label | Chi [s3] |
| C.cpp:24:5:24:25 | Store | semmle.label | Store |
| C.cpp:24:16:24:25 | new | semmle.label | new |
| C.cpp:27:8:27:11 | *#this [s1] | semmle.label | *#this [s1] |
| C.cpp:27:8:27:11 | *#this [s3] | semmle.label | *#this [s3] |
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
@@ -260,7 +252,6 @@ nodes
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
@@ -271,12 +262,10 @@ nodes
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:98:3:98:21 | Store | semmle.label | Store |
| aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:106:3:106:20 | Store | semmle.label | Store |
| aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:121:15:121:16 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
@@ -330,16 +319,12 @@ nodes
| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | semmle.label | Store |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:88:3:88:24 | Store | semmle.label | Store |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:92:3:92:20 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:92:3:92:20 | Store | semmle.label | Store |
| by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:96:3:96:19 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:96:3:96:19 | Store | semmle.label | Store |
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
@@ -371,15 +356,21 @@ nodes
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] |
| complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] |
| complex.cpp:42:16:42:16 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | semmle.label | a output argument [b_] |
| complex.cpp:42:18:42:18 | call to a | semmle.label | call to a |
| complex.cpp:43:18:43:18 | call to b | semmle.label | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:54:12:54:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:55:12:55:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:56:12:56:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | semmle.label | setB output argument [a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input |
@@ -415,7 +406,6 @@ nodes
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] |
| simple.cpp:83:9:83:28 | Store | semmle.label | Store |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] |
@@ -425,11 +415,9 @@ nodes
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:20:20:20:29 | Store | semmle.label | Store |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:27:7:27:16 | Store | semmle.label | Store |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
#select

View File

@@ -294,22 +294,16 @@
| complex.cpp:11:22:11:23 | a_ | AST only |
| complex.cpp:12:22:12:23 | b_ | AST only |
| complex.cpp:42:8:42:8 | b | AST only |
| complex.cpp:42:10:42:14 | inner | AST only |
| complex.cpp:42:16:42:16 | f | AST only |
| complex.cpp:43:8:43:8 | b | AST only |
| complex.cpp:43:10:43:14 | inner | AST only |
| complex.cpp:43:16:43:16 | f | AST only |
| complex.cpp:53:3:53:4 | b1 | AST only |
| complex.cpp:53:6:53:10 | inner | AST only |
| complex.cpp:53:12:53:12 | f | AST only |
| complex.cpp:54:3:54:4 | b2 | AST only |
| complex.cpp:54:6:54:10 | inner | AST only |
| complex.cpp:54:12:54:12 | f | AST only |
| complex.cpp:55:3:55:4 | b3 | AST only |
| complex.cpp:55:6:55:10 | inner | AST only |
| complex.cpp:55:12:55:12 | f | AST only |
| complex.cpp:56:3:56:4 | b3 | AST only |
| complex.cpp:56:6:56:10 | inner | AST only |
| complex.cpp:56:12:56:12 | f | AST only |
| complex.cpp:59:7:59:8 | b1 | AST only |
| complex.cpp:62:7:62:8 | b2 | AST only |

View File

@@ -51,6 +51,12 @@
| by_reference.cpp:128:15:128:20 | pouter |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | this |
| complex.cpp:42:10:42:14 | inner |
| complex.cpp:43:10:43:14 | inner |
| complex.cpp:53:6:53:10 | inner |
| complex.cpp:54:6:54:10 | inner |
| complex.cpp:55:6:55:10 | inner |
| complex.cpp:56:6:56:10 | inner |
| constructors.cpp:20:24:20:25 | this |
| constructors.cpp:21:24:21:25 | this |
| qualifiers.cpp:9:30:9:33 | this |

View File

@@ -5113,10 +5113,11 @@
| swap1.cpp:109:5:109:30 | ... = ... | swap1.cpp:111:20:111:24 | data1 | |
| swap1.cpp:109:5:109:30 | ... = ... | swap1.cpp:115:18:115:22 | data1 | |
| swap1.cpp:109:23:109:28 | call to source | swap1.cpp:109:5:109:30 | ... = ... | |
| swap1.cpp:113:31:113:39 | call to move | swap1.cpp:113:31:113:51 | call to Class | |
| swap1.cpp:113:31:113:39 | call to move | swap1.cpp:113:31:113:51 | call to Class | TAINT |
| swap1.cpp:113:31:113:39 | ref arg call to move | swap1.cpp:113:41:113:49 | move_from [inner post update] | |
| swap1.cpp:113:31:113:51 | call to Class | swap1.cpp:115:10:115:16 | move_to | |
| swap1.cpp:113:41:113:49 | move_from | swap1.cpp:113:31:113:39 | call to move | |
| swap1.cpp:113:41:113:49 | move_from | swap1.cpp:113:31:113:51 | call to Class | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:122:5:122:5 | x | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:124:10:124:10 | x | |
| swap1.cpp:120:23:120:23 | x | swap1.cpp:127:19:127:19 | x | |
@@ -5279,10 +5280,11 @@
| swap2.cpp:109:5:109:30 | ... = ... | swap2.cpp:111:20:111:24 | data1 | |
| swap2.cpp:109:5:109:30 | ... = ... | swap2.cpp:115:18:115:22 | data1 | |
| swap2.cpp:109:23:109:28 | call to source | swap2.cpp:109:5:109:30 | ... = ... | |
| swap2.cpp:113:31:113:39 | call to move | swap2.cpp:113:31:113:51 | call to Class | |
| swap2.cpp:113:31:113:39 | call to move | swap2.cpp:113:31:113:51 | call to Class | TAINT |
| swap2.cpp:113:31:113:39 | ref arg call to move | swap2.cpp:113:41:113:49 | move_from [inner post update] | |
| swap2.cpp:113:31:113:51 | call to Class | swap2.cpp:115:10:115:16 | move_to | |
| swap2.cpp:113:41:113:49 | move_from | swap2.cpp:113:31:113:39 | call to move | |
| swap2.cpp:113:41:113:49 | move_from | swap2.cpp:113:31:113:51 | call to Class | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:122:5:122:5 | x | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:124:10:124:10 | x | |
| swap2.cpp:120:23:120:23 | x | swap2.cpp:127:19:127:19 | x | |

View File

@@ -1491,6 +1491,7 @@ postWithInFlow
| conditional_destructors.cpp:18:13:18:19 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:45:82:48 | Chi | PostUpdateNode should not be the target of local flow. |
| defdestructordeleteexpr.cpp:4:9:4:15 | Chi | PostUpdateNode should not be the target of local flow. |
| deleteexpr.cpp:7:9:7:15 | Chi | PostUpdateNode should not be the target of local flow. |
@@ -1541,6 +1542,18 @@ postWithInFlow
| ir.cpp:659:9:659:14 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:660:13:660:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:661:9:661:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:662:9:662:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:663:5:663:5 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:748:10:748:10 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:754:8:754:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:757:12:757:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:763:8:763:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:766:13:766:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:775:15:775:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:784:15:784:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:793:15:793:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:943:3:943:11 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:947:3:947:25 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. |
@@ -1564,3 +1577,4 @@ postWithInFlow
| range_analysis.c:102:5:102:15 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:3:2:3:8 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:21:2:21:12 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:240:7:240:7 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -5,10 +5,6 @@ edges
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:28 | access to array | tests.c:28:22:28:28 | (const char *)... |
| tests.c:28:22:28:28 | access to array | tests.c:28:22:28:28 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
@@ -19,10 +15,6 @@ edges
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:16 | access to array | tests.c:34:10:34:16 | (const char *)... |
| tests.c:34:10:34:16 | access to array | tests.c:34:10:34:16 | access to array |
nodes
| tests.c:28:22:28:25 | argv | semmle.label | argv |
| tests.c:28:22:28:25 | argv | semmle.label | argv |

View File

@@ -5,10 +5,6 @@ edges
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:15 | (const char *)... |
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
@@ -39,8 +35,6 @@ edges
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
@@ -51,16 +45,10 @@ edges
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:106:9:106:13 | (const char *)... |
| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:110:9:110:11 | (const char *)... |
| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |

View File

@@ -59,9 +59,8 @@ edges
| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | Store | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Store |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Store |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
@@ -144,7 +143,7 @@ nodes
| test.cpp:235:2:235:9 | Argument 0 | semmle.label | Argument 0 |
| test.cpp:237:2:237:8 | Argument 0 | semmle.label | Argument 0 |
| test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:241:2:241:32 | Store | semmle.label | Store |
| test.cpp:241:2:241:32 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv |

View File

@@ -43,13 +43,11 @@ edges
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:13:2:13:15 | Chi [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] |
| test.cpp:13:2:13:15 | Store | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Store |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Store |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:18:2:18:14 | Chi [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] |
| test.cpp:18:2:18:14 | Store | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Store |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Store |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
@@ -111,11 +109,11 @@ nodes
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:13:2:13:15 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:13:2:13:15 | Store | semmle.label | Store |
| test.cpp:13:2:13:15 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:18:2:18:14 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:18:2:18:14 | Store | semmle.label | Store |
| test.cpp:18:2:18:14 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand |

View File

@@ -0,0 +1,5 @@
lgtm,codescanning
* Attribute extraction has been extended to extract attributes not only from source
code, but from referenced assemblies too. This change may lead to more results in
queries that rely on attributes. Note that, as more attributes might be extracted,
the DB size might increase.

View File

@@ -198,12 +198,12 @@ namespace Semmle.Extraction.CSharp
/// Perform an analysis on an assembly.
/// </summary>
/// <param name="assembly">Assembly to analyse.</param>
private void AnalyseAssembly(PortableExecutableReference assembly)
private void AnalyseReferenceAssembly(PortableExecutableReference assembly)
{
// CIL first - it takes longer.
if (options.CIL)
extractionTasks.Add(() => DoExtractCIL(assembly));
extractionTasks.Add(() => DoAnalyseAssembly(assembly));
extractionTasks.Add(() => DoAnalyseReferenceAssembly(assembly));
}
private static bool FileIsUpToDate(string src, string dest)
@@ -250,7 +250,7 @@ namespace Semmle.Extraction.CSharp
/// extraction within the snapshot.
/// </summary>
/// <param name="r">The assembly to extract.</param>
private void DoAnalyseAssembly(PortableExecutableReference r)
private void DoAnalyseReferenceAssembly(PortableExecutableReference r)
{
try
{
@@ -294,6 +294,8 @@ namespace Semmle.Extraction.CSharp
AnalyseNamespace(cx, module.GlobalNamespace);
}
Entities.Attribute.ExtractAttributes(cx, assembly, Extraction.Entities.Assembly.Create(cx, assembly.GetSymbolLocation()));
cx.PopulateAll();
}
}
@@ -335,7 +337,7 @@ namespace Semmle.Extraction.CSharp
{
foreach (var r in compilation.References.OfType<PortableExecutableReference>())
{
AnalyseAssembly(r);
AnalyseReferenceAssembly(r);
}
}

View File

@@ -1,82 +1,134 @@
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class Attribute : FreshEntity, IExpressionParentEntity
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
{
bool IExpressionParentEntity.IsTopLevelParent => true;
private readonly AttributeData attribute;
private readonly AttributeSyntax attributeSyntax;
private readonly IEntity entity;
public Attribute(Context cx, AttributeData attribute, IEntity entity)
: base(cx)
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
: base(cx, attributeData)
{
this.attribute = attribute;
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
this.entity = entity;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
public override void WriteId(TextWriter trapFile)
{
if (attribute.ApplicationSyntaxReference != null)
if (ReportingLocation?.IsInSource == true)
{
// !! Extract attributes from assemblies.
// This is harder because the "expression" entities presume the
// existence of a syntax tree. This is not the case for compiled
// attributes.
var syntax = attribute.ApplicationSyntaxReference.GetSyntax() as AttributeSyntax;
ExtractAttribute(cx.TrapWriter.Writer, syntax, attribute.AttributeClass, entity);
trapFile.WriteSubId(Location);
trapFile.Write(";attribute");
}
else
{
trapFile.Write('*');
}
}
public Attribute(Context cx, AttributeSyntax attribute, IEntity entity)
: base(cx)
public override void WriteQuotedId(TextWriter trapFile)
{
var info = cx.GetSymbolInfo(attribute);
ExtractAttribute(cx.TrapWriter.Writer, attribute, info.Symbol.ContainingType, entity);
if (ReportingLocation?.IsInSource == true)
{
base.WriteQuotedId(trapFile);
}
else
{
trapFile.Write('*');
}
}
private void ExtractAttribute(System.IO.TextWriter trapFile, AttributeSyntax syntax, ITypeSymbol attributeClass, IEntity entity)
public override void Populate(TextWriter trapFile)
{
var type = Type.Create(cx, attributeClass);
var type = Type.Create(Context, symbol.AttributeClass);
trapFile.attributes(this, type.TypeRef, entity);
trapFile.attribute_location(this, Location);
trapFile.attribute_location(this, cx.Create(syntax.Name.GetLocation()));
if (cx.Extractor.OutputPath != null)
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(cx));
TypeMention.Create(cx, syntax.Name, this, type);
if (syntax.ArgumentList != null)
if (attributeSyntax is object)
{
cx.PopulateLater(() =>
if (Context.Extractor.OutputPath != null)
{
var child = 0;
foreach (var arg in syntax.ArgumentList.Arguments)
{
var expr = Expression.Create(cx, arg.Expression, this, child++);
if (!(arg.NameEquals is null))
{
trapFile.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text);
}
}
});
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
}
TypeMention.Create(Context, attributeSyntax.Name, this, type);
}
ExtractArguments(trapFile);
}
private void ExtractArguments(TextWriter trapFile)
{
var childIndex = 0;
foreach (var constructorArgument in symbol.ConstructorArguments)
{
CreateExpressionFromArgument(
constructorArgument,
attributeSyntax?.ArgumentList.Arguments[childIndex].Expression,
this,
childIndex++);
}
foreach (var namedArgument in symbol.NamedArguments)
{
var expr = CreateExpressionFromArgument(
namedArgument.Value,
attributeSyntax?.ArgumentList.Arguments.Single(a => a.NameEquals?.Name?.Identifier.Text == namedArgument.Key).Expression,
this,
childIndex++);
if (expr is object)
{
trapFile.expr_argument_name(expr, namedArgument.Key);
}
}
}
private Expression CreateExpressionFromArgument(TypedConstant constant, ExpressionSyntax syntax, IExpressionParentEntity parent,
int childIndex)
{
return syntax is null
? Expression.CreateGenerated(Context, constant, parent, childIndex, Location)
: Expression.Create(Context, syntax, parent, childIndex);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
public override Microsoft.CodeAnalysis.Location ReportingLocation => attributeSyntax?.Name.GetLocation();
private Semmle.Extraction.Entities.Location location;
private Semmle.Extraction.Entities.Location Location =>
location ?? (location = Semmle.Extraction.Entities.Location.Create(Context, attributeSyntax is null ? entity.ReportingLocation : attributeSyntax.Name.GetLocation()));
public override bool NeedsPopulation => true;
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
{
foreach (var attribute in symbol.GetAttributes())
{
new Attribute(cx, attribute, entity);
Create(cx, attribute, entity);
}
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
{
var init = (attributeData, entity);
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
}
private class AttributeFactory : ICachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>
{
public static readonly AttributeFactory Instance = new AttributeFactory();
public Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver) init) =>
new Attribute(cx, init.attributeData, init.receiver);
}
}
}

View File

@@ -1,9 +1,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System;
using System.IO;
using System.Linq;
@@ -125,6 +127,42 @@ namespace Semmle.Extraction.CSharp.Entities
private static bool ContainsPattern(SyntaxNode node) =>
node is PatternSyntax || node is VariableDesignationSyntax || node.ChildNodes().Any(ContainsPattern);
/// <summary>
/// Creates a generated expression from a typed constant.
/// </summary>
public static Expression CreateGenerated(Context cx, TypedConstant constant, IExpressionParentEntity parent,
int childIndex, Semmle.Extraction.Entities.Location location)
{
if (constant.IsNull)
{
return Literal.CreateGeneratedNullLiteral(cx, parent, childIndex, location);
}
switch (constant.Kind)
{
case TypedConstantKind.Primitive:
return Literal.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, location);
case TypedConstantKind.Enum:
// Enum value is generated in the following format: (Enum)value
Action<Expression, int> createChild = (parent, index) => Literal.CreateGenerated(cx, parent, index, ((INamedTypeSymbol)constant.Type).EnumUnderlyingType, constant.Value, location);
var cast = Cast.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, createChild, location);
return cast;
case TypedConstantKind.Type:
var type = ((ITypeSymbol)constant.Value).OriginalDefinition;
return TypeOf.CreateGenerated(cx, parent, childIndex, type, location);
case TypedConstantKind.Array:
// Single dimensional arrays are in the following format:
// * new Type[N] { item1, item2, ..., itemN }
// * new Type[0]
//
// itemI is generated recursively.
return NormalArrayCreation.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Values, location);
default:
cx.ExtractionError("Couldn't extract constant in attribute", constant.ToString(), location);
return null;
}
}
/// <summary>
/// Adapt the operator kind depending on whether it's a dynamic call or a user-operator call.
/// </summary>

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -10,6 +11,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
internal abstract class ArrayCreation<TSyntaxNode> : Expression<TSyntaxNode>
where TSyntaxNode : ExpressionSyntax
{
protected const int InitializerIndex = -1;
protected ArrayCreation(ExpressionNodeInfo info) : base(info) { }
}
@@ -48,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (!(Initializer is null))
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, InitializerIndex));
}
if (explicitlySized)
@@ -66,17 +69,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return;
}
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
Location,
ExprKind.INT_LITERAL,
this,
level,
true,
initializer.Expressions.Count.ToString());
new Expression(info);
Literal.CreateGenerated(cx, this, level, cx.Compilation.GetSpecialType(SpecialType.System_Int32), initializer.Expressions.Count, Location);
initializer = initializer.Expressions.FirstOrDefault() as InitializerExpressionSyntax;
}
@@ -92,6 +85,37 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public override InitializerExpressionSyntax Initializer => Syntax.Initializer;
public static Expression Create(ExpressionNodeInfo info) => new NormalArrayCreation(info).TryPopulate();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, IEnumerable<TypedConstant> items, Semmle.Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
location,
ExprKind.ARRAY_CREATION,
parent,
childIndex,
true,
null);
var arrayCreation = new Expression(info);
var length = items.Count();
Literal.CreateGenerated(cx, arrayCreation, 0, cx.Compilation.GetSpecialType(SpecialType.System_Int32), length, location);
if (length > 0)
{
var arrayInit = ArrayInitializer.CreateGenerated(cx, arrayCreation, InitializerIndex, location);
var child = 0;
foreach (var item in items)
{
Expression.CreateGenerated(cx, item, arrayInit, child++, location);
}
}
return arrayCreation;
}
}
internal class StackAllocArrayCreation : ExplicitArrayCreation<StackAllocArrayCreationExpressionSyntax>
@@ -119,7 +143,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
protected override void PopulateExpression(TextWriter trapFile)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
trapFile.implicitly_typed_array_creation(this);
trapFile.stackalloc_array_creation(this);
}
@@ -135,7 +159,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
if (Syntax.Initializer != null)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
}
trapFile.implicitly_typed_array_creation(this);

View File

@@ -1,22 +1,26 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class Cast : Expression<CastExpressionSyntax>
{
private const int ExpressionIndex = 0;
private const int TypeAccessIndex = 1;
private Cast(ExpressionNodeInfo info) : base(info.SetKind(UnaryOperatorKind(info.Context, ExprKind.CAST, info.Node))) { }
public static Expression Create(ExpressionNodeInfo info) => new Cast(info).TryPopulate();
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
Create(cx, Syntax.Expression, this, ExpressionIndex);
if (Kind == ExprKind.CAST)
{ // Type cast
TypeAccess.Create(new ExpressionNodeInfo(cx, Syntax.Type, this, 1));
TypeAccess.Create(new ExpressionNodeInfo(cx, Syntax.Type, this, TypeAccessIndex));
}
else
{
@@ -27,5 +31,26 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => Syntax.GetLocation();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, object value, Action<Expression, int> createChild, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.CAST,
parent,
childIndex,
true,
ValueAsString(value));
var ret = new Expression(info);
createChild(ret, ExpressionIndex);
TypeAccess.CreateGenerated(cx, ret, TypeAccessIndex, type, location);
return ret;
}
}
}

View File

@@ -35,6 +35,21 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
}
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int index, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
location,
ExprKind.ARRAY_INIT,
parent,
index,
true,
null);
return new Expression(info);
}
}
// Array initializer { ..., ... }.

View File

@@ -26,8 +26,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
var type = info.Type.Type.symbol;
return GetExprKind(type, info.Node, info.Context);
}
switch (type.SpecialType)
private static ExprKind GetExprKind(ITypeSymbol type, ExpressionSyntax expr, Context context)
{
switch (type?.SpecialType)
{
case SpecialType.System_Boolean:
return ExprKind.BOOL_LITERAL;
@@ -63,10 +67,45 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SpecialType.System_UInt64:
return ExprKind.ULONG_LITERAL;
case null:
default:
info.Context.ModelError(info.Node, "Unhandled literal type");
if (expr is object)
context.ModelError(expr, "Unhandled literal type");
else
context.ModelError("Unhandled literal type");
return ExprKind.UNKNOWN;
}
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object value,
Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
location,
GetExprKind(type, null, cx),
parent,
childIndex,
true,
ValueAsString(value));
return new Expression(info);
}
public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParentEntity parent, int childIndex, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
location,
ExprKind.NULL_LITERAL,
parent,
childIndex,
true,
ValueAsString(null));
return new Expression(info);
}
}
}

View File

@@ -34,5 +34,20 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
public static Expression Create(ExpressionNodeInfo info) => new TypeAccess(info).TryPopulate();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, Extraction.Entities.Location location)
{
var typeAccessInfo = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.TYPE_ACCESS,
parent,
childIndex,
true,
null);
return new Expression(typeAccessInfo);
}
}
}

View File

@@ -6,13 +6,34 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class TypeOf : Expression<TypeOfExpressionSyntax>
{
private const int TypeAccessIndex = 0;
private TypeOf(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.TYPEOF)) { }
public static Expression Create(ExpressionNodeInfo info) => new TypeOf(info).TryPopulate();
protected override void PopulateExpression(TextWriter trapFile)
{
TypeAccess.Create(cx, Syntax.Type, this, 0);
TypeAccess.Create(cx, Syntax.Type, this, TypeAccessIndex);
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.TYPEOF,
parent,
childIndex,
true,
null);
var ret = new Expression(info);
TypeAccess.CreateGenerated(cx, ret, TypeOf.TypeAccessIndex, type, location);
return ret;
}
}
}

View File

@@ -3,8 +3,12 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities;
using Semmle.Extraction.Entities;
using Semmle.Util;
using Semmle.Util.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Populators
{
@@ -13,12 +17,23 @@ namespace Semmle.Extraction.CSharp.Populators
protected Context cx { get; }
protected IEntity parent { get; }
protected TextWriter trapFile { get; }
private readonly Lazy<Func<SyntaxNode, AttributeData>> attributeLookup;
public TypeContainerVisitor(Context cx, TextWriter trapFile, IEntity parent)
{
this.cx = cx;
this.parent = parent;
this.trapFile = trapFile;
attributeLookup = new Lazy<Func<SyntaxNode, AttributeData>>(() =>
{
var dict = new Dictionary<SyntaxNode, AttributeData>();
foreach (var attributeData in cx.Compilation.Assembly.GetAttributes().Concat(cx.Compilation.Assembly.Modules.SelectMany(m => m.GetAttributes())))
{
if (attributeData.ApplicationSyntaxReference?.GetSyntax() is SyntaxNode syntax)
dict.Add(syntax, attributeData);
}
return dict.GetValueOrDefault;
});
}
public override void DefaultVisit(SyntaxNode node)
@@ -59,8 +74,11 @@ namespace Semmle.Extraction.CSharp.Populators
var outputAssembly = Assembly.CreateOutputAssembly(cx);
foreach (var attribute in node.Attributes)
{
var ae = new Attribute(cx, attribute, outputAssembly);
cx.BindComments(ae, attribute.GetLocation());
if (attributeLookup.Value(attribute) is AttributeData attributeData)
{
var ae = Semmle.Extraction.CSharp.Entities.Attribute.Create(cx, attributeData, outputAssembly);
cx.BindComments(ae, attribute.GetLocation());
}
}
}
}

View File

@@ -0,0 +1,22 @@
/**
* Provides shared predicates related to contextual queries in the code viewer.
*/
import semmle.files.FileSystem
/**
* Returns the `File` matching the given source file name as encoded by the VS
* Code extension.
*/
cached
File getFileBySourceArchiveName(string name) {
// The name provided for a file in the source archive by the VS Code extension
// has some differences from the absolute path in the database:
// 1. colons are replaced by underscores
// 2. there's a leading slash, even for Windows paths: "C:/foo/bar" ->
// "/C_/foo/bar"
// 3. double slashes in UNC prefixes are replaced with a single slash
// We can handle 2 and 3 together by unconditionally adding a leading slash
// before replacing double slashes.
name = ("/" + result.getAbsolutePath().replaceAll(":", "_")).replaceAll("//", "/")
}

View File

@@ -4,6 +4,7 @@
*/
import csharp
import IDEContextual
/** An element with an associated definition. */
abstract class Use extends @type_mention_parent {
@@ -188,11 +189,3 @@ Declaration definitionOf(Use use, string kind) {
result.fromSource() and
kind = use.getUseType()
}
/**
* Returns an appropriately encoded version of a filename `name`
* passed by the VS Code extension in order to coincide with the
* output of `.getFile()` on locatable entities.
*/
cached
File getEncodedFile(string name) { result.getAbsolutePath().replaceAll(":", "_") = name }

View File

@@ -15,5 +15,5 @@ from Use e, Declaration def, string kind, string filepath
where
def = definitionOf(e, kind) and
e.hasLocationInfo(filepath, _, _, _, _) and
filepath = getEncodedFile(selectedSourceFile()).getAbsolutePath()
filepath = getFileBySourceArchiveName(selectedSourceFile()).getAbsolutePath()
select e, def, kind

View File

@@ -12,5 +12,6 @@ import definitions
external string selectedSourceFile();
from Use e, Declaration def, string kind
where def = definitionOf(e, kind) and def.getFile() = getEncodedFile(selectedSourceFile())
where
def = definitionOf(e, kind) and def.getFile() = getFileBySourceArchiveName(selectedSourceFile())
select e, def, kind

View File

@@ -23,6 +23,6 @@ class PrintAstConfigurationOverride extends PrintAstConfiguration {
*/
override predicate shouldPrint(Element e, Location l) {
super.shouldPrint(e, l) and
l.getFile() = getEncodedFile(selectedSourceFile())
l.getFile() = getFileBySourceArchiveName(selectedSourceFile())
}
}

View File

@@ -135,7 +135,7 @@ private newtype TPrintAstNode =
} or
TAttributesNode(Attributable attributable) {
shouldPrint(attributable, _) and
exists(attributable.getAnAttribute()) and
exists(Attribute a | a = attributable.getAnAttribute() | shouldPrint(a, _)) and
not isNotNeeded(attributable)
} or
TTypeParametersNode(UnboundGeneric unboundGeneric) {
@@ -298,7 +298,10 @@ class ControlFlowElementNode extends ElementNode {
controlFlowElement.getParent*()
)
) and
not isNotNeeded(element.getParent+())
not isNotNeeded(element.getParent+()) and
// LambdaExpr is both a Callable and a ControlFlowElement,
// print it with the more specific CallableNode
not element instanceof Callable
}
override PrintAstNode getChild(int childIndex) {

View File

@@ -7,6 +7,30 @@ private import semmle.code.csharp.frameworks.System
private import ControlFlow
private import ControlFlow::BasicBlocks
private newtype TAssertionFailure =
TExceptionAssertionFailure(Class c) or
TExitAssertionFailure()
/** An entity that describes how an assertion may fail. */
class AssertionFailure extends TAssertionFailure {
/** Holds if this failure describes an exception of type `c`. */
predicate isException(Class c) { this = TExceptionAssertionFailure(c) }
/** Holds if this failure describes an exit. */
predicate isExit() { this = TExitAssertionFailure() }
/** Gets a textual representation of this element. */
string toString() {
exists(Class c |
this = TExceptionAssertionFailure(c) and
result = c.toString()
)
or
this = TExitAssertionFailure() and
result = "exit"
}
}
/** An assertion method. */
abstract class AssertMethod extends Method {
/** Gets the index of a parameter being asserted. */
@@ -32,15 +56,15 @@ abstract class AssertMethod extends Method {
*/
deprecated final Parameter getAssertedParameter() { result = getAssertedParameter(_) }
/** Gets the exception being thrown if the assertion fails for argument `i`, if any. */
abstract Class getExceptionClass(int i);
/** Gets the failure type if the assertion fails for argument `i`, if any. */
abstract AssertionFailure getAssertionFailure(int i);
/**
* DEPRECATED: Use `getExceptionClass(_)` instead.
* DEPRECATED: Use `getAssertionFailure(_)` instead.
*
* Gets the exception being thrown if the assertion fails, if any.
*/
deprecated final Class getExceptionClass() { result = this.getExceptionClass(_) }
deprecated final Class getExceptionClass() { this.getAssertionFailure(_).isException(result) }
}
/** A Boolean assertion method. */
@@ -62,7 +86,7 @@ deprecated class AssertTrueMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A negated assertion method. */
@@ -76,7 +100,7 @@ deprecated class AssertFalseMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A nullness assertion method. */
@@ -101,7 +125,7 @@ deprecated class AssertNullMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A non-`null` assertion method. */
@@ -115,7 +139,7 @@ deprecated class AssertNonNullMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** An assertion, that is, a call to an assertion method. */
@@ -258,7 +282,7 @@ class FailingAssertion extends Assertion {
}
/** Gets the exception being thrown by this failing assertion, if any. */
Class getExceptionClass() { result = this.getAssertMethod().getExceptionClass(i) }
AssertionFailure getAssertionFailure() { result = this.getAssertMethod().getAssertionFailure(i) }
}
/**
@@ -271,10 +295,10 @@ class SystemDiagnosticsDebugAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
// A failing assertion generates a message box, see
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debug.assert
none()
i = 0 and result.isExit()
}
}
@@ -294,10 +318,10 @@ class SystemDiagnosticsContractAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
// A failing assertion generates a message box, see
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.contract.assert
none()
i = 0 and result.isExit()
}
}
@@ -321,7 +345,9 @@ class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod exte
override int getAnAssertionIndex(boolean b) { result = i_ and b = true }
override Class getExceptionClass(int i) { i = i_ and result instanceof SystemExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = i_ and result.isException(any(SystemExceptionClass c))
}
}
/**
@@ -340,7 +366,9 @@ class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertFalseMethod ext
b = false
}
override Class getExceptionClass(int i) { i = i_ and result instanceof SystemExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = i_ and result.isException(any(SystemExceptionClass c))
}
}
/** A Visual Studio assertion method. */
@@ -349,7 +377,9 @@ class VSTestAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio negated assertion method. */
@@ -358,7 +388,9 @@ class VSTestAssertFalseMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = false }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio `null` assertion method. */
@@ -367,7 +399,9 @@ class VSTestAssertNullMethod extends NullnessAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio non-`null` assertion method. */
@@ -376,14 +410,18 @@ class VSTestAssertNonNullMethod extends NullnessAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = false }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** An NUnit assertion method. */
abstract class NUnitAssertMethod extends AssertMethod {
override int getAnAssertionIndex() { result = 0 }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertionExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertionExceptionClass c))
}
}
/** An NUnit assertion method. */
@@ -466,9 +504,9 @@ class ForwarderAssertMethod extends AssertMethod {
/** Gets the assertion index of the forwarded assertion, for assertion index `i`. */
int getAForwarderAssertionIndex(int i) { i = p.getPosition() and result = forwarderIndex }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
i = p.getPosition() and
result = this.getUnderlyingAssertMethod().getExceptionClass(forwarderIndex)
result = this.getUnderlyingAssertMethod().getAssertionFailure(forwarderIndex)
}
/** Gets the underlying assertion method that is being forwarded to. */
@@ -507,8 +545,8 @@ class ForwarderBooleanAssertMethod extends BooleanAssertMethod {
forwarder.getAForwarderAssertionIndex(result) = underlying.getAnAssertionIndex(b)
}
override Class getExceptionClass(int i) {
result = underlying.getExceptionClass(forwarder.getAForwarderAssertionIndex(i))
override AssertionFailure getAssertionFailure(int i) {
result = underlying.getAssertionFailure(forwarder.getAForwarderAssertionIndex(i))
}
}
@@ -536,8 +574,8 @@ class ForwarderNullnessAssertMethod extends NullnessAssertMethod {
forwarder.getAForwarderAssertionIndex(result) = underlying.getAnAssertionIndex(b)
}
override Class getExceptionClass(int i) {
result = underlying.getExceptionClass(forwarder.getAForwarderAssertionIndex(i))
override AssertionFailure getAssertionFailure(int i) {
result = underlying.getAssertionFailure(forwarder.getAForwarderAssertionIndex(i))
}
}

View File

@@ -393,11 +393,13 @@ private predicate assertion(Assertion a, int i, AssertMethod am, Expr e) {
/** Gets a valid completion when argument `i` fails in assertion `a`. */
Completion assertionCompletion(Assertion a, int i) {
exists(AssertMethod am | am = a.getAssertMethod() |
result = TThrowCompletion(am.getExceptionClass(i))
or
i = am.getAnAssertionIndex() and
not exists(am.getExceptionClass(i)) and
result = TExitCompletion()
if am.getAssertionFailure(i).isExit()
then result = TExitCompletion()
else
exists(Class c |
am.getAssertionFailure(i).isException(c) and
result = TThrowCompletion(c)
)
)
}

View File

@@ -23,7 +23,7 @@ private class ExitingCall extends NonReturningCall {
ExitingCall() {
this.getTarget() instanceof ExitingCallable
or
this = any(FailingAssertion fa | not exists(fa.getExceptionClass()))
this = any(FailingAssertion fa | fa.getAssertionFailure().isExit())
}
override ExitCompletion getACompletion() { not result instanceof NestedCompletion }
@@ -37,7 +37,7 @@ private class ThrowingCall extends NonReturningCall {
(
c = this.getTarget().(ThrowingCallable).getACallCompletion()
or
c.getExceptionClass() = this.(FailingAssertion).getExceptionClass()
this.(FailingAssertion).getAssertionFailure().isException(c.getExceptionClass())
or
exists(CIL::Method m, CIL::Type ex |
this.getTarget().matchesHandle(m) and

View File

@@ -1462,7 +1462,11 @@ predicate succEntrySplits(
exists(int rnk |
succ = succEntry(pred) and
t instanceof NormalSuccessor and
succEntrySplitsFromRank(pred, succ, succSplits, rnk)
succEntrySplitsFromRank(pred, succ, succSplits, rnk) and
// Attribute arguments in assemblies are represented as expressions, even though
// they are not from source. We are not interested in constructing a CFG for such
// expressions.
succ.fromSource()
|
rnk = 0 and
not any(SplitInternal split).hasEntry(pred, succ)

View File

@@ -8,6 +8,7 @@ private import internal.FlowSummarySpecific::Private
private import internal.DataFlowPublic as DataFlowPublic
// import all instances below
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
private import semmle.code.csharp.frameworks.EntityFramework
class SummarizableCallable = Impl::Public::SummarizableCallable;
@@ -135,6 +136,17 @@ module SummaryOutput {
result = TDelegateSummaryOutput(i, j) and
hasDelegateArgumentPosition2(c, i, j)
}
/**
* Gets an output specification that specifies the `output` of `target` as the
* output. That is, data will flow into one callable and out of another callable
* (`target`).
*
* `output` is limited to (this) parameters and ordinary returns.
*/
SummaryOutput jump(SummarizableCallable target, SummaryOutput output) {
result = TJumpSummaryOutput(target, toReturnKind(output))
}
}
class SummarizedCallable = Impl::Public::SummarizedCallable;

View File

@@ -1751,8 +1751,10 @@ class SystemTupleFlow extends LibraryTypeDataFlow, ValueOrRefType {
result =
unique(AccessPath ap |
i in [1 .. count(this.getAMember())] and
ap in [AccessPath::field(this.getField("Item" + i)),
AccessPath::property(this.getProperty("Item" + i))]
ap in [
AccessPath::field(this.getField("Item" + i)),
AccessPath::property(this.getProperty("Item" + i))
]
|
ap
)

View File

@@ -21,6 +21,9 @@ DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
result = sourceDecl and
result instanceof SummarizedCallable
or
result = sourceDecl and
FlowSummaryImpl::Private::summary(_, _, _, SummaryOutput::jump(result, _), _, _)
or
result.hasBody() and
if sourceDecl.getFile().fromSource()
then

View File

@@ -382,7 +382,10 @@ private predicate isParamsArg(Call c, Expr arg, Parameter p) {
p.isParams() and
numArgs = c.getNumberOfArguments() and
arg =
[getImplicitArgument(c, [p.getPosition() .. numArgs - 1]), getExplicitArgument(c, p.getName())]
[
getImplicitArgument(c, [p.getPosition() .. numArgs - 1]),
getExplicitArgument(c, p.getName())
]
|
numArgs > target.getNumberOfParameters()
or
@@ -469,12 +472,9 @@ private predicate overridesOrImplementsSourceDecl(Property p1, Property p2) {
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(ContentList cl, Property target |
FlowSummaryImpl::Private::summary(_, _, _, _, cl, _) and
cl.contains(ret.getContent()) and
exists(Property target |
target.getGetter() = e2.(PropertyCall).getARuntimeTarget() and
overridesOrImplementsSourceDecl(target, ret)
)
@@ -640,6 +640,10 @@ private module Cached {
output = SummaryOutput::delegate(delegateIndex, parameterIndex)
)
} or
TSummaryJumpNode(SummarizedCallable c, SummarizableCallable target, ReturnKind rk) {
FlowSummaryImpl::Private::summary(c, _, _,
FlowSummarySpecific::Private::TJumpSummaryOutput(target, rk), _, _)
} or
TParamsArgumentNode(ControlFlow::Node callCfn) {
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
}
@@ -685,8 +689,19 @@ private module Cached {
* taken into account.
*/
cached
predicate jumpStepImpl(ExprNode pred, ExprNode succ) {
predicate jumpStepImpl(Node pred, Node succ) {
pred.(NonLocalJumpNode).getAJumpSuccessor(true) = succ
or
exists(FieldOrProperty fl, FieldOrPropertyRead flr |
fl.isStatic() and
fl.isFieldLike() and
fl.getAnAssignedValue() = pred.asExpr() and
fl.getAnAccess() = flr and
flr = succ.asExpr() and
flr.hasNonlocalValue()
)
or
succ = pred.(SummaryJumpNode).getAJumpTarget()
}
cached
@@ -1613,6 +1628,28 @@ private class SummaryInternalNode extends SummaryNodeImpl, TSummaryInternalNode
override string toStringImpl() { result = "[summary] " + state + " in " + c }
}
/** A data-flow node used to model flow summaries with jumps. */
private class SummaryJumpNode extends SummaryNodeImpl, TSummaryJumpNode {
private SummarizedCallable c;
private SummarizableCallable target;
private ReturnKind rk;
SummaryJumpNode() { this = TSummaryJumpNode(c, target, rk) }
/** Gets a jump target of this node. */
OutNode getAJumpTarget() { target = viableCallable(result.getCall(rk)) }
override Callable getEnclosingCallableImpl() { result = c }
override DotNet::Type getTypeImpl() { result = target.getReturnType() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override Location getLocationImpl() { result = c.getLocation() }
override string toStringImpl() { result = "[summary] jump to " + target }
}
/** A field or a property. */
class FieldOrProperty extends Assignable, Modifiable {
FieldOrProperty() {
@@ -1669,26 +1706,6 @@ private class FieldOrPropertyRead extends FieldOrPropertyAccess, AssignableRead
}
}
/** A write to a static field/property. */
private class StaticFieldLikeJumpNode extends NonLocalJumpNode, ExprNode {
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
flr.hasNonlocalValue()
}
override ExprNode getAJumpSuccessor(boolean preservesValue) {
result = succ and preservesValue = true
}
}
predicate jumpStep = jumpStepImpl/2;
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {

View File

@@ -4,13 +4,13 @@
private import csharp
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import DataFlowDispatch
module Private {
private import Public
private import DataFlowPrivate as DataFlowPrivate
private import DataFlowPublic as DataFlowPublic
private import FlowSummaryImpl as Impl
private import DataFlowDispatch
private import semmle.code.csharp.Unification
class Content = DataFlowPublic::Content;
@@ -56,7 +56,19 @@ module Private {
TParameterSummaryOutput(int i) {
i in [-1, any(SummarizableCallable c).getAParameter().getPosition()]
} or
TDelegateSummaryOutput(int i, int j) { hasDelegateArgumentPosition2(_, i, j) }
TDelegateSummaryOutput(int i, int j) { hasDelegateArgumentPosition2(_, i, j) } or
TJumpSummaryOutput(SummarizableCallable target, ReturnKind rk) {
rk instanceof NormalReturnKind and
(
target instanceof Constructor or
not target.getReturnType() instanceof VoidType
)
or
rk instanceof QualifierReturnKind and
not target.(Modifiable).isStatic()
or
exists(target.getParameter(rk.(OutRefReturnKind).getPosition()))
}
/** Gets the return kind that matches `sink`, if any. */
ReturnKind toReturnKind(SummaryOutput output) {
@@ -92,6 +104,11 @@ module Private {
output = TDelegateSummaryOutput(i, j) and
result = DataFlowPrivate::TSummaryDelegateArgumentNode(c, i, j)
)
or
exists(SummarizableCallable target, ReturnKind rk |
output = TJumpSummaryOutput(target, rk) and
result = DataFlowPrivate::TSummaryJumpNode(c, target, rk)
)
}
/** Gets the internal summary node for the given values. */
@@ -151,6 +168,11 @@ module Public {
this = TDelegateSummaryOutput(delegateIndex, parameterIndex) and
result = "parameter " + parameterIndex + " of delegate parameter " + delegateIndex
)
or
exists(SummarizableCallable target, ReturnKind rk |
this = TJumpSummaryOutput(target, rk) and
result = "jump to " + target + " (" + rk + ")"
)
}
}
}

View File

@@ -160,8 +160,9 @@ private module Impl {
/** Returned an expression that is assigned to `f`. */
ExprNode getAssignedValueToField(Field f) {
result.getExpr() in [f.getAnAssignedValue(),
any(AssignOperation a | a.getLValue() = f.getAnAccess())]
result.getExpr() in [
f.getAnAssignedValue(), any(AssignOperation a | a.getLValue() = f.getAnAccess())
]
}
/** Holds if `f` can have any sign. */

View File

@@ -3,17 +3,19 @@
*/
import csharp
private import DataFlow
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.data.Entity
private import semmle.code.csharp.frameworks.system.collections.Generic
private import semmle.code.csharp.frameworks.Sql
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
private import semmle.code.csharp.dataflow.FlowSummary
/**
* Definitions relating to the `System.ComponentModel.DataAnnotations`
* namespace.
*/
module DataAnnotations {
/** Class for `NotMappedAttribute`. */
/** The `NotMappedAttribute` attribute. */
class NotMappedAttribute extends Attribute {
NotMappedAttribute() {
this
@@ -23,6 +25,11 @@ module DataAnnotations {
}
}
/** Holds if `a` has the `[NotMapped]` attribute */
private predicate isNotMapped(Attributable a) {
a.getAnAttribute() instanceof DataAnnotations::NotMappedAttribute
}
/**
* Definitions relating to the `Microsoft.EntityFrameworkCore` or
* `System.Data.Entity` namespaces.
@@ -66,6 +73,41 @@ module EntityFramework {
/** The class `Microsoft.EntityFrameworkCore.DbSet<>` or `System.Data.Entity.DbSet<>`. */
class DbSet extends EFClass, UnboundGenericClass {
DbSet() { this.getName() = "DbSet<>" }
/** Gets a method that adds or updates entities in a DB set. */
SummarizableMethod getAnAddOrUpdateMethod(boolean range) {
exists(string name | result = this.getAMethod(name) |
name in ["Add", "AddAsync", "Attach", "Update"] and
range = false
or
name in ["AddRange", "AddRangeAsync", "AttachRange", "UpdateRange"] and
range = true
)
}
}
/** A flow summary for EntityFramework. */
abstract class EFSummarizedCallable extends SummarizedCallable { }
private class DbSetAddOrUpdate extends EFSummarizedCallable {
private boolean range;
DbSetAddOrUpdate() { this = any(DbSet c).getAnAddOrUpdateMethod(range) }
override predicate propagatesFlow(
SummaryInput input, ContentList inputContents, SummaryOutput output,
ContentList outputContents, boolean preservesValue
) {
input = SummaryInput::parameter(0) and
(
if range = true
then inputContents = ContentList::element()
else inputContents = ContentList::empty()
) and
output = SummaryOutput::thisParameter() and
outputContents = ContentList::element() and
preservesValue = true
}
}
/** The class `Microsoft.EntityFrameworkCore.DbQuery<>` or `System.Data.Entity.DbQuery<>`. */
@@ -107,29 +149,14 @@ module EntityFramework {
MappedProperty() {
this = any(MappedType t).getAMember() and
this.isPublic() and
not this.getAnAttribute() instanceof DataAnnotations::NotMappedAttribute
not isNotMapped(this)
}
}
/** The struct `Microsoft.EntityFrameworkCore.RawSqlString`. */
class RawSqlStringStruct extends Struct, LibraryTypeDataFlow {
private class RawSqlStringStruct extends Struct {
RawSqlStringStruct() { this.getQualifiedName() = "Microsoft.EntityFrameworkCore.RawSqlString" }
override predicate callableFlow(
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
boolean preservesValue
) {
c = this.getAConstructor() and
source.(CallableFlowSourceArg).getArgumentIndex() = 0 and
sink instanceof CallableFlowSinkReturn and
preservesValue = false
or
c = this.getAConversionTo() and
source.(CallableFlowSourceArg).getArgumentIndex() = 0 and
sink instanceof CallableFlowSinkReturn and
preservesValue = false
}
/** Gets a conversion operator from `string` to `RawSqlString`. */
ConversionOperator getAConversionTo() {
result = this.getAMember() and
@@ -138,6 +165,35 @@ module EntityFramework {
}
}
private class RawSqlStringSummarizedCallable extends EFSummarizedCallable {
private SummaryInput input_;
private SummaryOutput output_;
private boolean preservesValue_;
RawSqlStringSummarizedCallable() {
exists(RawSqlStringStruct s |
this = s.getAConstructor() and
input_ = SummaryInput::parameter(0) and
this.getNumberOfParameters() > 0 and
output_ = SummaryOutput::return() and
preservesValue_ = false
or
this = s.getAConversionTo() and
input_ = SummaryInput::parameter(0) and
output_ = SummaryOutput::return() and
preservesValue_ = false
)
}
override predicate propagatesFlow(
SummaryInput input, SummaryOutput output, boolean preservesValue
) {
input = input_ and
output = output_ and
preservesValue = preservesValue_
}
}
/**
* A parameter that accepts raw SQL. Parameters of type `System.FormattableString`
* are not included as they are not vulnerable to SQL injection.
@@ -192,18 +248,183 @@ module EntityFramework {
override Expr getSql() { result = this.getArgumentForName("sql") }
}
/**
* A dataflow node whereby data flows from a property write to a property read
* via some database. The assumption is that all writes can flow to all reads.
*/
class MappedPropertyJumpNode extends DataFlow::NonLocalJumpNode {
MappedProperty property;
/** Holds if `t` is compatible with a DB column type. */
private predicate isColumnType(Type t) {
t instanceof SimpleType
or
t instanceof StringType
or
t instanceof Enum
or
t instanceof SystemDateTimeStruct
or
isColumnType(t.(NullableType).getUnderlyingType())
}
MappedPropertyJumpNode() { this.asExpr() = property.getAnAssignedValue() }
/** A DB Context. */
private class DbContextClass extends Class {
DbContextClass() { this.getBaseClass*().getSourceDeclaration() instanceof DbContext }
override DataFlow::Node getAJumpSuccessor(boolean preservesValue) {
result.asExpr().(PropertyRead).getTarget() = property and
preservesValue = false
/**
* Gets a `DbSet<elementType>` property belonging to this DB context.
*
* For example `Persons` with `elementType = Person` in
*
* ```csharp
* class MyContext : DbContext
* {
* public virtual DbSet<Person> Persons { get; set; }
* public virtual DbSet<Address> Addresses { get; set; }
* }
* ```
*/
private Property getADbSetProperty(Class elementType) {
exists(ConstructedClass c |
result.getType() = c and
c.getSourceDeclaration() instanceof DbSet and
elementType = c.getTypeArgument(0) and
this.hasMember(any(Property p | result = p.getSourceDeclaration())) and
not isNotMapped([result.(Attributable), elementType])
)
}
/**
* Holds if `[c2, c1]` is part of a valid access path starting from a `DbSet<T>`
* property belonging to this DB context. `t1` is the type of `c1` and `t2` is
* the type of `c2`.
*
* If `t2` is a column type, `c2` will be included in the model (see
* https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations).
*/
private predicate step(Content c1, Type t1, Content c2, Type t2) {
exists(Property p1 |
p1 = this.getADbSetProperty(t2) and
c1.(PropertyContent).getProperty() = p1 and
t1 = p1.getType() and
c2 instanceof ElementContent
)
or
step(_, _, c1, t1) and
not isNotMapped(t2) and
(
// Navigation property (https://docs.microsoft.com/en-us/ef/ef6/fundamentals/relationships)
exists(Property p2 |
p2.getDeclaringType().(Class) = t1 and
not isColumnType(t1) and
c2.(PropertyContent).getProperty() = p2 and
t2 = p2.getType() and
not isNotMapped(p2)
)
or
exists(ConstructedInterface ci |
c1 instanceof PropertyContent and
t1.(ValueOrRefType).getABaseType*() = ci and
not t1 instanceof StringType and
ci.getSourceDeclaration() instanceof SystemCollectionsGenericIEnumerableTInterface and
c2 instanceof ElementContent and
t2 = ci.getTypeArgument(0)
)
)
}
/**
* Gets a property belonging to the model of this DB context, which is mapped
* directly to a column in the underlying DB.
*
* For example the `Name` and `Id` properties of `Person`, but not `Title`
* as it is explicitly unmapped, in
*
* ```csharp
* class Person
* {
* public int Id { get; set; }
* public string Name { get; set; }
*
* [NotMapped]
* public string Title { get; set; }
* }
*
* class MyContext : DbContext
* {
* public virtual DbSet<Person> Persons { get; set; }
* public virtual DbSet<Address> Addresses { get; set; }
* }
* ```
*/
private Property getAColumnProperty() {
exists(PropertyContent c, Type t |
this.step(_, _, c, t) and
c.getProperty() = result and
isColumnType(t)
)
}
/** Gets a `SaveChanges[Async]` method. */
pragma[nomagic]
SummarizableMethod getASaveChanges() {
this.hasMethod(result) and
result.getName().matches("SaveChanges%")
}
/** Holds if content list `head :: tail` is required. */
predicate requiresContentList(
Content head, Type headType, ContentList tail, Type tailType, Property last
) {
exists(PropertyContent p |
last = this.getAColumnProperty() and
p.getProperty() = last and
tail = ContentList::singleton(p) and
this.step(head, headType, p, tailType)
)
or
exists(Content tailHead, ContentList tailTail |
this.requiresContentList(tailHead, tailType, tailTail, _, last) and
tail = ContentList::cons(tailHead, tailTail) and
this.step(head, headType, tailHead, tailType)
)
}
/**
* Holds if the access path obtained by concatenating `head` onto `tail`
* is a path from `dbSet` (which is a `DbSet<T>` property belonging to
* this DB context) to `last`, which is a property that is mapped directly
* to a column in the underlying DB.
*/
pragma[noinline]
predicate pathFromDbSetToDbProperty(
Property dbSet, PropertyContent head, ContentList tail, Property last
) {
this.requiresContentList(head, _, tail, _, last) and
head.getProperty() = dbSet and
dbSet = this.getADbSetProperty(_)
}
}
private class DbContextSaveChanges extends EFSummarizedCallable {
private DbContextClass c;
DbContextSaveChanges() { this = c.getASaveChanges() }
override predicate requiresContentList(Content head, ContentList tail) {
c.requiresContentList(head, _, tail, _, _)
}
override predicate propagatesFlow(
SummaryInput input, ContentList inputContents, SummaryOutput output,
ContentList outputContents, boolean preservesValue
) {
exists(Property mapped |
preservesValue = true and
exists(PropertyContent sourceHead, ContentList sourceTail |
input = SummaryInput::thisParameter() and
c.pathFromDbSetToDbProperty(_, sourceHead, sourceTail, mapped) and
inputContents = ContentList::cons(sourceHead, sourceTail)
) and
exists(Property dbSetProp |
output = SummaryOutput::jump(dbSetProp.getGetter(), SummaryOutput::return()) and
c.pathFromDbSetToDbProperty(dbSetProp, _, outputContents, mapped)
)
)
}
}
}

View File

@@ -729,3 +729,8 @@ class SystemGuid extends SystemStruct {
class SystemNotImplementedExceptionClass extends SystemClass {
SystemNotImplementedExceptionClass() { this.hasName("NotImplementedException") }
}
/** The `System.DateTime` struct. */
class SystemDateTimeStruct extends SystemStruct {
SystemDateTimeStruct() { this.hasName("DateTime") }
}

View File

@@ -1,4 +1,5 @@
import csharp
from Expr argument
where argument.fromSource()
select argument, argument.getExplicitArgumentName()

View File

@@ -0,0 +1,27 @@
using System;
[assembly: Assembly1.CustomAttribute(1, new object[] { 1, 2, null }, typeof(Assembly1.CustomAttribute), (Assembly1.Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
[module: Assembly1.CustomAttribute(2, new object[] { 1, 2, null }, typeof(Assembly1.CustomAttribute), (Assembly1.Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
namespace Assembly1
{
public enum Enum1 { A = 42, B, C }
public class CustomAttribute : Attribute
{
public object[] Prop1 { get; set; }
public object[] Prop2 { get; set; }
public CustomAttribute(int i, object o, Type t, Enum1 e, int[] arr) { }
}
[Custom(3, new int[] { 1, 2, 3 }, null, (Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
public class Class1
{
[CustomAttribute(42 + 0, new int[] { 1, 2, 3 }, typeof(Class1), Enum1.B, new int[] { 1, 2, 3 }, Prop2 = new object[] { 1, typeof(int) })]
[return: Custom(42 + 0, new int[] { 1, 2, 3 }, null, Enum1.A, new int[] { 1, 2, 3 }, Prop2 = new object[] { 1, typeof(int) })]
public int Method1()
{
return 1;
}
}
}

Binary file not shown.

View File

@@ -1,39 +1,123 @@
arguments
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 1 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 3 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 42 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \u00a9 Semmle 2018" |
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
| attributes.cs:54:6:54:16 | [My(...)] | 1 | attributes.cs:54:28:54:29 | "" |
| attributes.cs:54:6:54:16 | [My(...)] | 2 | attributes.cs:54:36:54:36 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 0 | attributes.cs:40:17:40:17 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 1 | attributes.cs:40:20:40:46 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | 2 | attributes.cs:40:49:40:69 | typeof(...) |
| attributes.cs:40:12:40:15 | [Args(...)] | 3 | attributes.cs:40:72:40:76 | (...) ... |
| attributes.cs:40:12:40:15 | [Args(...)] | 4 | attributes.cs:40:79:40:82 | null |
| attributes.cs:40:12:40:15 | [Args(...)] | 5 | attributes.cs:40:92:40:122 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 0 | attributes.cs:41:15:41:15 | 0 |
| attributes.cs:41:10:41:13 | [Args(...)] | 1 | attributes.cs:41:18:41:44 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 2 | attributes.cs:41:47:41:67 | typeof(...) |
| attributes.cs:41:10:41:13 | [Args(...)] | 3 | attributes.cs:41:70:41:74 | (...) ... |
| attributes.cs:41:10:41:13 | [Args(...)] | 4 | attributes.cs:41:77:41:80 | null |
| attributes.cs:41:10:41:13 | [Args(...)] | 5 | attributes.cs:41:90:41:120 | array creation of type Object[] |
| attributes.cs:43:2:43:22 | [AttributeUsage(...)] | 0 | attributes.cs:43:24:43:50 | access to constant All |
| attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false |
| attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true |
| attributes.cs:57:6:57:16 | [My(...)] | 1 | attributes.cs:57:28:57:29 | "" |
| attributes.cs:57:6:57:16 | [My(...)] | 2 | attributes.cs:57:36:57:36 | 0 |
| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 |
| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null |
| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) |
| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A |
| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] |
| attributes.cs:76:2:76:5 | [Args(...)] | 5 | attributes.cs:76:63:76:93 | array creation of type Object[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 5 | attributes.cs:79:68:79:98 | array creation of type Object[] |
constructorArguments
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 1 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 3 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 42 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \u00a9 Semmle 2018" |
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
| attributes.cs:40:12:40:15 | [Args(...)] | 0 | attributes.cs:40:17:40:17 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 1 | attributes.cs:40:20:40:46 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | 2 | attributes.cs:40:49:40:69 | typeof(...) |
| attributes.cs:40:12:40:15 | [Args(...)] | 3 | attributes.cs:40:72:40:76 | (...) ... |
| attributes.cs:40:12:40:15 | [Args(...)] | 4 | attributes.cs:40:79:40:82 | null |
| attributes.cs:41:10:41:13 | [Args(...)] | 0 | attributes.cs:41:15:41:15 | 0 |
| attributes.cs:41:10:41:13 | [Args(...)] | 1 | attributes.cs:41:18:41:44 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 2 | attributes.cs:41:47:41:67 | typeof(...) |
| attributes.cs:41:10:41:13 | [Args(...)] | 3 | attributes.cs:41:70:41:74 | (...) ... |
| attributes.cs:41:10:41:13 | [Args(...)] | 4 | attributes.cs:41:77:41:80 | null |
| attributes.cs:43:2:43:22 | [AttributeUsage(...)] | 0 | attributes.cs:43:24:43:50 | access to constant All |
| attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false |
| attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true |
| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 |
| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null |
| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) |
| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A |
| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null |
namedArguments
| attributes.cs:54:6:54:16 | [My(...)] | x | attributes.cs:54:36:54:36 | 0 |
| attributes.cs:54:6:54:16 | [My(...)] | y | attributes.cs:54:28:54:29 | "" |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | Prop | attributes.cs:40:92:40:122 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | Prop | attributes.cs:41:90:41:120 | array creation of type Object[] |
| attributes.cs:57:6:57:16 | [My(...)] | x | attributes.cs:57:36:57:36 | 0 |
| attributes.cs:57:6:57:16 | [My(...)] | y | attributes.cs:57:28:57:29 | "" |
| attributes.cs:76:2:76:5 | [Args(...)] | Prop | attributes.cs:76:63:76:93 | array creation of type Object[] |
| attributes.cs:79:6:79:9 | [Args(...)] | Prop | attributes.cs:79:68:79:98 | array creation of type Object[] |

View File

@@ -1,13 +1,31 @@
import csharp
query predicate arguments(Attribute attribute, int index, Expr e) {
private class RelevantElement extends Element {
RelevantElement() {
this.fromSource()
or
this.getLocation().(Assembly).getName() = "Assembly1"
}
}
private class RelevantAttribute extends RelevantElement, Attribute {
RelevantAttribute() {
this.fromSource()
or
this.getType().getName() = "CustomAttribute"
}
}
private class RelevantExpr extends RelevantElement, Expr { }
query predicate arguments(RelevantAttribute attribute, int index, RelevantExpr e) {
e = attribute.getArgument(index)
}
query predicate constructorArguments(Attribute attribute, int index, Expr e) {
query predicate constructorArguments(RelevantAttribute attribute, int index, RelevantExpr e) {
e = attribute.getConstructorArgument(index)
}
query predicate namedArguments(Attribute attribute, string name, Expr e) {
query predicate namedArguments(RelevantAttribute attribute, string name, RelevantExpr e) {
e = attribute.getNamedArgument(name)
}

View File

@@ -1,8 +1,21 @@
| attributes.cs:41:7:41:9 | Foo | attributes.cs:40:2:40:22 | [AttributeUsage(...)] | System.AttributeUsageAttribute |
| attributes.cs:44:17:44:19 | foo | attributes.cs:43:6:43:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute |
| attributes.cs:49:23:49:23 | x | attributes.cs:49:14:49:16 | [Foo(...)] | Foo |
| attributes.cs:52:10:52:11 | M1 | attributes.cs:51:6:51:16 | [My(...)] | MyAttribute |
| attributes.cs:55:10:55:11 | M2 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyCompany(...)] | System.Reflection.AssemblyCompanyAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyFileVersion(...)] | System.Reflection.AssemblyFileVersionAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyInformationalVersion(...)] | System.Reflection.AssemblyInformationalVersionAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyProduct(...)] | System.Reflection.AssemblyProductAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [CompilationRelaxations(...)] | System.Runtime.CompilerServices.CompilationRelaxationsAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [Custom(...)] | Assembly1.CustomAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [Debuggable(...)] | System.Diagnostics.DebuggableAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [RuntimeCompatibility(...)] | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [TargetFramework(...)] | System.Runtime.Versioning.TargetFrameworkAttribute |
| attributes.cs:44:7:44:9 | Foo | attributes.cs:43:2:43:22 | [AttributeUsage(...)] | System.AttributeUsageAttribute |
| attributes.cs:47:17:47:19 | foo | attributes.cs:46:6:46:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute |
| attributes.cs:52:23:52:23 | x | attributes.cs:52:14:52:16 | [Foo(...)] | Foo |
| attributes.cs:55:10:55:11 | M1 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute |
| attributes.cs:58:10:58:11 | M2 | attributes.cs:57:6:57:16 | [My(...)] | MyAttribute |
| attributes.cs:77:14:77:14 | X | attributes.cs:76:2:76:5 | [Args(...)] | ArgsAttribute |
| attributes.cs:81:9:81:18 | SomeMethod | attributes.cs:79:6:79:9 | [Args(...)] | ArgsAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | System.Reflection.AssemblyDescriptionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute |
@@ -15,3 +28,5 @@
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:25:12:25:15 | [Guid(...)] | System.Runtime.InteropServices.GuidAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | System.Reflection.AssemblyVersionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | System.Reflection.AssemblyFileVersionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:40:12:40:15 | [Args(...)] | ArgsAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:41:10:41:13 | [Args(...)] | ArgsAttribute |

View File

@@ -1,5 +1,7 @@
import csharp
from Attributable element, Attribute attribute
where attribute = element.getAnAttribute()
where
attribute = element.getAnAttribute() and
(element.(Element).fromSource() or element.(Assembly).getName() in ["attributes", "Assembly1"])
select element, attribute, attribute.getType().getQualifiedName()

View File

@@ -16,7 +16,7 @@ attributes.cs:
# 14| 0: [StringLiteral] "Odasa"
# 15| [Attribute] [AssemblyCopyright(...)]
# 15| -1: [TypeMention] AssemblyCopyrightAttribute
# 15| 0: [StringLiteral] "Copyright <EFBFBD> Semmle 2018"
# 15| 0: [StringLiteral] "Copyright © Semmle 2018"
# 16| [Attribute] [AssemblyTrademark(...)]
# 16| -1: [TypeMention] AssemblyTrademarkAttribute
# 16| 0: [StringLiteral] ""
@@ -35,65 +35,213 @@ attributes.cs:
# 38| [Attribute] [AssemblyFileVersion(...)]
# 38| -1: [TypeMention] AssemblyFileVersionAttribute
# 38| 0: [StringLiteral] "1.0.0.0"
# 41| [Class] Foo
# 40| [Attribute] [Args(...)]
# 40| -1: [TypeMention] ArgsAttribute
# 40| 0: [IntLiteral] 0
# 40| 1: [ArrayCreation] array creation of type Object[]
# 40| -2: [TypeMention] Object[]
# 40| 1: [TypeMention] object
# 40| -1: [ArrayInitializer] { ..., ... }
# 40| 0: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 1
# 40| 1: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 2
# 40| 2: [NullLiteral] null
# 40| 2: [TypeofExpr] typeof(...)
# 40| 0: [TypeAccess] access to type ArgsAttribute
# 40| 0: [TypeMention] ArgsAttribute
# 40| 3: [CastExpr] (...) ...
# 40| 0: [TypeAccess] access to type E
# 40| 0: [TypeMention] E
# 40| 1: [IntLiteral] 12
# 40| 4: [NullLiteral] null
# 40| 5: [ArrayCreation] array creation of type Object[]
# 40| -2: [TypeMention] Object[]
# 40| 1: [TypeMention] object
# 40| -1: [ArrayInitializer] { ..., ... }
# 40| 0: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 1
# 40| 1: [TypeofExpr] typeof(...)
# 40| 0: [TypeAccess] access to type Int32
# 40| 0: [TypeMention] int
# 41| [Attribute] [Args(...)]
# 41| -1: [TypeMention] ArgsAttribute
# 41| 0: [IntLiteral] 0
# 41| 1: [ArrayCreation] array creation of type Object[]
# 41| -2: [TypeMention] Object[]
# 41| 1: [TypeMention] object
# 41| -1: [ArrayInitializer] { ..., ... }
# 41| 0: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 1
# 41| 1: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 2
# 41| 2: [NullLiteral] null
# 41| 2: [TypeofExpr] typeof(...)
# 41| 0: [TypeAccess] access to type ArgsAttribute
# 41| 0: [TypeMention] ArgsAttribute
# 41| 3: [CastExpr] (...) ...
# 41| 0: [TypeAccess] access to type E
# 41| 0: [TypeMention] E
# 41| 1: [IntLiteral] 12
# 41| 4: [NullLiteral] null
# 41| 5: [ArrayCreation] array creation of type Object[]
# 41| -2: [TypeMention] Object[]
# 41| 1: [TypeMention] object
# 41| -1: [ArrayInitializer] { ..., ... }
# 41| 0: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 1
# 41| 1: [TypeofExpr] typeof(...)
# 41| 0: [TypeAccess] access to type Int32
# 41| 0: [TypeMention] int
# 44| [Class] Foo
#-----| 0: (Attributes)
# 40| 1: [Attribute] [AttributeUsage(...)]
# 40| -1: [TypeMention] AttributeUsageAttribute
# 40| 0: [MemberConstantAccess] access to constant All
# 40| -1: [TypeAccess] access to type AttributeTargets
# 40| 0: [TypeMention] AttributeTargets
# 43| 1: [Attribute] [AttributeUsage(...)]
# 43| -1: [TypeMention] AttributeUsageAttribute
# 43| 0: [MemberConstantAccess] access to constant All
# 43| -1: [TypeAccess] access to type AttributeTargets
# 43| 0: [TypeMention] AttributeTargets
#-----| 3: (Base types)
# 41| 0: [TypeMention] Attribute
# 44| 5: [Method] foo
# 44| -1: [TypeMention] Void
# 44| 0: [TypeMention] Attribute
# 47| 5: [Method] foo
# 47| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 43| 1: [Attribute] [Conditional(...)]
# 43| -1: [TypeMention] ConditionalAttribute
# 43| 0: [StringLiteral] "DEBUG2"
# 44| 4: [BlockStmt] {...}
# 47| [Class] Bar
# 49| 5: [Method] inc
# 49| -1: [TypeMention] int
# 46| 1: [Attribute] [Conditional(...)]
# 46| -1: [TypeMention] ConditionalAttribute
# 46| 0: [StringLiteral] "DEBUG2"
# 47| 4: [BlockStmt] {...}
# 50| [Class] Bar
# 52| 5: [Method] inc
# 52| -1: [TypeMention] int
#-----| 2: (Parameters)
# 49| 0: [Parameter] x
# 49| -1: [TypeMention] int
# 52| 0: [Parameter] x
# 52| -1: [TypeMention] int
#-----| 0: (Attributes)
# 49| 1: [Attribute] [Foo(...)]
# 49| 0: [TypeMention] Foo
# 49| 4: [BlockStmt] {...}
# 49| 0: [ReturnStmt] return ...;
# 49| 0: [AddExpr] ... + ...
# 49| 0: [ParameterAccess] access to parameter x
# 49| 1: [IntLiteral] 1
# 52| 6: [Method] M1
# 52| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 51| 1: [Attribute] [My(...)]
# 51| -1: [TypeMention] MyAttribute
# 51| 0: [BoolLiteral] false
# 52| 1: [Attribute] [Foo(...)]
# 52| 0: [TypeMention] Foo
# 52| 4: [BlockStmt] {...}
# 55| 7: [Method] M2
# 52| 0: [ReturnStmt] return ...;
# 52| 0: [AddExpr] ... + ...
# 52| 0: [ParameterAccess] access to parameter x
# 52| 1: [IntLiteral] 1
# 55| 6: [Method] M1
# 55| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 54| 1: [Attribute] [My(...)]
# 54| -1: [TypeMention] MyAttribute
# 54| 0: [BoolLiteral] true
# 54| 1: [StringLiteral] ""
# 54| 2: [IntLiteral] 0
# 54| 0: [BoolLiteral] false
# 55| 4: [BlockStmt] {...}
# 58| [Class] MyAttribute
# 58| 7: [Method] M2
# 58| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 57| 1: [Attribute] [My(...)]
# 57| -1: [TypeMention] MyAttribute
# 57| 0: [BoolLiteral] true
# 57| 1: [StringLiteral] ""
# 57| 2: [IntLiteral] 0
# 58| 4: [BlockStmt] {...}
# 61| [Class] MyAttribute
#-----| 3: (Base types)
# 58| 0: [TypeMention] Attribute
# 60| 4: [Field] x
# 60| -1: [TypeMention] int
# 61| 5: [IndexerProperty] y
# 61| -1: [TypeMention] string
# 61| 3: [Getter] get_y
# 61| 4: [Setter] set_y
# 61| 0: [TypeMention] Attribute
# 63| 4: [Field] x
# 63| -1: [TypeMention] int
# 64| 5: [IndexerProperty] y
# 64| -1: [TypeMention] string
# 64| 3: [Getter] get_y
# 64| 4: [Setter] set_y
#-----| 2: (Parameters)
# 61| 0: [Parameter] value
# 62| 6: [InstanceConstructor] MyAttribute
# 64| 0: [Parameter] value
# 65| 6: [InstanceConstructor] MyAttribute
#-----| 2: (Parameters)
# 62| 0: [Parameter] b
# 62| -1: [TypeMention] bool
# 62| 4: [BlockStmt] {...}
# 65| 0: [Parameter] b
# 65| -1: [TypeMention] bool
# 65| 4: [BlockStmt] {...}
# 68| [Enum] E
# 68| 5: [Field] A
# 68| 1: [AssignExpr] ... = ...
# 68| 0: [MemberConstantAccess] access to constant A
# 68| 1: [IntLiteral] 42
# 70| [Class] ArgsAttribute
#-----| 3: (Base types)
# 70| 0: [TypeMention] Attribute
# 72| 4: [Property] Prop
# 72| -1: [TypeMention] Object[]
# 72| 1: [TypeMention] object
# 72| 3: [Getter] get_Prop
# 72| 4: [Setter] set_Prop
#-----| 2: (Parameters)
# 72| 0: [Parameter] value
# 73| 5: [InstanceConstructor] ArgsAttribute
#-----| 2: (Parameters)
# 73| 0: [Parameter] i
# 73| -1: [TypeMention] int
# 73| 1: [Parameter] o
# 73| -1: [TypeMention] object
# 73| 2: [Parameter] t
# 73| -1: [TypeMention] Type
# 73| 3: [Parameter] e
# 73| -1: [TypeMention] E
# 73| 4: [Parameter] arr
# 73| -1: [TypeMention] Int32[]
# 73| 1: [TypeMention] int
# 73| 4: [BlockStmt] {...}
# 77| [Class] X
#-----| 0: (Attributes)
# 76| 1: [Attribute] [Args(...)]
# 76| -1: [TypeMention] ArgsAttribute
# 76| 0: [IntLiteral] 42
# 76| 1: [NullLiteral] null
# 76| 2: [TypeofExpr] typeof(...)
# 76| 0: [TypeAccess] access to type X
# 76| 0: [TypeMention] X
# 76| 3: [MemberConstantAccess] access to constant A
# 76| -1: [TypeAccess] access to type E
# 76| 0: [TypeMention] E
# 76| 4: [ArrayCreation] array creation of type Int32[]
# 76| -2: [TypeMention] Int32[]
# 76| 1: [TypeMention] int
# 76| -1: [ArrayInitializer] { ..., ... }
# 76| 0: [IntLiteral] 1
# 76| 1: [IntLiteral] 2
# 76| 2: [IntLiteral] 3
# 76| 5: [ArrayCreation] array creation of type Object[]
# 76| -2: [TypeMention] Object[]
# 76| 1: [TypeMention] object
# 76| -1: [ArrayInitializer] { ..., ... }
# 76| 0: [CastExpr] (...) ...
# 76| 1: [IntLiteral] 1
# 76| 1: [TypeofExpr] typeof(...)
# 76| 0: [TypeAccess] access to type Int32
# 76| 0: [TypeMention] int
# 81| 5: [Method] SomeMethod
# 81| -1: [TypeMention] int
#-----| 0: (Attributes)
# 79| 1: [Attribute] [Args(...)]
# 79| -1: [TypeMention] ArgsAttribute
# 79| 0: [AddExpr] ... + ...
# 79| 0: [IntLiteral] 42
# 79| 1: [IntLiteral] 0
# 79| 1: [ArrayCreation] array creation of type Int32[]
# 79| -2: [TypeMention] Int32[]
# 79| 1: [TypeMention] int
# 79| -1: [ArrayInitializer] { ..., ... }
# 79| 0: [IntLiteral] 1
# 79| 1: [IntLiteral] 2
# 79| 2: [IntLiteral] 3
# 79| 2: [NullLiteral] null
# 79| 3: [CastExpr] (...) ...
# 79| 0: [TypeAccess] access to type E
# 79| 0: [TypeMention] E
# 79| 1: [IntLiteral] 12
# 79| 4: [NullLiteral] null
# 79| 5: [ArrayCreation] array creation of type Object[]
# 79| -2: [TypeMention] Object[]
# 79| 1: [TypeMention] object
# 79| -1: [ArrayInitializer] { ..., ... }
# 79| 0: [CastExpr] (...) ...
# 79| 1: [IntLiteral] 1
# 79| 1: [TypeofExpr] typeof(...)
# 79| 0: [TypeAccess] access to type Int32
# 79| 0: [TypeMention] int
# 81| 4: [BlockStmt] {...}
# 81| 0: [ReturnStmt] return ...;
# 81| 0: [IntLiteral] 1

View File

@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Semmle Plc")]
[assembly: AssemblyProduct("Odasa")]
[assembly: AssemblyCopyright("Copyright <EFBFBD> Semmle 2018")]
[assembly: AssemblyCopyright("Copyright © Semmle 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -37,6 +37,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Args(0, new object[] { 1, 2, null }, typeof(ArgsAttribute), (E)12, null, Prop = new object[] { 1, typeof(int) })]
[module: Args(0, new object[] { 1, 2, null }, typeof(ArgsAttribute), (E)12, null, Prop = new object[] { 1, typeof(int) })]
[System.AttributeUsage(System.AttributeTargets.All)]
class Foo : Attribute
{
@@ -61,3 +64,19 @@ class MyAttribute : Attribute
public string y { get; set; }
public MyAttribute(bool b) { }
}
public enum E { A = 42 }
public class ArgsAttribute : Attribute
{
public object[] Prop { get; set; }
public ArgsAttribute(int i, object o, Type t, E e, int[] arr) { }
}
[Args(42, null, typeof(X), E.A, new int[] { 1, 2, 3 }, Prop = new object[] { 1, typeof(int) })]
public class X
{
[Args(42 + 0, new int[] { 1, 2, 3 }, null, (E)12, null, Prop = new object[] { 1, typeof(int) })]
[return: Args(42 + 0, new int[] { 1, 2, 3 }, null, (E)12, null, Prop = new object[] { 1, typeof(int) })]
int SomeMethod() { return 1; }
}

View File

@@ -2,11 +2,13 @@ import csharp
import Common
query predicate dominance(SourceControlFlowNode dom, SourceControlFlowNode node) {
dom.strictlyDominates(node) and dom.getASuccessor() = node
dom.strictlyDominates(node) and
dom.getASuccessor() = node
}
query predicate postDominance(SourceControlFlowNode dom, SourceControlFlowNode node) {
dom.strictlyPostDominates(node) and dom.getAPredecessor() = node
dom.strictlyPostDominates(node) and
dom.getAPredecessor() = node
}
query predicate blockDominance(SourceBasicBlock dom, SourceBasicBlock bb) { dom.dominates(bb) }

View File

@@ -189,6 +189,7 @@
| AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access |
| AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access |
| AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 |
| AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 |
@@ -1600,7 +1601,9 @@
| Foreach.cs:25:5:28:5 | {...} | Foreach.cs:25:5:28:5 | {...} |
| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:36:26:39 | access to parameter args |
| Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:23:26:23 | String x |
| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 |
| Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x |
| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 |
| Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y |
| Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args |
| Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; |

View File

@@ -3,4 +3,5 @@ import Common
import ControlFlow::Internal
from SourceControlFlowElement cfe
where cfe.fromSource()
select cfe, first(cfe)

View File

@@ -189,6 +189,7 @@
| AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access | normal |
| AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access | normal |
| AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:33:58:44 | (..., ...) | normal |
| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 | normal |
| AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access | normal |
| AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:42:58:42 | 0 | normal |
| AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 | normal |
@@ -2268,7 +2269,9 @@
| Foreach.cs:25:5:28:5 | {...} | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty |
| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty |
| Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:18:26:31 | (..., ...) | normal |
| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 | normal |
| Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x | normal |
| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 | normal |
| Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y | normal |
| Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args | normal |
| Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; | normal |

View File

@@ -4,4 +4,5 @@ private import semmle.code.csharp.controlflow.internal.Completion
import Common
from SourceControlFlowElement cfe, Completion c
where cfe.fromSource()
select cfe, last(cfe, c), c

View File

@@ -1,8 +1,12 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
query predicate abstractValue(AbstractValue value, Expr e) { e = value.getAnExpr() }
query predicate abstractValue(AbstractValue value, Expr e) {
e = value.getAnExpr() and e.fromSource()
}
query predicate dualValue(AbstractValue value, AbstractValue dual) { dual = value.getDualValue() }
query predicate singletonValue(AbstractValue value) { value.isSingleton() }
query predicate singletonValue(AbstractValue value) {
value.isSingleton() and value.getAnExpr().fromSource()
}

View File

@@ -1,4 +1,5 @@
import csharp
from IntLiteral l
where l.fromSource()
select l

View File

@@ -1,11 +1,13 @@
import csharp
query predicate arrayCreation(ArrayCreation creation, int i, Expr length) {
creation.fromSource() and
length = creation.getLengthArgument(i)
}
query predicate arrayElement(ArrayCreation array, int i, Expr element) {
array.fromSource() and
element = array.getInitializer().getElement(i)
}
query predicate stackalloc(Stackalloc a) { any() }
query predicate stackalloc(Stackalloc a) { a.fromSource() }

View File

@@ -9,5 +9,9 @@ private boolean isImplicit(Expr expr) {
}
from ArrayCreation ac, Expr expr
where ac.isImplicitlySized() and not ac.isImplicitlyTyped() and expr = ac.getALengthArgument()
where
ac.isImplicitlySized() and
not ac.isImplicitlyTyped() and
expr = ac.getALengthArgument() and
ac.fromSource()
select ac, expr, isImplicit(expr)

View File

@@ -1995,15 +1995,15 @@ expressions.cs:
# 449| 2: [TypeMention] byte
# 449| 0: [LocalVariableAccess] access to local variable f1
# 449| 1: [LambdaExpr] (...) => ...
# 449| 0: [CastExpr] (...) ...
#-----| 2: (Parameters)
# 449| 0: [Parameter] x
# 449| 4: [CastExpr] (...) ...
# 449| 0: [TypeAccess] access to type Byte
# 449| 0: [TypeMention] byte
# 449| 1: [AddExpr] ... + ...
# 449| 0: [CastExpr] (...) ...
# 449| 1: [ParameterAccess] access to parameter x
# 449| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 449| 0: [Parameter] x
# 450| 1: [LocalVariableDeclStmt] ... ...;
# 450| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Double> f2 = ...
# 450| -1: [TypeMention] Func<Int32, Double>
@@ -2011,14 +2011,14 @@ expressions.cs:
# 450| 2: [TypeMention] double
# 450| 0: [LocalVariableAccess] access to local variable f2
# 450| 1: [LambdaExpr] (...) => ...
# 450| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 450| 0: [Parameter] x
# 450| 4: [BlockStmt] {...}
# 450| 0: [ReturnStmt] return ...;
# 450| 0: [CastExpr] (...) ...
# 450| 1: [AddExpr] ... + ...
# 450| 0: [ParameterAccess] access to parameter x
# 450| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 450| 0: [Parameter] x
# 451| 2: [LocalVariableDeclStmt] ... ...;
# 451| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f3 = ...
# 451| -1: [TypeMention] Func<Int32, Int32>
@@ -2026,12 +2026,12 @@ expressions.cs:
# 451| 2: [TypeMention] int
# 451| 0: [LocalVariableAccess] access to local variable f3
# 451| 1: [LambdaExpr] (...) => ...
# 451| 0: [AddExpr] ... + ...
# 451| 0: [ParameterAccess] access to parameter x
# 451| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 451| 0: [Parameter] x
# 451| -1: [TypeMention] int
# 451| 4: [AddExpr] ... + ...
# 451| 0: [ParameterAccess] access to parameter x
# 451| 1: [IntLiteral] 1
# 452| 3: [LocalVariableDeclStmt] ... ...;
# 452| 0: [LocalVariableDeclAndInitExpr] Func<Int32,String> f4 = ...
# 452| -1: [TypeMention] Func<Int32, String>
@@ -2039,32 +2039,32 @@ expressions.cs:
# 452| 2: [TypeMention] string
# 452| 0: [LocalVariableAccess] access to local variable f4
# 452| 1: [LambdaExpr] (...) => ...
# 452| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 452| 0: [Parameter] x
# 452| -1: [TypeMention] int
# 452| 4: [BlockStmt] {...}
# 452| 0: [ReturnStmt] return ...;
# 452| 0: [AddExpr] ... + ...
# 452| 0: [CastExpr] (...) ...
# 452| 1: [ParameterAccess] access to parameter x
# 452| 1: [StringLiteral] ""
#-----| 2: (Parameters)
# 452| 0: [Parameter] x
# 452| -1: [TypeMention] int
# 453| 4: [LocalVariableDeclStmt] ... ...;
# 453| 0: [LocalVariableDeclAndInitExpr] S f5 = ...
# 453| -1: [TypeMention] S
# 453| 0: [LocalVariableAccess] access to local variable f5
# 453| 1: [LambdaExpr] (...) => ...
# 453| 0: [MulExpr] ... * ...
# 453| 0: [ParameterAccess] access to parameter x
# 453| 1: [ParameterAccess] access to parameter y
#-----| 2: (Parameters)
# 453| 0: [Parameter] x
# 453| 1: [Parameter] y
# 453| 4: [MulExpr] ... * ...
# 453| 0: [ParameterAccess] access to parameter x
# 453| 1: [ParameterAccess] access to parameter y
# 454| 5: [LocalVariableDeclStmt] ... ...;
# 454| 0: [LocalVariableDeclAndInitExpr] Unit f6 = ...
# 454| -1: [TypeMention] Unit
# 454| 0: [LocalVariableAccess] access to local variable f6
# 454| 1: [LambdaExpr] (...) => ...
# 454| 0: [MethodCall] call to method WriteLine
# 454| 4: [MethodCall] call to method WriteLine
# 454| -1: [TypeAccess] access to type Console
# 454| 0: [TypeMention] Console
# 455| 6: [LocalVariableDeclStmt] ... ...;
@@ -2074,14 +2074,14 @@ expressions.cs:
# 455| 2: [TypeMention] int
# 455| 0: [LocalVariableAccess] access to local variable f7
# 455| 1: [AnonymousMethodExpr] delegate(...) { ... }
# 455| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 455| 0: [Parameter] x
# 455| -1: [TypeMention] int
# 455| 4: [BlockStmt] {...}
# 455| 0: [ReturnStmt] return ...;
# 455| 0: [AddExpr] ... + ...
# 455| 0: [ParameterAccess] access to parameter x
# 455| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 455| 0: [Parameter] x
# 455| -1: [TypeMention] int
# 456| 7: [LocalVariableDeclStmt] ... ...;
# 456| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
# 456| -1: [TypeMention] int
@@ -2093,7 +2093,7 @@ expressions.cs:
# 457| 1: [TypeMention] int
# 457| 0: [LocalVariableAccess] access to local variable f8
# 457| 1: [AnonymousMethodExpr] delegate(...) { ... }
# 457| 0: [BlockStmt] {...}
# 457| 4: [BlockStmt] {...}
# 457| 0: [ReturnStmt] return ...;
# 457| 0: [AddExpr] ... + ...
# 457| 0: [LocalVariableAccess] access to local variable j

View File

@@ -1,5 +1,5 @@
import csharp
from Expr e, Expr stripped
where stripped = e.stripCasts() and e != stripped
where stripped = e.stripCasts() and e != stripped and e.fromSource()
select e, stripped

View File

@@ -1,7 +1,355 @@
| EntityFramework.cs:52:18:52:24 | access to property Name | EntityFramework.cs:47:34:47:42 | "tainted" |
| EntityFramework.cs:53:18:53:34 | access to property Name | EntityFramework.cs:47:34:47:42 | "tainted" |
| EntityFrameworkCore.cs:50:18:50:28 | access to local variable taintSource | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:51:18:51:46 | (...) ... | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:52:18:52:42 | (...) ... | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:60:18:60:24 | access to property Name | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
| EntityFrameworkCore.cs:61:18:61:34 | access to property Name | EntityFrameworkCore.cs:47:31:47:39 | "tainted" |
edges
| EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String | EntityFramework.cs:68:29:68:30 | access to local variable p1 [Name] : String |
| EntityFramework.cs:63:24:63:32 | "tainted" : String | EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String |
| EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:68:13:68:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:68:29:68:30 | access to local variable p1 [Name] : String | EntityFramework.cs:68:13:68:23 | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String |
| EntityFramework.cs:83:13:86:13 | { ..., ... } [Name] : String | EntityFramework.cs:90:29:90:30 | access to local variable p1 [Name] : String |
| EntityFramework.cs:85:24:85:32 | "tainted" : String | EntityFramework.cs:83:13:86:13 | { ..., ... } [Name] : String |
| EntityFramework.cs:90:13:90:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:90:13:90:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:90:13:90:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:90:29:90:30 | access to local variable p1 [Name] : String | EntityFramework.cs:90:13:90:23 | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String |
| EntityFramework.cs:105:13:108:13 | { ..., ... } [Name] : String | EntityFramework.cs:111:27:111:28 | access to local variable p1 [Name] : String |
| EntityFramework.cs:107:24:107:32 | "tainted" : String | EntityFramework.cs:105:13:108:13 | { ..., ... } [Name] : String |
| EntityFramework.cs:111:27:111:28 | access to local variable p1 [Name] : String | EntityFramework.cs:195:35:195:35 | p [Name] : String |
| EntityFramework.cs:124:13:127:13 | { ..., ... } [Title] : String | EntityFramework.cs:131:18:131:19 | access to local variable p1 [Title] : String |
| EntityFramework.cs:126:25:126:33 | "tainted" : String | EntityFramework.cs:124:13:127:13 | { ..., ... } [Title] : String |
| EntityFramework.cs:131:18:131:19 | access to local variable p1 [Title] : String | EntityFramework.cs:131:18:131:25 | access to property Title |
| EntityFramework.cs:143:13:150:13 | { ..., ... } [Addresses, [], Street] : String | EntityFramework.cs:151:29:151:30 | access to local variable p1 [Addresses, [], Street] : String |
| EntityFramework.cs:144:29:149:17 | array creation of type Address[] [[], Street] : String | EntityFramework.cs:143:13:150:13 | { ..., ... } [Addresses, [], Street] : String |
| EntityFramework.cs:144:35:149:17 | { ..., ... } [[], Street] : String | EntityFramework.cs:144:29:149:17 | array creation of type Address[] [[], Street] : String |
| EntityFramework.cs:145:21:148:21 | object creation of type Address [Street] : String | EntityFramework.cs:144:35:149:17 | { ..., ... } [[], Street] : String |
| EntityFramework.cs:145:33:148:21 | { ..., ... } [Street] : String | EntityFramework.cs:145:21:148:21 | object creation of type Address [Street] : String |
| EntityFramework.cs:147:34:147:42 | "tainted" : String | EntityFramework.cs:145:33:148:21 | { ..., ... } [Street] : String |
| EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:13:151:23 | [post] access to property Persons [[], Addresses, [], Street] : String | EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:29:151:30 | access to local variable p1 [Addresses, [], Street] : String | EntityFramework.cs:151:13:151:23 | [post] access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:159:13:162:13 | { ..., ... } [Street] : String | EntityFramework.cs:163:31:163:32 | access to local variable a1 [Street] : String |
| EntityFramework.cs:161:26:161:34 | "tainted" : String | EntityFramework.cs:159:13:162:13 | { ..., ... } [Street] : String |
| EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:163:13:163:25 | [post] access to property Addresses [[], Street] : String | EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:163:31:163:32 | access to local variable a1 [Street] : String | EntityFramework.cs:163:13:163:25 | [post] access to property Addresses [[], Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:175:13:178:13 | { ..., ... } [Name] : String | EntityFramework.cs:184:71:184:72 | access to local variable p1 [Name] : String |
| EntityFramework.cs:177:24:177:32 | "tainted" : String | EntityFramework.cs:175:13:178:13 | { ..., ... } [Name] : String |
| EntityFramework.cs:180:13:183:13 | { ..., ... } [Street] : String | EntityFramework.cs:184:85:184:86 | access to local variable a1 [Street] : String |
| EntityFramework.cs:182:26:182:34 | "tainted" : String | EntityFramework.cs:180:13:183:13 | { ..., ... } [Street] : String |
| EntityFramework.cs:184:60:184:88 | { ..., ... } [Address, Street] : String | EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Address, Street] : String |
| EntityFramework.cs:184:60:184:88 | { ..., ... } [Person, Name] : String | EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Person, Name] : String |
| EntityFramework.cs:184:71:184:72 | access to local variable p1 [Name] : String | EntityFramework.cs:184:60:184:88 | { ..., ... } [Person, Name] : String |
| EntityFramework.cs:184:85:184:86 | access to local variable a1 [Street] : String | EntityFramework.cs:184:60:184:88 | { ..., ... } [Address, Street] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Address, Street] : String | EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Person, Name] : String | EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Address, Street] : String | EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Address, Street] : String |
| EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Person, Name] : String | EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Person, Name] : String |
| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String |
| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String |
| EntityFramework.cs:195:35:195:35 | p [Name] : String | EntityFramework.cs:198:29:198:29 | access to parameter p [Name] : String |
| EntityFramework.cs:198:13:198:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:198:13:198:23 | [post] access to property Persons [[], Name] : String | EntityFramework.cs:198:13:198:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:198:29:198:29 | access to parameter p [Name] : String | EntityFramework.cs:198:13:198:23 | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String | EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String |
| EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | EntityFramework.cs:206:18:206:36 | call to method First [Name] : String |
| EntityFramework.cs:206:18:206:36 | call to method First [Name] : String | EntityFramework.cs:206:18:206:41 | access to property Name |
| EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | EntityFramework.cs:214:18:214:38 | call to method First [Street] : String |
| EntityFramework.cs:214:18:214:38 | call to method First [Street] : String | EntityFramework.cs:214:18:214:45 | access to property Street |
| EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | EntityFramework.cs:221:18:221:36 | call to method First [Addresses, [], Street] : String |
| EntityFramework.cs:221:18:221:36 | call to method First [Addresses, [], Street] : String | EntityFramework.cs:221:18:221:46 | access to property Addresses [[], Street] : String |
| EntityFramework.cs:221:18:221:46 | access to property Addresses [[], Street] : String | EntityFramework.cs:221:18:221:54 | call to method First [Street] : String |
| EntityFramework.cs:221:18:221:54 | call to method First [Street] : String | EntityFramework.cs:221:18:221:61 | access to property Street |
| EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:76:18:76:28 | access to local variable taintSource |
| EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:77:35:77:45 | access to local variable taintSource : String |
| EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:78:32:78:42 | access to local variable taintSource : String |
| EntityFrameworkCore.cs:77:18:77:46 | object creation of type RawSqlString : RawSqlString | EntityFrameworkCore.cs:77:18:77:46 | (...) ... |
| EntityFrameworkCore.cs:77:35:77:45 | access to local variable taintSource : String | EntityFrameworkCore.cs:77:18:77:46 | object creation of type RawSqlString : RawSqlString |
| EntityFrameworkCore.cs:78:18:78:42 | call to operator implicit conversion : RawSqlString | EntityFrameworkCore.cs:78:18:78:42 | (...) ... |
| EntityFrameworkCore.cs:78:32:78:42 | access to local variable taintSource : String | EntityFrameworkCore.cs:78:18:78:42 | call to operator implicit conversion : RawSqlString |
| EntityFrameworkCore.cs:85:13:88:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:92:29:92:30 | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:87:24:87:32 | "tainted" : String | EntityFrameworkCore.cs:85:13:88:13 | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:92:13:92:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:92:13:92:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:92:13:92:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:92:29:92:30 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:92:13:92:23 | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:107:13:110:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:114:29:114:30 | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:109:24:109:32 | "tainted" : String | EntityFrameworkCore.cs:107:13:110:13 | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:114:13:114:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:114:13:114:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:114:13:114:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:114:29:114:30 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:114:13:114:23 | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:129:13:132:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:135:27:135:28 | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:131:24:131:32 | "tainted" : String | EntityFrameworkCore.cs:129:13:132:13 | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:135:27:135:28 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:219:35:219:35 | p [Name] : String |
| EntityFrameworkCore.cs:148:13:151:13 | { ..., ... } [Title] : String | EntityFrameworkCore.cs:155:18:155:19 | access to local variable p1 [Title] : String |
| EntityFrameworkCore.cs:150:25:150:33 | "tainted" : String | EntityFrameworkCore.cs:148:13:151:13 | { ..., ... } [Title] : String |
| EntityFrameworkCore.cs:155:18:155:19 | access to local variable p1 [Title] : String | EntityFrameworkCore.cs:155:18:155:25 | access to property Title |
| EntityFrameworkCore.cs:167:13:174:13 | { ..., ... } [Addresses, [], Street] : String | EntityFrameworkCore.cs:175:29:175:30 | access to local variable p1 [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:168:29:173:17 | array creation of type Address[] [[], Street] : String | EntityFrameworkCore.cs:167:13:174:13 | { ..., ... } [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:168:35:173:17 | { ..., ... } [[], Street] : String | EntityFrameworkCore.cs:168:29:173:17 | array creation of type Address[] [[], Street] : String |
| EntityFrameworkCore.cs:169:21:172:21 | object creation of type Address [Street] : String | EntityFrameworkCore.cs:168:35:173:17 | { ..., ... } [[], Street] : String |
| EntityFrameworkCore.cs:169:33:172:21 | { ..., ... } [Street] : String | EntityFrameworkCore.cs:169:21:172:21 | object creation of type Address [Street] : String |
| EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | EntityFrameworkCore.cs:169:33:172:21 | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:13:175:23 | [post] access to property Persons [[], Addresses, [], Street] : String | EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:29:175:30 | access to local variable p1 [Addresses, [], Street] : String | EntityFrameworkCore.cs:175:13:175:23 | [post] access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:183:13:186:13 | { ..., ... } [Street] : String | EntityFrameworkCore.cs:187:31:187:32 | access to local variable a1 [Street] : String |
| EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | EntityFrameworkCore.cs:183:13:186:13 | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:187:13:187:25 | [post] access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:187:31:187:32 | access to local variable a1 [Street] : String | EntityFrameworkCore.cs:187:13:187:25 | [post] access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:199:13:202:13 | { ..., ... } [Name] : String | EntityFrameworkCore.cs:208:71:208:72 | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:201:24:201:32 | "tainted" : String | EntityFrameworkCore.cs:199:13:202:13 | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:204:13:207:13 | { ..., ... } [Street] : String | EntityFrameworkCore.cs:208:85:208:86 | access to local variable a1 [Street] : String |
| EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | EntityFrameworkCore.cs:204:13:207:13 | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Address, Street] : String | EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Address, Street] : String |
| EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Person, Name] : String | EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Person, Name] : String |
| EntityFrameworkCore.cs:208:71:208:72 | access to local variable p1 [Name] : String | EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Person, Name] : String |
| EntityFrameworkCore.cs:208:85:208:86 | access to local variable a1 [Street] : String | EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Address, Street] : String | EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Person, Name] : String | EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Address, Street] : String | EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Address, Street] : String |
| EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Person, Name] : String | EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Person, Name] : String |
| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:219:35:219:35 | p [Name] : String | EntityFrameworkCore.cs:222:29:222:29 | access to parameter p [Name] : String |
| EntityFrameworkCore.cs:222:13:222:15 | [post] access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:222:13:222:23 | [post] access to property Persons [[], Name] : String | EntityFrameworkCore.cs:222:13:222:15 | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:222:29:222:29 | access to parameter p [Name] : String | EntityFrameworkCore.cs:222:13:222:23 | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String | EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | EntityFrameworkCore.cs:230:18:230:36 | call to method First [Name] : String |
| EntityFrameworkCore.cs:230:18:230:36 | call to method First [Name] : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name |
| EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:238:18:238:38 | call to method First [Street] : String |
| EntityFrameworkCore.cs:238:18:238:38 | call to method First [Street] : String | EntityFrameworkCore.cs:238:18:238:45 | access to property Street |
| EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:36 | call to method First [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:245:18:245:36 | call to method First [Addresses, [], Street] : String | EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses [[], Street] : String | EntityFrameworkCore.cs:245:18:245:54 | call to method First [Street] : String |
| EntityFrameworkCore.cs:245:18:245:54 | call to method First [Street] : String | EntityFrameworkCore.cs:245:18:245:61 | access to property Street |
nodes
| EntityFramework.cs:61:13:64:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFramework.cs:63:24:63:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:68:13:68:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:68:13:68:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:68:29:68:30 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFramework.cs:70:13:70:15 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:83:13:86:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFramework.cs:85:24:85:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:90:13:90:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:90:13:90:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:90:29:90:30 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFramework.cs:92:19:92:21 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:105:13:108:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFramework.cs:107:24:107:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:111:27:111:28 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFramework.cs:124:13:127:13 | { ..., ... } [Title] : String | semmle.label | { ..., ... } [Title] : String |
| EntityFramework.cs:126:25:126:33 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:131:18:131:19 | access to local variable p1 [Title] : String | semmle.label | access to local variable p1 [Title] : String |
| EntityFramework.cs:131:18:131:25 | access to property Title | semmle.label | access to property Title |
| EntityFramework.cs:143:13:150:13 | { ..., ... } [Addresses, [], Street] : String | semmle.label | { ..., ... } [Addresses, [], Street] : String |
| EntityFramework.cs:144:29:149:17 | array creation of type Address[] [[], Street] : String | semmle.label | array creation of type Address[] [[], Street] : String |
| EntityFramework.cs:144:35:149:17 | { ..., ... } [[], Street] : String | semmle.label | { ..., ... } [[], Street] : String |
| EntityFramework.cs:145:21:148:21 | object creation of type Address [Street] : String | semmle.label | object creation of type Address [Street] : String |
| EntityFramework.cs:145:33:148:21 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFramework.cs:147:34:147:42 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:151:13:151:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:151:13:151:23 | [post] access to property Persons [[], Addresses, [], Street] : String | semmle.label | [post] access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:151:29:151:30 | access to local variable p1 [Addresses, [], Street] : String | semmle.label | access to local variable p1 [Addresses, [], Street] : String |
| EntityFramework.cs:152:13:152:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:156:13:156:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:159:13:162:13 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFramework.cs:161:26:161:34 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:163:13:163:15 | [post] access to local variable ctx [Addresses, [], Street] : String | semmle.label | [post] access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:163:13:163:25 | [post] access to property Addresses [[], Street] : String | semmle.label | [post] access to property Addresses [[], Street] : String |
| EntityFramework.cs:163:31:163:32 | access to local variable a1 [Street] : String | semmle.label | access to local variable a1 [Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Addresses, [], Street] : String | semmle.label | access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:164:13:164:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Addresses, [], Street] : String | semmle.label | access to local variable ctx [Addresses, [], Street] : String |
| EntityFramework.cs:168:13:168:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFramework.cs:175:13:178:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFramework.cs:177:24:177:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:180:13:183:13 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFramework.cs:182:26:182:34 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFramework.cs:184:60:184:88 | { ..., ... } [Address, Street] : String | semmle.label | { ..., ... } [Address, Street] : String |
| EntityFramework.cs:184:60:184:88 | { ..., ... } [Person, Name] : String | semmle.label | { ..., ... } [Person, Name] : String |
| EntityFramework.cs:184:71:184:72 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFramework.cs:184:85:184:86 | access to local variable a1 [Street] : String | semmle.label | access to local variable a1 [Street] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:185:13:185:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Address, Street] : String | semmle.label | [post] access to property PersonAddresses [[], Address, Street] : String |
| EntityFramework.cs:185:13:185:31 | [post] access to property PersonAddresses [[], Person, Name] : String | semmle.label | [post] access to property PersonAddresses [[], Person, Name] : String |
| EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Address, Street] : String | semmle.label | access to local variable personAddressMap1 [Address, Street] : String |
| EntityFramework.cs:185:37:185:53 | access to local variable personAddressMap1 [Person, Name] : String | semmle.label | access to local variable personAddressMap1 [Person, Name] : String |
| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:186:13:186:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFramework.cs:192:13:192:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFramework.cs:195:35:195:35 | p [Name] : String | semmle.label | p [Name] : String |
| EntityFramework.cs:198:13:198:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:198:13:198:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFramework.cs:198:29:198:29 | access to parameter p [Name] : String | semmle.label | access to parameter p [Name] : String |
| EntityFramework.cs:199:13:199:15 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFramework.cs:206:18:206:28 | access to property Persons [[], Name] : String | semmle.label | access to property Persons [[], Name] : String |
| EntityFramework.cs:206:18:206:36 | call to method First [Name] : String | semmle.label | call to method First [Name] : String |
| EntityFramework.cs:206:18:206:41 | access to property Name | semmle.label | access to property Name |
| EntityFramework.cs:214:18:214:30 | access to property Addresses [[], Street] : String | semmle.label | access to property Addresses [[], Street] : String |
| EntityFramework.cs:214:18:214:38 | call to method First [Street] : String | semmle.label | call to method First [Street] : String |
| EntityFramework.cs:214:18:214:45 | access to property Street | semmle.label | access to property Street |
| EntityFramework.cs:221:18:221:28 | access to property Persons [[], Addresses, [], Street] : String | semmle.label | access to property Persons [[], Addresses, [], Street] : String |
| EntityFramework.cs:221:18:221:36 | call to method First [Addresses, [], Street] : String | semmle.label | call to method First [Addresses, [], Street] : String |
| EntityFramework.cs:221:18:221:46 | access to property Addresses [[], Street] : String | semmle.label | access to property Addresses [[], Street] : String |
| EntityFramework.cs:221:18:221:54 | call to method First [Street] : String | semmle.label | call to method First [Street] : String |
| EntityFramework.cs:221:18:221:61 | access to property Street | semmle.label | access to property Street |
| EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:76:18:76:28 | access to local variable taintSource | semmle.label | access to local variable taintSource |
| EntityFrameworkCore.cs:77:18:77:46 | (...) ... | semmle.label | (...) ... |
| EntityFrameworkCore.cs:77:18:77:46 | object creation of type RawSqlString : RawSqlString | semmle.label | object creation of type RawSqlString : RawSqlString |
| EntityFrameworkCore.cs:77:35:77:45 | access to local variable taintSource : String | semmle.label | access to local variable taintSource : String |
| EntityFrameworkCore.cs:78:18:78:42 | (...) ... | semmle.label | (...) ... |
| EntityFrameworkCore.cs:78:18:78:42 | call to operator implicit conversion : RawSqlString | semmle.label | call to operator implicit conversion : RawSqlString |
| EntityFrameworkCore.cs:78:32:78:42 | access to local variable taintSource : String | semmle.label | access to local variable taintSource : String |
| EntityFrameworkCore.cs:85:13:88:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:87:24:87:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:92:13:92:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:92:13:92:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:92:29:92:30 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:94:13:94:15 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:107:13:110:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:109:24:109:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:114:13:114:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:114:13:114:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:114:29:114:30 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:116:19:116:21 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:129:13:132:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:131:24:131:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:135:27:135:28 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:148:13:151:13 | { ..., ... } [Title] : String | semmle.label | { ..., ... } [Title] : String |
| EntityFrameworkCore.cs:150:25:150:33 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:155:18:155:19 | access to local variable p1 [Title] : String | semmle.label | access to local variable p1 [Title] : String |
| EntityFrameworkCore.cs:155:18:155:25 | access to property Title | semmle.label | access to property Title |
| EntityFrameworkCore.cs:167:13:174:13 | { ..., ... } [Addresses, [], Street] : String | semmle.label | { ..., ... } [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:168:29:173:17 | array creation of type Address[] [[], Street] : String | semmle.label | array creation of type Address[] [[], Street] : String |
| EntityFrameworkCore.cs:168:35:173:17 | { ..., ... } [[], Street] : String | semmle.label | { ..., ... } [[], Street] : String |
| EntityFrameworkCore.cs:169:21:172:21 | object creation of type Address [Street] : String | semmle.label | object creation of type Address [Street] : String |
| EntityFrameworkCore.cs:169:33:172:21 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:175:13:175:15 | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | [post] access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:13:175:23 | [post] access to property Persons [[], Addresses, [], Street] : String | semmle.label | [post] access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:175:29:175:30 | access to local variable p1 [Addresses, [], Street] : String | semmle.label | access to local variable p1 [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:176:13:176:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:180:13:180:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:183:13:186:13 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:187:13:187:15 | [post] access to local variable ctx [Addresses, [], Street] : String | semmle.label | [post] access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:187:13:187:25 | [post] access to property Addresses [[], Street] : String | semmle.label | [post] access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:187:31:187:32 | access to local variable a1 [Street] : String | semmle.label | access to local variable a1 [Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Addresses, [], Street] : String | semmle.label | access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:188:13:188:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Addresses, [], Street] : String | semmle.label | access to local variable ctx [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:192:13:192:15 | access to local variable ctx [Persons, [], Addresses, [], Street] : String | semmle.label | access to local variable ctx [Persons, [], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:199:13:202:13 | { ..., ... } [Name] : String | semmle.label | { ..., ... } [Name] : String |
| EntityFrameworkCore.cs:201:24:201:32 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:204:13:207:13 | { ..., ... } [Street] : String | semmle.label | { ..., ... } [Street] : String |
| EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | semmle.label | "tainted" : String |
| EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Address, Street] : String | semmle.label | { ..., ... } [Address, Street] : String |
| EntityFrameworkCore.cs:208:60:208:88 | { ..., ... } [Person, Name] : String | semmle.label | { ..., ... } [Person, Name] : String |
| EntityFrameworkCore.cs:208:71:208:72 | access to local variable p1 [Name] : String | semmle.label | access to local variable p1 [Name] : String |
| EntityFrameworkCore.cs:208:85:208:86 | access to local variable a1 [Street] : String | semmle.label | access to local variable a1 [Street] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | [post] access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:15 | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | [post] access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Address, Street] : String | semmle.label | [post] access to property PersonAddresses [[], Address, Street] : String |
| EntityFrameworkCore.cs:209:13:209:31 | [post] access to property PersonAddresses [[], Person, Name] : String | semmle.label | [post] access to property PersonAddresses [[], Person, Name] : String |
| EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Address, Street] : String | semmle.label | access to local variable personAddressMap1 [Address, Street] : String |
| EntityFrameworkCore.cs:209:37:209:53 | access to local variable personAddressMap1 [Person, Name] : String | semmle.label | access to local variable personAddressMap1 [Person, Name] : String |
| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:210:13:210:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Address, Street] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Address, Street] : String |
| EntityFrameworkCore.cs:216:13:216:15 | access to local variable ctx [PersonAddresses, [], Person, Name] : String | semmle.label | access to local variable ctx [PersonAddresses, [], Person, Name] : String |
| EntityFrameworkCore.cs:219:35:219:35 | p [Name] : String | semmle.label | p [Name] : String |
| EntityFrameworkCore.cs:222:13:222:15 | [post] access to local variable ctx [Persons, [], Name] : String | semmle.label | [post] access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:222:13:222:23 | [post] access to property Persons [[], Name] : String | semmle.label | [post] access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:222:29:222:29 | access to parameter p [Name] : String | semmle.label | access to parameter p [Name] : String |
| EntityFrameworkCore.cs:223:13:223:15 | access to local variable ctx [Persons, [], Name] : String | semmle.label | access to local variable ctx [Persons, [], Name] : String |
| EntityFrameworkCore.cs:230:18:230:28 | access to property Persons [[], Name] : String | semmle.label | access to property Persons [[], Name] : String |
| EntityFrameworkCore.cs:230:18:230:36 | call to method First [Name] : String | semmle.label | call to method First [Name] : String |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name | semmle.label | access to property Name |
| EntityFrameworkCore.cs:238:18:238:30 | access to property Addresses [[], Street] : String | semmle.label | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:238:18:238:38 | call to method First [Street] : String | semmle.label | call to method First [Street] : String |
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street | semmle.label | access to property Street |
| EntityFrameworkCore.cs:245:18:245:28 | access to property Persons [[], Addresses, [], Street] : String | semmle.label | access to property Persons [[], Addresses, [], Street] : String |
| EntityFrameworkCore.cs:245:18:245:36 | call to method First [Addresses, [], Street] : String | semmle.label | call to method First [Addresses, [], Street] : String |
| EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses [[], Street] : String | semmle.label | access to property Addresses [[], Street] : String |
| EntityFrameworkCore.cs:245:18:245:54 | call to method First [Street] : String | semmle.label | call to method First [Street] : String |
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street | semmle.label | access to property Street |
#select
| EntityFramework.cs:131:18:131:25 | access to property Title | EntityFramework.cs:126:25:126:33 | "tainted" : String | EntityFramework.cs:131:18:131:25 | access to property Title | $@ | EntityFramework.cs:126:25:126:33 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:206:18:206:41 | access to property Name | EntityFramework.cs:63:24:63:32 | "tainted" : String | EntityFramework.cs:206:18:206:41 | access to property Name | $@ | EntityFramework.cs:63:24:63:32 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:206:18:206:41 | access to property Name | EntityFramework.cs:85:24:85:32 | "tainted" : String | EntityFramework.cs:206:18:206:41 | access to property Name | $@ | EntityFramework.cs:85:24:85:32 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:206:18:206:41 | access to property Name | EntityFramework.cs:107:24:107:32 | "tainted" : String | EntityFramework.cs:206:18:206:41 | access to property Name | $@ | EntityFramework.cs:107:24:107:32 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:206:18:206:41 | access to property Name | EntityFramework.cs:177:24:177:32 | "tainted" : String | EntityFramework.cs:206:18:206:41 | access to property Name | $@ | EntityFramework.cs:177:24:177:32 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:214:18:214:45 | access to property Street | EntityFramework.cs:147:34:147:42 | "tainted" : String | EntityFramework.cs:214:18:214:45 | access to property Street | $@ | EntityFramework.cs:147:34:147:42 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:214:18:214:45 | access to property Street | EntityFramework.cs:161:26:161:34 | "tainted" : String | EntityFramework.cs:214:18:214:45 | access to property Street | $@ | EntityFramework.cs:161:26:161:34 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:214:18:214:45 | access to property Street | EntityFramework.cs:182:26:182:34 | "tainted" : String | EntityFramework.cs:214:18:214:45 | access to property Street | $@ | EntityFramework.cs:182:26:182:34 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:221:18:221:61 | access to property Street | EntityFramework.cs:147:34:147:42 | "tainted" : String | EntityFramework.cs:221:18:221:61 | access to property Street | $@ | EntityFramework.cs:147:34:147:42 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:221:18:221:61 | access to property Street | EntityFramework.cs:161:26:161:34 | "tainted" : String | EntityFramework.cs:221:18:221:61 | access to property Street | $@ | EntityFramework.cs:161:26:161:34 | "tainted" : String | "tainted" : String |
| EntityFramework.cs:221:18:221:61 | access to property Street | EntityFramework.cs:182:26:182:34 | "tainted" : String | EntityFramework.cs:221:18:221:61 | access to property Street | $@ | EntityFramework.cs:182:26:182:34 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:76:18:76:28 | access to local variable taintSource | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:76:18:76:28 | access to local variable taintSource | $@ | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:77:18:77:46 | (...) ... | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:77:18:77:46 | (...) ... | $@ | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:78:18:78:42 | (...) ... | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | EntityFrameworkCore.cs:78:18:78:42 | (...) ... | $@ | EntityFrameworkCore.cs:75:31:75:39 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:155:18:155:25 | access to property Title | EntityFrameworkCore.cs:150:25:150:33 | "tainted" : String | EntityFrameworkCore.cs:155:18:155:25 | access to property Title | $@ | EntityFrameworkCore.cs:150:25:150:33 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name | EntityFrameworkCore.cs:87:24:87:32 | "tainted" : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name | $@ | EntityFrameworkCore.cs:87:24:87:32 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name | EntityFrameworkCore.cs:109:24:109:32 | "tainted" : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name | $@ | EntityFrameworkCore.cs:109:24:109:32 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name | EntityFrameworkCore.cs:131:24:131:32 | "tainted" : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name | $@ | EntityFrameworkCore.cs:131:24:131:32 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name | EntityFrameworkCore.cs:201:24:201:32 | "tainted" : String | EntityFrameworkCore.cs:230:18:230:41 | access to property Name | $@ | EntityFrameworkCore.cs:201:24:201:32 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street | EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | EntityFrameworkCore.cs:238:18:238:45 | access to property Street | $@ | EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street | EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | EntityFrameworkCore.cs:238:18:238:45 | access to property Street | $@ | EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street | EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | EntityFrameworkCore.cs:238:18:238:45 | access to property Street | $@ | EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street | EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | EntityFrameworkCore.cs:245:18:245:61 | access to property Street | $@ | EntityFrameworkCore.cs:171:34:171:42 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street | EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | EntityFrameworkCore.cs:245:18:245:61 | access to property Street | $@ | EntityFrameworkCore.cs:185:26:185:34 | "tainted" : String | "tainted" : String |
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street | EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | EntityFrameworkCore.cs:245:18:245:61 | access to property Street | $@ | EntityFrameworkCore.cs:206:26:206:34 | "tainted" : String | "tainted" : String |

View File

@@ -1,5 +1,9 @@
/**
* @kind path-problem
*/
import csharp
import semmle.code.csharp.dataflow.TaintTracking
import DataFlow::PathGraph
class MyConfiguration extends TaintTracking::Configuration {
MyConfiguration() { this = "EntityFramework dataflow" }
@@ -11,6 +15,6 @@ class MyConfiguration extends TaintTracking::Configuration {
}
}
from MyConfiguration config, DataFlow::Node source, DataFlow::Node sink
where config.hasFlow(source, sink)
select sink, source
from DataFlow::PathNode source, DataFlow::PathNode sink, MyConfiguration conf
where conf.hasFlowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -1,64 +1,228 @@
// semmle-extractor-options: /r:System.Data.dll /r:System.ComponentModel.Primitives.dll /r:System.ComponentModel.TypeConverter.dll ${testdir}/../../../resources/stubs/EntityFramework.cs ${testdir}/../../../resources/stubs/System.Data.cs /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll
// semmle-extractor-options: /r:System.Data.dll /r:System.ComponentModel.Primitives.dll /r:System.ComponentModel.TypeConverter.dll ${testdir}/../../../resources/stubs/EntityFramework.cs ${testdir}/../../../resources/stubs/System.Data.cs /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll /r:System.Linq.dll
using System.Data.Entity;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data;
using System.Data.Common;
using System.Data.Entity;
using System.Linq;
namespace EFTests
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual int Id { get; set; }
public virtual string Name { get; set; }
[NotMapped]
public int Age { get; set; }
public string Title { get; set; }
// Navigation property
public ICollection<Address> Addresses { get; set; }
}
class Address
{
public int Id { get; set; }
public string Street { get; set; }
}
class PersonAddressMap
{
public int Id { get; set; }
public int PersonId { get; set; }
public int AddressId { get; set; }
// Navigation properties
public Person Person { get; set; }
public Address Address { get; set; }
}
class MyContext : DbContext
{
DbSet<Person> person { get; set; }
public virtual DbSet<Person> Persons { get; set; }
public virtual DbSet<Address> Addresses { get; set; }
public virtual DbSet<PersonAddressMap> PersonAddresses { get; set; }
public static MyContext GetInstance() => null;
}
class Tests
{
void FlowSources()
{
var p = new Person();
var id = p.Id; // Remote flow source
var name = p.Name; // Remote flow source
var age = p.Age; // Not a remote flow source
var title = p.Title; // Not a remote flow source
}
DbCommand command;
async void SqlSinks()
void TestSaveChangesDirectDataFlow()
{
// System.Data.Common.DbCommand.set_CommandText
command.CommandText = ""; // SqlExpr
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
// System.Data.SqlClient.SqlCommand.SqlCommand
new System.Data.SqlClient.SqlCommand(""); // SqlExpr
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.Persons.Add(p2);
ctx.SaveChanges();
this.Database.ExecuteSqlCommand(""); // SqlExpr
await this.Database.ExecuteSqlCommandAsync(""); // SqlExpr
var p3 = new Person
{
// No flow (no call to `SaveChanges`)
Name = "tainted"
};
ctx.Persons.Add(p3);
}
void TestDataFlow()
async void TestSaveChangesAsyncDirectDataFlow()
{
string taintSource = "tainted";
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
// Tainted via database, even though technically there were no reads or writes to the database in this particular case.
var p1 = new Person { Name = taintSource };
var p2 = new Person();
Sink(p2.Name); // Tainted
Sink(new Person().Name); // Tainted
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.Persons.Add(p2);
await ctx.SaveChangesAsync();
p1.Age = int.Parse(taintSource);
Sink(p2.Age); // Not tainted due to NotMappedAttribute
var p3 = new Person
{
// No flow (no call to `SaveChanges`)
Name = "tainted"
};
ctx.Persons.Add(p3);
}
void TestSaveChangesIndirectDataFlow()
{
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
AddPersonToDB(p1);
AddPersonToDB(p2);
var p3 = new Person
{
// No flow (not added)
Name = "tainted"
};
}
void TestNotMappedDataFlow()
{
var p1 = new Person
{
// Flows only to `Sink` below as `Title` it is not mapped
Title = "tainted"
};
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.SaveChanges();
Sink(p1.Title);
var p2 = new Person { Title = "untainted" };
ctx.Persons.Add(p2);
ctx.SaveChanges();
Sink(p2.Title);
}
void TestNavigationPropertyReadFlow()
{
var ctx = MyContext.GetInstance();
var p1 = new Person
{
Addresses = new[] {
new Address {
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
}
}
};
ctx.Persons.Add(p1);
ctx.SaveChanges();
var p2 = new Person { Addresses = new[] { new Address { Street = "untainted" } } };
ctx.Persons.Add(p2);
ctx.SaveChanges();
var a1 = new Address
{
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
};
ctx.Addresses.Add(a1);
ctx.SaveChanges();
var a2 = new Address { Street = "untainted" };
ctx.Addresses.Add(a2);
ctx.SaveChanges();
}
void TestNavigationPropertyStoreFlow()
{
var ctx = MyContext.GetInstance();
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var a1 = new Address
{
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
};
var personAddressMap1 = new PersonAddressMap() { Person = p1, Address = a1 };
ctx.PersonAddresses.Add(personAddressMap1);
ctx.SaveChanges();
var p2 = new Person { Name = "untainted" };
var a2 = new Address { Street = "untainted" };
var personAddressMap2 = new PersonAddressMap() { Person = p2, Address = a2 };
ctx.PersonAddresses.Add(personAddressMap2);
ctx.SaveChanges();
}
void AddPersonToDB(Person p)
{
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p);
ctx.SaveChanges();
}
void ReadFirstPersonFromDB()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Persons.First().Id);
Sink(ctx.Persons.First().Name);
Sink(ctx.Persons.First().Title);
}
void ReadFirstAddressFromDB()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Addresses.First().Id);
Sink(ctx.Addresses.First().Street);
}
void ReadFirstPersonAddress()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Persons.First().Addresses.First().Id);
Sink(ctx.Persons.First().Addresses.First().Street);
}
void Sink(object @object)
{
}
}
}

View File

@@ -1,38 +1,66 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Linq;
namespace EFCoreTests
{
class Person
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public int Age { get; set; }
public virtual int Id { get; set; }
public virtual string Name { get; set; }
[NotMapped]
public string Title { get; set; }
// Navigation property
public ICollection<Address> Addresses { get; set; }
}
class Address
{
public int Id { get; set; }
public string Street { get; set; }
}
class PersonAddressMap
{
public int Id { get; set; }
public int PersonId { get; set; }
public int AddressId { get; set; }
// Navigation properties
public Person Person { get; set; }
public Address Address { get; set; }
}
class MyContext : DbContext
{
DbSet<Person> person;
public virtual DbSet<Person> Persons { get; set; }
public virtual DbSet<Address> Addresses { get; set; }
public virtual DbSet<PersonAddressMap> PersonAddresses { get; set; }
public static MyContext GetInstance() => null;
}
class Tests
{
void FlowSources()
{
var p = new Person();
var id = p.Id; // Remote flow source
var name = p.Name; // Remote flow source
var age = p.Age; // Not a remote flow source
var title = p.Title; // Not a remote flow source
}
Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder builder;
async void SqlExprs()
async void SqlExprs(MyContext ctx)
{
// Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlCommand
this.Database.ExecuteSqlCommand(""); // SqlExpr
await this.Database.ExecuteSqlCommandAsync(""); // SqlExpr
ctx.Database.ExecuteSqlCommand(""); // SqlExpr
await ctx.Database.ExecuteSqlCommandAsync(""); // SqlExpr
// Microsoft.EntityFrameworkCore.Storage.IRawSqlCommandBuilder.Build
builder.Build(""); // SqlExpr
@@ -42,26 +70,179 @@ namespace EFCoreTests
RawSqlString str = ""; // SqlExpr
}
void TestDataFlow()
void TestRawSqlStringDataFlow()
{
var taintSource = "tainted";
var untaintedSource = "untainted";
Sink(taintSource); // Tainted
Sink(new RawSqlString(taintSource)); // Tainted
Sink((RawSqlString)taintSource); // Tainted
Sink((RawSqlString)(FormattableString)$"{taintSource}"); // Tainted, but not reported because conversion operator is in a stub .cs file
}
// Tainted via database, even though technically there were no reads or writes to the database in this particular case.
var p1 = new Person { Name = taintSource };
p1.Name = untaintedSource;
var p2 = new Person();
void TestSaveChangesDirectDataFlow()
{
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
Sink(p2.Name); // Tainted
Sink(new Person().Name); // Tainted
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.Persons.Add(p2);
ctx.SaveChanges();
p1.Age = int.Parse(taintSource);
Sink(p2.Age); // Not tainted due to NotMappedAttribute
var p3 = new Person
{
// No flow (no call to `SaveChanges`)
Name = "tainted"
};
ctx.Persons.Add(p3);
}
async void TestSaveChangesAsyncDirectDataFlow()
{
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.Persons.Add(p2);
await ctx.SaveChangesAsync();
var p3 = new Person
{
// No flow (no call to `SaveChanges`)
Name = "tainted"
};
ctx.Persons.Add(p3);
}
void TestSaveChangesIndirectDataFlow()
{
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var p2 = new Person { Name = "untainted" };
AddPersonToDB(p1);
AddPersonToDB(p2);
var p3 = new Person
{
// No flow (not added)
Name = "tainted"
};
}
void TestNotMappedDataFlow()
{
var p1 = new Person
{
// Flows only to `Sink` below as `Title` it is not mapped
Title = "tainted"
};
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p1);
ctx.SaveChanges();
Sink(p1.Title);
var p2 = new Person { Title = "untainted" };
ctx.Persons.Add(p2);
ctx.SaveChanges();
Sink(p2.Title);
}
void TestNavigationPropertyReadFlow()
{
var ctx = MyContext.GetInstance();
var p1 = new Person
{
Addresses = new[] {
new Address {
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
}
}
};
ctx.Persons.Add(p1);
ctx.SaveChanges();
var p2 = new Person { Addresses = new[] { new Address { Street = "untainted" } } };
ctx.Persons.Add(p2);
ctx.SaveChanges();
var a1 = new Address
{
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
};
ctx.Addresses.Add(a1);
ctx.SaveChanges();
var a2 = new Address { Street = "untainted" };
ctx.Addresses.Add(a2);
ctx.SaveChanges();
}
void TestNavigationPropertyStoreFlow()
{
var ctx = MyContext.GetInstance();
var p1 = new Person
{
// Flows to `ReadFirstPersonFromDB`
Name = "tainted"
};
var a1 = new Address
{
// Flows to `ReadFirstAddressFromDB` and `ReadFirstPersonAddress`
Street = "tainted"
};
var personAddressMap1 = new PersonAddressMap() { Person = p1, Address = a1 };
ctx.PersonAddresses.Add(personAddressMap1);
ctx.SaveChanges();
var p2 = new Person { Name = "untainted" };
var a2 = new Address { Street = "untainted" };
var personAddressMap2 = new PersonAddressMap() { Person = p2, Address = a2 };
ctx.PersonAddresses.Add(personAddressMap2);
ctx.SaveChanges();
}
void AddPersonToDB(Person p)
{
var ctx = MyContext.GetInstance();
ctx.Persons.Add(p);
ctx.SaveChanges();
}
void ReadFirstPersonFromDB()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Persons.First().Id);
Sink(ctx.Persons.First().Name);
Sink(ctx.Persons.First().Title);
}
void ReadFirstAddressFromDB()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Addresses.First().Id);
Sink(ctx.Addresses.First().Street);
}
void ReadFirstPersonAddress()
{
var ctx = MyContext.GetInstance();
Sink(ctx.Persons.First().Addresses.First().Id);
Sink(ctx.Persons.First().Addresses.First().Street);
}
void Sink(object @object)

View File

@@ -0,0 +1,158 @@
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], AddressId] -> jump to get_PersonAddresses (return) [[], AddressId] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Id] -> jump to get_PersonAddresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_Persons (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_Persons (return) [[], Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [PersonAddresses, [], PersonId] -> jump to get_PersonAddresses (return) [[], PersonId] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Id] -> jump to get_Persons (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChanges() | this parameter [Persons, [], Name] -> jump to get_Persons (return) [[], Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], AddressId] -> jump to get_PersonAddresses (return) [[], AddressId] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Id] -> jump to get_PersonAddresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_Persons (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_Persons (return) [[], Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], PersonId] -> jump to get_PersonAddresses (return) [[], PersonId] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Id] -> jump to get_Persons (return) [[], Id] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync() | this parameter [Persons, [], Name] -> jump to get_Persons (return) [[], Name] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.Add(T) | parameter 0 -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.AddAsync(T) | parameter 0 -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.AddRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.AddRangeAsync(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.Attach(T) | parameter 0 -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.AttachRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.Update(T) | parameter 0 -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.DbSet<>.UpdateRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| Microsoft.EntityFrameworkCore.RawSqlString.RawSqlString(string) | parameter 0 -> return | false |
| Microsoft.EntityFrameworkCore.RawSqlString.implicit conversion(string) | parameter 0 -> return | false |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], AddressId] -> jump to get_PersonAddresses (return) [[], AddressId] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Id] -> jump to get_PersonAddresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_Persons (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_Persons (return) [[], Name] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [PersonAddresses, [], PersonId] -> jump to get_PersonAddresses (return) [[], PersonId] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Id] -> jump to get_Persons (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| System.Data.Entity.DbContext.SaveChanges() | this parameter [Persons, [], Name] -> jump to get_Persons (return) [[], Name] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Address, Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], AddressId] -> jump to get_PersonAddresses (return) [[], AddressId] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Id] -> jump to get_PersonAddresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Id] -> jump to get_Persons (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], Person, Name] -> jump to get_Persons (return) [[], Name] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [PersonAddresses, [], PersonId] -> jump to get_PersonAddresses (return) [[], PersonId] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Addresses (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Address, Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Id] -> jump to get_Persons (return) [[], Addresses, [], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Addresses (return) [[], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Address, Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_PersonAddresses (return) [[], Person, Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Addresses, [], Street] -> jump to get_Persons (return) [[], Addresses, [], Street] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Id] -> jump to get_PersonAddresses (return) [[], Person, Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Id] -> jump to get_Persons (return) [[], Id] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Name] -> jump to get_PersonAddresses (return) [[], Person, Name] | true |
| System.Data.Entity.DbContext.SaveChangesAsync() | this parameter [Persons, [], Name] -> jump to get_Persons (return) [[], Name] | true |
| System.Data.Entity.DbSet<>.Add(T) | parameter 0 -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.AddAsync(T) | parameter 0 -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.AddRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.AddRangeAsync(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.Attach(T) | parameter 0 -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.AttachRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.Update(T) | parameter 0 -> this parameter [[]] | true |
| System.Data.Entity.DbSet<>.UpdateRange(IEnumerable<T>) | parameter 0 [[]] -> this parameter [[]] | true |

View File

@@ -0,0 +1,6 @@
import semmle.code.csharp.dataflow.FlowSummary::TestOutput
import semmle.code.csharp.frameworks.EntityFramework::EntityFramework
private class IncludeEFSummarizedCallable extends RelevantSummarizedCallable {
IncludeEFSummarizedCallable() { this instanceof EFSummarizedCallable }
}

View File

@@ -1,4 +1,20 @@
| EntityFramework.cs:12:20:12:21 | Id |
| EntityFramework.cs:13:23:13:26 | Name |
| EntityFrameworkCore.cs:10:18:10:19 | Id |
| EntityFrameworkCore.cs:11:21:11:24 | Name |
| EntityFramework.cs:12:28:12:29 | Id |
| EntityFramework.cs:13:31:13:34 | Name |
| EntityFramework.cs:19:37:19:45 | Addresses |
| EntityFramework.cs:24:20:24:21 | Id |
| EntityFramework.cs:25:23:25:28 | Street |
| EntityFramework.cs:30:20:30:21 | Id |
| EntityFramework.cs:31:20:31:27 | PersonId |
| EntityFramework.cs:32:20:32:28 | AddressId |
| EntityFramework.cs:35:23:35:28 | Person |
| EntityFramework.cs:36:24:36:30 | Address |
| EntityFrameworkCore.cs:11:28:11:29 | Id |
| EntityFrameworkCore.cs:12:31:12:34 | Name |
| EntityFrameworkCore.cs:18:37:18:45 | Addresses |
| EntityFrameworkCore.cs:23:20:23:21 | Id |
| EntityFrameworkCore.cs:24:23:24:28 | Street |
| EntityFrameworkCore.cs:29:20:29:21 | Id |
| EntityFrameworkCore.cs:30:20:30:27 | PersonId |
| EntityFrameworkCore.cs:31:20:31:28 | AddressId |
| EntityFrameworkCore.cs:34:23:34:28 | Person |
| EntityFrameworkCore.cs:35:24:35:30 | Address |

View File

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

View File

@@ -1,8 +1,20 @@
| EntityFramework.cs:26:22:26:25 | access to property Id |
| EntityFramework.cs:27:24:27:29 | access to property Name |
| EntityFramework.cs:52:18:52:24 | access to property Name |
| EntityFramework.cs:53:18:53:34 | access to property Name |
| EntityFrameworkCore.cs:24:22:24:25 | access to property Id |
| EntityFrameworkCore.cs:25:24:25:29 | access to property Name |
| EntityFrameworkCore.cs:60:18:60:24 | access to property Name |
| EntityFrameworkCore.cs:61:18:61:34 | access to property Name |
| EntityFramework.cs:53:22:53:25 | access to property Id |
| EntityFramework.cs:54:24:54:29 | access to property Name |
| EntityFramework.cs:205:18:205:39 | access to property Id |
| EntityFramework.cs:206:18:206:41 | access to property Name |
| EntityFramework.cs:213:18:213:41 | access to property Id |
| EntityFramework.cs:214:18:214:45 | access to property Street |
| EntityFramework.cs:220:18:220:46 | access to property Addresses |
| EntityFramework.cs:220:18:220:57 | access to property Id |
| EntityFramework.cs:221:18:221:46 | access to property Addresses |
| EntityFramework.cs:221:18:221:61 | access to property Street |
| EntityFrameworkCore.cs:52:22:52:25 | access to property Id |
| EntityFrameworkCore.cs:53:24:53:29 | access to property Name |
| EntityFrameworkCore.cs:229:18:229:39 | access to property Id |
| EntityFrameworkCore.cs:230:18:230:41 | access to property Name |
| EntityFrameworkCore.cs:237:18:237:41 | access to property Id |
| EntityFrameworkCore.cs:238:18:238:45 | access to property Street |
| EntityFrameworkCore.cs:244:18:244:46 | access to property Addresses |
| EntityFrameworkCore.cs:244:18:244:57 | access to property Id |
| EntityFrameworkCore.cs:245:18:245:46 | access to property Addresses |
| EntityFrameworkCore.cs:245:18:245:61 | access to property Street |

View File

@@ -1,5 +1,5 @@
import csharp
from Expr e, Location loc
where e.getLocation() = loc
where e.getLocation() = loc and e.fromSource()
select loc.getStartLine(), loc.getStartColumn(), e.getParent(), e, e.getType().toString()

File diff suppressed because one or more lines are too long

View File

@@ -10,8 +10,18 @@ namespace System.Data.Entity
{
}
public class DbSet<T>
public class DbSet<T> : IEnumerable<T>
{
public void Add(T t) { }
public System.Threading.Tasks.Task<int> AddAsync(T t) => null;
public void AddRange(IEnumerable<T> t) { }
public System.Threading.Tasks.Task<int> AddRangeAsync(IEnumerable<T> t) => null;
public void Attach(T t) { }
public void AttachRange(IEnumerable<T> t) { }
public void Update(T t) { }
public void UpdateRange(IEnumerable<T> t) { }
IEnumerator<T> IEnumerable<T>.GetEnumerator() => null;
IEnumerator IEnumerable.GetEnumerator() => null;
}
public class Database
@@ -27,6 +37,8 @@ namespace System.Data.Entity
public void Dispose() { }
public Database Database => null;
public Infrastructure.DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters) => null;
public int SaveChanges() => 0;
public System.Threading.Tasks.Task<int> SaveChangesAsync() => null;
}
}
@@ -47,35 +59,46 @@ namespace System.Data.Entity.Infrastructure
namespace Microsoft.EntityFrameworkCore
{
public class DbSet<T>
public class DbSet<T> : IEnumerable<T>
{
public void Add(T t) { }
public System.Threading.Tasks.Task<int> AddAsync(T t) => null;
public void AddRange(IEnumerable<T> t) { }
public System.Threading.Tasks.Task<int> AddRangeAsync(IEnumerable<T> t) => null;
public void Attach(T t) { }
public void AttachRange(IEnumerable<T> t) { }
public void Update(T t) { }
public void UpdateRange(IEnumerable<T> t) { }
IEnumerator<T> IEnumerable<T>.GetEnumerator() => null;
IEnumerator IEnumerable.GetEnumerator() => null;
}
public class DbContext : IDisposable
{
public void Dispose() { }
public virtual Infrastructure.DatabaseFacade Database => null;
// public Infrastructure.DbRawSqlQuery<TElement> SqlQuery<TElement>(string sql, params object[] parameters) => null;
public int SaveChanges() => 0;
public System.Threading.Tasks.Task<int> SaveChangesAsync() => null;
}
namespace Infrastructure
{
public class DatabaseFacade
{
}
public class DatabaseFacade
{
}
}
public static class RelationalDatabaseFacaseExtensions
{
public static void ExecuteSqlCommand(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) {}
public static Task ExecuteSqlCommandAsync(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) => throw null;
public static void ExecuteSqlCommand(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) { }
public static Task ExecuteSqlCommandAsync(this Infrastructure.DatabaseFacade db, string sql, params object[] parameters) => throw null;
}
struct RawSqlString
{
public RawSqlString(string str) { }
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString (FormattableString fs) => throw null;
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString (string s) => throw null;
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString(FormattableString fs) => throw null;
public static implicit operator Microsoft.EntityFrameworkCore.RawSqlString(string s) => throw null;
}
}

View File

@@ -18,7 +18,7 @@ Project structure
The documentation currently consists of the following Sphinx projects:
- ``learn-ql``help topics to help you learn CodeQL and write queries
- ``ql-handbook``an overview of important concepts in QL, the language that underlies CodeQL analysis
- ``ql-language-reference``an overview of important concepts in QL, the language that underlies CodeQL analysis
- ``support``the languages and frameworks currently supported in CodeQL analysis
- ``ql-training``source files for the CodeQL training and variant analysis examples slide decks

View File

@@ -14,17 +14,17 @@ The following sections provide a brief introduction to data flow analysis with C
See the following tutorials for more information about analyzing data flow in specific languages:
- ":doc:`Analyzing data flow in C/C++ <cpp/dataflow>`"
- ":doc:`Analyzing data flow in C# <csharp/dataflow>`"
- ":doc:`Analyzing data flow in Java <java/dataflow>`"
- ":doc:`Analyzing data flow in JavaScript/TypeScript <javascript/dataflow>`"
- ":doc:`Analyzing data flow and tracking tainted data in Python <python/taint-tracking>`"
- ":doc:`Analyzing data flow in C/C++ <cpp/analyzing-data-flow-in-cpp>`"
- ":doc:`Analyzing data flow in C# <csharp/analyzing-data-flow-in-csharp>`"
- ":doc:`Analyzing data flow in Java <java/analyzing-data-flow-in-java>`"
- ":doc:`Analyzing data flow in JavaScript/TypeScript <javascript/analyzing-data-flow-in-javascript>`"
- ":doc:`Analyzing data flow and tracking tainted data in Python <python/analyzing-data-flow-and-tracking-tainted-data-in-python>`"
.. pull-quote::
Note
Data flow analysis is used extensively in path queries. To learn more about path queries, see ":doc:`Creating path queries <writing-queries/path-queries>`."
Data flow analysis is used extensively in path queries. To learn more about path queries, see ":doc:`Creating path queries <writing-queries/creating-path-queries>`."
.. _data-flow-graph:
@@ -49,8 +49,8 @@ flow between functions and through object properties. Global data flow, however,
graph that do not precisely correspond to the flow of values, but model whether some value at runtime may be derived from another, for instance through a string manipulating
operation.
The data flow graph is computed using `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ to model the program elements that represent the graph's nodes.
The flow of data between the nodes is modeled using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ to compute the graph's edges.
The data flow graph is computed using `classes <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__ to model the program elements that represent the graph's nodes.
The flow of data between the nodes is modeled using `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ to compute the graph's edges.
Computing an accurate and complete data flow graph presents several challenges:
@@ -82,5 +82,5 @@ These flow steps are modeled in the taint-tracking library using predicates that
Further reading
***************
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"

View File

@@ -14,7 +14,7 @@ Read the examples below to learn how to define predicates and classes in QL. The
Select the southerners
----------------------
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``isSouthern``:
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ ``isSouthern``:
.. code-block:: ql
@@ -41,7 +41,7 @@ You can now list all southerners using:
where isSouthern(p)
select p
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
.. code-block:: ql

View File

@@ -20,8 +20,8 @@ A solution should be a set of instructions for how to ferry the items, such as "
across the river, and come back with nothing. Then ferry the cabbage across, and come back with ..."
There are lots of ways to approach this problem and implement it in QL. Before you start, make
sure that you are familiar with how to define `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__
and `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ in QL.
sure that you are familiar with how to define `classes <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__
and `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ in QL.
The following walkthrough is just one of many possible implementations, so have a go at writing your
own query too! To find more example queries, see the list :ref:`below <alternatives>`.
@@ -69,7 +69,7 @@ For example, if the man is on the left shore, the goat on the right shore, and t
shore, the state should be ``Left, Right, Left, Left``.
You may find it helpful to introduce some variables that refer to the shore on which the man and the cargo items are. These
temporary variables in the body of a class are called `fields <https://help.semmle.com/QL/ql-handbook/types.html#fields>`__.
temporary variables in the body of a class are called `fields <https://help.semmle.com/QL/ql-language-reference/types.html#fields>`__.
.. container:: toggle
@@ -159,12 +159,12 @@ could ferry the goat back and forth any number of times without ever reaching an
Such a path would have an infinite number of river crossings without ever solving the puzzle.
One way to restrict our paths to a finite number of river crossings is to define a
`member predicate <https://help.semmle.com/QL/ql-handbook/types.html#member-predicates>`__
`member predicate <https://help.semmle.com/QL/ql-language-reference/types.html#member-predicates>`__
``State reachesVia(string path, int steps)``.
The result of this predicate is any state that is reachable from the current state (``this``) via
the given path in a specified finite number of steps.
You can write this as a `recursive predicate <https://help.semmle.com/QL/ql-handbook/recursion.html>`__,
You can write this as a `recursive predicate <https://help.semmle.com/QL/ql-language-reference/recursion.html>`__,
with the following base case and recursion step:
- If ``this`` *is* the result state, then it (trivially) reaches the result state via an
@@ -203,7 +203,7 @@ the given path without revisiting any previously visited states.
revisiting any previous states, and there is a ``safeFerry`` action from the intermediate state to
the result state.
(Hint: To check whether a state has previously been visited, you could check if
there is an `index of <https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string>`__
there is an `index of <ql-language-specification#built-ins-for-string>`__
``visitedStates`` at which the state occurs.)
.. container:: toggle
@@ -218,7 +218,7 @@ the given path without revisiting any previously visited states.
Display the results
~~~~~~~~~~~~~~~~~~~
Once you've defined all the necessary classes and predicates, write a `select clause <https://help.semmle.com/QL/ql-handbook/queries.html#select-clauses>`__
Once you've defined all the necessary classes and predicates, write a `select clause <https://help.semmle.com/QL/ql-language-reference/queries.html#select-clauses>`__
that returns the resulting path.
.. container:: toggle
@@ -230,7 +230,7 @@ that returns the resulting path.
.. literalinclude:: river-crossing.ql
:lines: 115-117
The `don't-care expression <https://help.semmle.com/QL/ql-handbook/expressions.html#don-t-care-expressions>`__ (``_``),
The `don't-care expression <https://help.semmle.com/QL/ql-language-reference/expressions.html#don-t-care-expressions>`__ (``_``),
as the second argument to the ``reachesVia`` predicate, represents any value of ``visitedStates``.
For now, the path defined in ``reachesVia`` just lists the order of cargo items to ferry.
@@ -254,12 +254,12 @@ Here are some more example queries that solve the river crossing puzzle:
`See solution in the query console on LGTM.com <https://lgtm.com/query/659603593702729237/>`__
#. This query models the man and the cargo items in a different way, using an
`abstract <https://help.semmle.com/QL/ql-handbook/annotations.html#abstract>`__
`abstract <https://help.semmle.com/QL/ql-language-reference/annotations.html#abstract>`__
class and predicate. It also displays the resulting path in a more visual way.
`See solution in the query console on LGTM.com <https://lgtm.com/query/1025323464423811143/>`__
#. This query introduces `algebraic datatypes <https://help.semmle.com/QL/ql-handbook/types.html#algebraic-datatypes>`__
#. This query introduces `algebraic datatypes <https://help.semmle.com/QL/ql-language-reference/types.html#algebraic-datatypes>`__
to model the situation, instead of defining everything as a subclass of ``string``.
`See solution in the query console on LGTM.com <https://lgtm.com/query/7260748307619718263/>`__

View File

@@ -106,7 +106,7 @@ You can translate this into QL as follows:
result = parentOf(ancestorOf(p))
}
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-handbook/recursion.html>`__.
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-language-reference/recursion.html>`__.
This kind of recursion, where the same operation (in this case ``parentOf()``) is applied multiple times, is very common in QL, and is known as the *transitive closure* of the operation. There are two special symbols ``+`` and ``*`` that are extremely useful when working with transitive closures:

View File

@@ -48,12 +48,12 @@ There is too much information to search through by hand, so you decide to use yo
#. Open the `query console on LGTM.com <https://lgtm.com/query>`__ to get started.
#. Select a language and a demo project. For this tutorial, any language and project will do.
#. Delete the default code ``import <language> select "hello world"``.
#. Delete the default code ``import <ql-language-specification> select "hello world"``.
QL libraries
------------
We've defined a number of QL `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age.
We've defined a number of QL `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age.
+--------------------+----------------------------------------------------------------------------------------+
| Predicate | Description |
@@ -84,14 +84,14 @@ The villagers answered "yes" to the question "Is the thief taller than 150cm?" T
where t.getHeight() > 150
select t
The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type <https://help.semmle.com/QL/ql-handbook/types.html>`__ of ``t`` is ``Person``.
The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type <https://help.semmle.com/QL/ql-language-reference/types.html>`__ of ``t`` is ``Person``.
Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries:
Logical connectives
-------------------
Using `logical connectives <https://help.semmle.com/QL/ql-handbook/formulas.html#logical-connectives>`__, you can write more complex queries that combine different pieces of information.
Using `logical connectives <https://help.semmle.com/QL/ql-language-reference/formulas.html#logical-connectives>`__, you can write more complex queries that combine different pieces of information.
For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates:
@@ -157,7 +157,7 @@ Notice that we have only temporarily introduced the variable ``c`` and we didn't
Note
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``.
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-language-reference/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``.
The real investigation
----------------------
@@ -218,7 +218,7 @@ You are getting closer to solving the mystery! Unfortunately, you still have qui
More advanced queries
---------------------
What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates <https://help.semmle.com/QL/ql-handbook/expressions.html#aggregations>`__.
What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates <https://help.semmle.com/QL/ql-language-reference/expressions.html#aggregations>`__.
In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is:

View File

@@ -6,7 +6,7 @@ You can use data flow analysis to track the flow of potentially malicious or ins
About data flow
---------------
Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../intro-to-data-flow>`."
Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../about-data-flow-analysis>`."
Local data flow
---------------
@@ -390,7 +390,7 @@ Exercise 4
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/cpp-further-reading.rst

Some files were not shown because too many files have changed in this diff Show More