mirror of
https://github.com/github/codeql.git
synced 2026-07-20 18:58:36 +02:00
Merge branch 'main' into jwt
This commit is contained in:
@@ -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"
|
||||
]
|
||||
}
|
||||
|
||||
22
cpp/ql/src/IDEContextual.qll
Normal file
22
cpp/ql/src/IDEContextual.qll
Normal 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("//", "/")
|
||||
}
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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 {
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
* ```
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
* ```
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 | |
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 { ..., ... }.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
csharp/ql/src/IDEContextual.qll
Normal file
22
csharp/ql/src/IDEContextual.qll
Normal 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("//", "/")
|
||||
}
|
||||
@@ -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 }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 + ")"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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") }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Expr argument
|
||||
where argument.fromSource()
|
||||
select argument, argument.getExplicitArgumentName()
|
||||
|
||||
27
csharp/ql/test/library-tests/attributes/Assembly1.cs_
Normal file
27
csharp/ql/test/library-tests/attributes/Assembly1.cs_
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
csharp/ql/test/library-tests/attributes/Assembly1.dll
Normal file
BIN
csharp/ql/test/library-tests/attributes/Assembly1.dll
Normal file
Binary file not shown.
@@ -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[] |
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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 | ; |
|
||||
|
||||
@@ -3,4 +3,5 @@ import Common
|
||||
import ControlFlow::Internal
|
||||
|
||||
from SourceControlFlowElement cfe
|
||||
where cfe.fromSource()
|
||||
select cfe, first(cfe)
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from IntLiteral l
|
||||
where l.fromSource()
|
||||
select l
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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 |
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>`__"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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/>`__
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user