Merge branch 'main' into loc2 and accept new test results.

This commit is contained in:
Geoffrey White
2024-10-01 16:10:30 +01:00
726 changed files with 8153 additions and 4658 deletions

View File

@@ -128,6 +128,7 @@ use_repo(
"kotlin-compiler-1.9.20-Beta",
"kotlin-compiler-2.0.0-RC1",
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
@@ -141,6 +142,7 @@ use_repo(
"kotlin-compiler-embeddable-1.9.20-Beta",
"kotlin-compiler-embeddable-2.0.0-RC1",
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
@@ -154,6 +156,7 @@ use_repo(
"kotlin-stdlib-1.9.20-Beta",
"kotlin-stdlib-2.0.0-RC1",
"kotlin-stdlib-2.0.20-Beta2",
"kotlin-stdlib-2.1.0-Beta1",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -57,10 +57,6 @@
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
],
"Model as Data Generation Java/C# - CaptureModels": [
"java/ql/src/utils/modelgenerator/internal/CaptureModels.qll",
"csharp/ql/src/utils/modelgenerator/internal/CaptureModels.qll"
],
"Sign Java/C#": [
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"

View File

@@ -1,3 +1,7 @@
## 2.0.1
No user-facing changes.
## 2.0.0
### Breaking Changes

View File

@@ -0,0 +1,3 @@
## 2.0.1
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.0.0
lastReleaseVersion: 2.0.1

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-all
version: 2.0.1-dev
version: 2.0.2-dev
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp

View File

@@ -651,7 +651,8 @@ class FunctionDeclarationEntry extends DeclarationEntry, @fun_decl {
/**
* Holds if this declaration is an implicit function declaration, that is,
* where a function is used before it is declared (under older C standards).
* where a function is used before it is declared (under older C standards,
* or when there were parse errors).
*/
predicate isImplicit() { fun_implicit(underlyingElement(this)) }

View File

@@ -39,8 +39,8 @@ class Type extends Locatable, @type {
/**
* Gets a specifier of this type, recursively looking through `typedef` and
* `decltype`. For example, in the context of `typedef const int *restrict
* t`, the type `volatile t` has specifiers `volatile` and `restrict` but not
* `decltype`. For example, in the context of `typedef const int *restrict t`,
* the type `volatile t` has specifiers `volatile` and `restrict` but not
* `const` since the `const` is attached to the type being pointed to rather
* than the pointer itself.
*/

View File

@@ -118,19 +118,34 @@ abstract class FormattingFunction extends ArrayFunction, TaintFunction {
/**
* Gets the position of the first format argument, corresponding with
* the first format specifier in the format string.
* the first format specifier in the format string. We ignore all
* implicit function definitions.
*/
int getFirstFormatArgumentIndex() {
result = this.getNumberOfParameters() and
// the formatting function either has a definition in the snapshot, or all
// The formatting function either has a definition in the snapshot, or all
// `DeclarationEntry`s agree on the number of parameters (otherwise we don't
// really know the correct number)
(
this.hasDefinition()
or
forall(FunctionDeclarationEntry fde | fde = this.getADeclarationEntry() |
result = fde.getNumberOfParameters()
)
if this.hasDefinition()
then result = this.getDefinition().getNumberOfParameters()
else result = this.getNumberOfExplicitParameters()
}
/**
* Gets a non-implicit function declaration entry.
*/
private FunctionDeclarationEntry getAnExplicitDeclarationEntry() {
result = this.getADeclarationEntry() and
not result.isImplicit()
}
/**
* Gets the number of parameters, excluding any parameters that have been defined
* from implicit function declarations. If there is some inconsistency in the number
* of parameters, then don't return anything.
*/
private int getNumberOfExplicitParameters() {
forex(FunctionDeclarationEntry fde | fde = this.getAnExplicitDeclarationEntry() |
result = fde.getNumberOfParameters()
)
}

View File

@@ -72,7 +72,6 @@ module FlowFromFree<FlowFromFreeParamSig P> {
predicate isSource(DataFlow::Node node, FlowState state) { isFree(node, _, state, _) }
pragma[inline]
predicate isSink(DataFlow::Node sink, FlowState state) {
exists(Expr e, DataFlow::Node source, DeallocationExpr dealloc |
P::isSink(sink, e) and

View File

@@ -1,9 +1,15 @@
## 1.2.4
### Minor Analysis Improvements
* Fixed false positives in the `cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.
## 1.2.3
### Minor Analysis Improvements
* Removed false positives caused by buffer accesses in unreachable code.
* Removed false positives caused by inconsistent type checking.
* Removed false positives caused by buffer accesses in unreachable code
* Removed false positives caused by inconsistent type checking
* Add modeling of C functions that don't throw, thereby increasing the precision of the `cpp/incorrect-allocation-error-handling` ("Incorrect allocation-error handling") query. The query now produces additional true positives.
## 1.2.2

View File

@@ -13,23 +13,85 @@
*/
import cpp
import semmle.code.cpp.controlflow.Guards
class WideCharPointerType extends PointerType {
WideCharPointerType() { this.getBaseType() instanceof WideCharType }
}
/**
* Given type `t`, recurses through and returns all
* intermediate base types, including `t`.
*/
Type getABaseType(Type t) {
result = t
or
result = getABaseType(t.(DerivedType).getBaseType())
or
result = getABaseType(t.(TypedefType).getBaseType())
}
/**
* A type that may also be `CharPointerType`, but that are likely used as arbitrary buffers.
*/
class UnlikelyToBeAStringType extends Type {
UnlikelyToBeAStringType() {
this.(PointerType).getBaseType().(CharType).isUnsigned() or
this.(PointerType).getBaseType().getName().toLowerCase().matches("%byte") or
this.getName().toLowerCase().matches("%byte") or
this.(PointerType).getBaseType().hasName("uint8_t")
exists(Type targ | getABaseType(this) = targ |
// NOTE: not using CharType isUnsigned, but rather look for any explicitly declared unsigned
// char types. Assuming these are used for buffers, not strings.
targ.(CharType).getName().toLowerCase().matches("unsigned%") or
targ.getName().toLowerCase().matches(["uint8_t", "%byte%"])
)
}
}
// Types that can be wide depending on the UNICODE macro
// see https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
class UnicodeMacroDependentWidthType extends Type {
UnicodeMacroDependentWidthType() {
exists(Type targ | getABaseType(this) = targ |
targ.getName() in [
"LPCTSTR",
"LPTSTR",
"PCTSTR",
"PTSTR",
"TBYTE",
"TCHAR"
]
)
}
}
class UnicodeMacro extends Macro {
UnicodeMacro() { this.getName().toLowerCase().matches("%unicode%") }
}
class UnicodeMacroInvocation extends MacroInvocation {
UnicodeMacroInvocation() { this.getMacro() instanceof UnicodeMacro }
}
/**
* Holds when a expression whose type is UnicodeMacroDependentWidthType and
* is observed to be guarded by a check involving a bitwise-and operation
* with a UnicodeMacroInvocation.
* Such expressions are assumed to be checked dynamically, i.e.,
* the flag would indicate if UNICODE typing is set correctly to allow
* or disallow a widening cast.
*/
predicate isLikelyDynamicallyChecked(Expr e) {
e.getType() instanceof UnicodeMacroDependentWidthType and
exists(GuardCondition gc, BitwiseAndExpr bai, UnicodeMacroInvocation umi |
bai.getAnOperand() = umi.getExpr()
|
// bai == 0 is false when reaching `e.getBasicBlock()`.
// That is, bai != 0 when reaching `e.getBasicBlock()`.
gc.ensuresEq(bai, 0, e.getBasicBlock(), false)
or
// bai == k and k != 0 is true when reaching `e.getBasicBlock()`.
gc.ensuresEq(bai, any(int k | k != 0), e.getBasicBlock(), true)
)
}
from Expr e1, Cast e2
where
e2 = e1.getConversion() and
@@ -42,7 +104,11 @@ where
not e1.getType() instanceof UnlikelyToBeAStringType and
// Avoid castings from 'new' expressions as typically these will be safe
// Example: `__Type* ret = reinterpret_cast<__Type*>(New(m_pmo) char[num * sizeof(__Type)]);`
not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1)
not exists(NewOrNewArrayExpr newExpr | newExpr.getAChild*() = e1) and
// Avoid cases where the cast is guarded by a check to determine if
// unicode encoding is enabled in such a way to disallow the dangerous cast
// at runtime.
not isLikelyDynamicallyChecked(e1)
select e1,
"Conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
". Use of invalid string can lead to undefined behavior."

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to detect byte arrays.
* The `cpp/incorrect-string-type-conversion` query now produces fewer false positives caused by failure to recognize dynamic checks prior to possible dangerous widening.

View File

@@ -0,0 +1,5 @@
## 1.2.4
### Minor Analysis Improvements
* Fixed false positives in the `cpp/wrong-number-format-arguments` ("Too few arguments to formatting function") query when the formatting function has been declared implicitly.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.2.3
lastReleaseVersion: 1.2.4

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.2.4-dev
version: 1.2.5-dev
groups:
- cpp
- queries

View File

@@ -2,25 +2,168 @@
| file://:0:0:0:0 | (unnamed parameter 0) | false |
| file://:0:0:0:0 | __super | false |
| file://:0:0:0:0 | __va_list_tag | false |
| file://:0:0:0:0 | decltype([...](...){...}) | false |
| file://:0:0:0:0 | operator= | false |
| file://:0:0:0:0 | operator= | false |
| test.cpp:0:0:0:0 | test.cpp | false |
| test.cpp:2:1:2:61 | #define FOO class S{int i; void f(void) { int j; return; } }; | false |
| test.cpp:2:1:2:68 | #define CLASS_DECL class S{int i; void f(void) { int j; return; } }; | false |
| test.cpp:4:1:4:1 | S | false |
| test.cpp:4:1:4:1 | declaration of S | false |
| test.cpp:4:1:4:1 | declaration of operator= | false |
| test.cpp:4:1:4:1 | declaration of operator= | false |
| test.cpp:4:1:4:1 | operator= | false |
| test.cpp:4:1:4:1 | operator= | false |
| test.cpp:4:1:4:3 | FOO | false |
| test.cpp:4:1:4:3 | S | false |
| test.cpp:4:1:4:3 | declaration | true |
| test.cpp:4:1:4:3 | definition of S | true |
| test.cpp:4:1:4:3 | definition of f | true |
| test.cpp:4:1:4:3 | definition of i | true |
| test.cpp:4:1:4:3 | definition of j | true |
| test.cpp:4:1:4:3 | f | false |
| test.cpp:4:1:4:3 | i | false |
| test.cpp:4:1:4:3 | j | true |
| test.cpp:4:1:4:3 | return ... | true |
| test.cpp:4:1:4:3 | { ... } | true |
| test.cpp:4:1:4:10 | CLASS_DECL | false |
| test.cpp:4:1:4:10 | S | false |
| test.cpp:4:1:4:10 | declaration | true |
| test.cpp:4:1:4:10 | definition of S | true |
| test.cpp:4:1:4:10 | definition of f | true |
| test.cpp:4:1:4:10 | definition of i | true |
| test.cpp:4:1:4:10 | definition of j | true |
| test.cpp:4:1:4:10 | f | false |
| test.cpp:4:1:4:10 | i | false |
| test.cpp:4:1:4:10 | j | true |
| test.cpp:4:1:4:10 | return ... | true |
| test.cpp:4:1:4:10 | { ... } | true |
| test.cpp:6:1:6:42 | #define FUNCTION_DECL void f1() { int k; } | false |
| test.cpp:8:1:8:13 | FUNCTION_DECL | false |
| test.cpp:8:1:8:13 | declaration | true |
| test.cpp:8:1:8:13 | definition of f1 | true |
| test.cpp:8:1:8:13 | definition of k | true |
| test.cpp:8:1:8:13 | f1 | false |
| test.cpp:8:1:8:13 | k | true |
| test.cpp:8:1:8:13 | return ... | true |
| test.cpp:8:1:8:13 | { ... } | true |
| test.cpp:10:1:10:33 | #define VARIABLE_DECL int v1 = 1; | false |
| test.cpp:12:1:12:13 | 1 | true |
| test.cpp:12:1:12:13 | VARIABLE_DECL | false |
| test.cpp:12:1:12:13 | definition of v1 | true |
| test.cpp:12:1:12:13 | initializer for v1 | true |
| test.cpp:12:1:12:13 | v1 | true |
| test.cpp:14:1:14:35 | #define TYPE_DECL_1 typedef int t1; | false |
| test.cpp:16:1:16:11 | TYPE_DECL_1 | false |
| test.cpp:16:1:16:11 | declaration of t1 | true |
| test.cpp:16:1:16:11 | t1 | false |
| test.cpp:18:1:18:35 | #define TYPE_DECL_2 using t2 = int; | false |
| test.cpp:20:1:20:11 | TYPE_DECL_2 | false |
| test.cpp:20:1:20:11 | declaration of t2 | true |
| test.cpp:20:1:20:11 | t2 | false |
| test.cpp:22:1:22:47 | #define NAMESPACE_DECL namespace ns { int v2; } | false |
| test.cpp:24:1:24:14 | NAMESPACE_DECL | false |
| test.cpp:24:1:24:14 | definition of v2 | true |
| test.cpp:24:1:24:14 | ns | false |
| test.cpp:24:1:24:14 | ns | false |
| test.cpp:24:1:24:14 | v2 | true |
| test.cpp:26:1:26:43 | #define USING_NAMESPACE using namespace ns; | false |
| test.cpp:28:1:28:34 | #define ENUM_CONSTANT enum_element | false |
| test.cpp:30:12:30:21 | definition of enum_class | false |
| test.cpp:30:12:30:21 | enum_class | false |
| test.cpp:30:25:30:37 | ENUM_CONSTANT | false |
| test.cpp:30:25:30:37 | enum_element | false |
| test.cpp:32:1:32:41 | #define USING_ENUM using enum enum_class; | false |
| test.cpp:34:1:34:10 | USING_ENUM | false |
| test.cpp:34:1:34:10 | using enum enum_class | false |
| test.cpp:36:1:36:48 | #define STATIC_ASSERT static_assert(1 == 1, ""); | false |
| test.cpp:38:1:38:13 | 1 | true |
| test.cpp:38:1:38:13 | 1 | true |
| test.cpp:38:1:38:13 | ... == ... | true |
| test.cpp:38:1:38:13 | STATIC_ASSERT | false |
| test.cpp:38:1:38:13 | static_assert(..., "") | false |
| test.cpp:40:1:40:42 | #define ATTRIBUTE [[nodiscard("reason1")]] | false |
| test.cpp:42:1:42:9 | ATTRIBUTE | false |
| test.cpp:42:1:42:9 | nodiscard | false |
| test.cpp:42:1:42:9 | reason1 | false |
| test.cpp:42:1:42:9 | reason1 | true |
| test.cpp:43:5:43:6 | declaration of f2 | false |
| test.cpp:43:5:43:6 | f2 | false |
| test.cpp:45:1:45:31 | #define ATTRIBUTE_ARG "reason2" | false |
| test.cpp:47:3:47:11 | nodiscard | false |
| test.cpp:47:13:47:25 | ATTRIBUTE_ARG | false |
| test.cpp:47:13:47:25 | reason2 | false |
| test.cpp:47:13:47:25 | reason2 | true |
| test.cpp:48:5:48:6 | declaration of f3 | false |
| test.cpp:48:5:48:6 | f3 | false |
| test.cpp:50:1:50:16 | #define TYPE int | false |
| test.cpp:52:1:52:4 | TYPE | false |
| test.cpp:52:6:52:7 | definition of v3 | true |
| test.cpp:52:6:52:7 | v3 | true |
| test.cpp:52:11:52:11 | 1 | false |
| test.cpp:52:11:52:11 | initializer for v3 | false |
| test.cpp:54:1:54:29 | #define DERIVATION : public S | false |
| test.cpp:56:7:56:7 | T | false |
| test.cpp:56:7:56:7 | T | false |
| test.cpp:56:7:56:7 | declaration of T | false |
| test.cpp:56:7:56:7 | declaration of operator= | false |
| test.cpp:56:7:56:7 | declaration of operator= | false |
| test.cpp:56:7:56:7 | definition of T | false |
| test.cpp:56:7:56:7 | operator= | false |
| test.cpp:56:7:56:7 | operator= | false |
| test.cpp:56:9:56:18 | DERIVATION | false |
| test.cpp:56:9:56:18 | derivation | false |
| test.cpp:58:1:58:31 | #define FRIEND friend int f3(); | false |
| test.cpp:60:7:60:7 | U | false |
| test.cpp:60:7:60:7 | declaration of operator= | false |
| test.cpp:60:7:60:7 | declaration of operator= | false |
| test.cpp:60:7:60:7 | definition of U | false |
| test.cpp:60:7:60:7 | operator= | false |
| test.cpp:60:7:60:7 | operator= | false |
| test.cpp:61:3:61:8 | FRIEND | false |
| test.cpp:61:3:61:8 | U's friend | false |
| test.cpp:64:1:64:24 | #define NAME_QUAL_1 ns:: | false |
| test.cpp:66:1:66:22 | #define NAME_QUAL_2 ns | false |
| test.cpp:68:1:68:19 | #define LOCAL_VAR m | false |
| test.cpp:70:6:70:7 | definition of f4 | false |
| test.cpp:70:6:70:7 | f4 | false |
| test.cpp:70:11:76:1 | { ... } | false |
| test.cpp:71:5:71:8 | ns:: | false |
| test.cpp:71:5:71:15 | NAME_QUAL_1 | false |
| test.cpp:71:5:71:18 | v2 | false |
| test.cpp:71:5:71:19 | ExprStmt | false |
| test.cpp:72:5:72:8 | ns:: | false |
| test.cpp:72:5:72:15 | NAME_QUAL_2 | false |
| test.cpp:72:5:72:21 | v2 | false |
| test.cpp:72:5:72:22 | ExprStmt | false |
| test.cpp:73:5:73:23 | declaration | false |
| test.cpp:73:9:73:17 | LOCAL_VAR | false |
| test.cpp:73:9:73:17 | definition of m | true |
| test.cpp:73:9:73:17 | m | true |
| test.cpp:73:20:73:22 | 42 | false |
| test.cpp:73:20:73:22 | initializer for m | false |
| test.cpp:74:5:74:41 | declaration | false |
| test.cpp:74:10:74:10 | definition of l | false |
| test.cpp:74:10:74:10 | l | false |
| test.cpp:74:13:74:40 | [...](...){...} | false |
| test.cpp:74:13:74:40 | initializer for l | false |
| test.cpp:74:13:74:40 | {...} | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | (unnamed constructor) | false |
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | declaration of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | definition of (unnamed constructor) | false |
| test.cpp:74:14:74:14 | definition of operator= | false |
| test.cpp:74:14:74:14 | operator= | false |
| test.cpp:74:15:74:15 | definition of m | false |
| test.cpp:74:15:74:15 | m | false |
| test.cpp:74:15:74:15 | m | false |
| test.cpp:74:15:74:23 | LOCAL_VAR | false |
| test.cpp:74:15:74:23 | m | true |
| test.cpp:74:25:74:25 | definition of operator() | false |
| test.cpp:74:25:74:25 | operator() | false |
| test.cpp:74:28:74:40 | { ... } | false |
| test.cpp:74:30:74:38 | return ... | false |
| test.cpp:74:37:74:37 | (int)... | false |
| test.cpp:75:5:75:5 | (const lambda [] type at line 74, col. 14)... | false |
| test.cpp:75:5:75:5 | l | false |
| test.cpp:75:5:75:8 | ExprStmt | false |
| test.cpp:75:6:75:6 | call to operator() | false |
| test.cpp:76:1:76:1 | return ... | false |
| test.cpp:78:1:78:15 | #define ID(x) x | false |
| test.cpp:79:1:79:23 | #define NESTED(x) ID(x) | false |
| test.cpp:80:5:80:6 | definition of v4 | false |
| test.cpp:80:5:80:6 | v4 | false |
| test.cpp:80:10:80:18 | ID(x) | false |
| test.cpp:80:10:80:18 | NESTED(x) | false |
| test.cpp:80:17:80:17 | 1 | true |
| test.cpp:80:17:80:17 | initializer for v4 | true |
| test.cpp:82:1:82:39 | // semmle-extractor-options: -std=c++20 | false |

View File

@@ -1,5 +1,82 @@
#define FOO class S{int i; void f(void) { int j; return; } };
#define CLASS_DECL class S{int i; void f(void) { int j; return; } };
FOO
CLASS_DECL
#define FUNCTION_DECL void f1() { int k; }
FUNCTION_DECL
#define VARIABLE_DECL int v1 = 1;
VARIABLE_DECL
#define TYPE_DECL_1 typedef int t1;
TYPE_DECL_1
#define TYPE_DECL_2 using t2 = int;
TYPE_DECL_2
#define NAMESPACE_DECL namespace ns { int v2; }
NAMESPACE_DECL
#define USING_NAMESPACE using namespace ns;
#define ENUM_CONSTANT enum_element
enum class enum_class { ENUM_CONSTANT };
#define USING_ENUM using enum enum_class;
USING_ENUM
#define STATIC_ASSERT static_assert(1 == 1, "");
STATIC_ASSERT
#define ATTRIBUTE [[nodiscard("reason1")]]
ATTRIBUTE
int f2();
#define ATTRIBUTE_ARG "reason2"
[[nodiscard(ATTRIBUTE_ARG)]]
int f3();
#define TYPE int
TYPE v3 = 1;
#define DERIVATION : public S
class T DERIVATION {};
#define FRIEND friend int f3();
class U {
FRIEND
};
#define NAME_QUAL_1 ns::
#define NAME_QUAL_2 ns
#define LOCAL_VAR m
void f4() {
NAME_QUAL_1 v2;
NAME_QUAL_2 :: v2;
int LOCAL_VAR = 42;
auto l = [LOCAL_VAR]() { return m; };
l();
}
#define ID(x) x
#define NESTED(x) ID(x)
int v4 = NESTED(1);
// semmle-extractor-options: -std=c++20

View File

@@ -10,3 +10,4 @@
| test.c:15:2:15:7 | call to printf | Format for printf expects 3 arguments but given 2 |
| test.c:19:2:19:7 | call to printf | Format for printf expects 2 arguments but given 1 |
| test.c:29:3:29:8 | call to printf | Format for printf expects 2 arguments but given 1 |
| test.c:53:2:53:10 | call to my_logger | Format for my_logger expects 3 arguments but given 2 |

View File

@@ -44,3 +44,6 @@ void test_custom_printf2()
printf("", "%i %i", 100, 200); // GOOD
printf("%i %i", "" ); // GOOD
}
extern "C" void my_logger(int param, char *fmt, ...) __attribute__((format(printf, 2, 3))) {}

View File

@@ -46,4 +46,12 @@ void test(int i, const char *str)
printf("%Y", 1, 2); // GOOD (unknown format character, this might be correct)
printf("%1.1Y", 1, 2); // GOOD (unknown format character, this might be correct)
printf("%*.*Y", 1, 2); // GOOD (unknown format character, this might be correct)
// Implicit logger function declaration
my_logger(0, "%i %i %i %i %i %i\n", 1, 2, 3, 4, 5, 6); // GOOD
my_logger(0, "%i %i %i\n", 1, 2, 3); // GOOD
my_logger(0, "%i %i %i\n", 1, 2); // BAD (too few format arguments)
}
// A spurious definition of my_logger
extern void my_logger(int param, char *fmt, int, int, int, int, int);

View File

@@ -53,4 +53,59 @@ void NonStringFalsePositiveTest2(unsigned char* buffer)
{
wchar_t *lpWchar = NULL;
lpWchar = (LPWSTR)buffer; // Possible False Positive
}
}
typedef unsigned char BYTE;
using FOO = BYTE*;
void NonStringFalsePositiveTest3(FOO buffer)
{
wchar_t *lpWchar = NULL;
lpWchar = (LPWSTR)buffer; // GOOD
}
#define UNICODE 0x8
// assume EMPTY_MACRO is tied to if UNICODE is enabled
#ifdef EMPTY_MACRO
typedef WCHAR* LPTSTR;
#else
typedef char* LPTSTR;
#endif
void CheckedConversionFalsePositiveTest3(unsigned short flags, LPTSTR buffer)
{
wchar_t *lpWchar = NULL;
if(flags & UNICODE)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) == 0x8)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) != 0x8)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // GOOD
// Bad operator precedence
if(flags & UNICODE == 0x8)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) != 0)
lpWchar = (LPWSTR)buffer; // GOOD
else
lpWchar = (LPWSTR)buffer; // BUG
if((flags & UNICODE) == 0)
lpWchar = (LPWSTR)buffer; // BUG
else
lpWchar = (LPWSTR)buffer; // GOOD
lpWchar = (LPWSTR)buffer; // BUG
}

View File

@@ -3,3 +3,11 @@
| WcharCharConversion.cpp:24:22:24:27 | lpChar | Conversion from char * to wchar_t *. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:26:23:26:28 | lpChar | Conversion from char * to LPCWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:27:17:27:22 | lpChar | Conversion from char * to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:82:21:82:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:87:21:87:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:90:21:90:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:96:21:96:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:98:21:98:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:103:21:103:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:106:21:106:26 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |
| WcharCharConversion.cpp:110:20:110:25 | buffer | Conversion from LPTSTR to LPWSTR. Use of invalid string can lead to undefined behavior. |

View File

@@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
catch (Exception exc)
{
Context.ExtractionError($"Couldn't read file: {originalPath}. {exc.Message}", null, null, exc.StackTrace);
Context.ExtractionError($"Couldn't read file: {originalPath}. {exc.Message}", null, null, exc.StackTrace, Semmle.Util.Logging.Severity.Warning);
}
}

View File

@@ -1,3 +1,7 @@
## 1.7.26
No user-facing changes.
## 1.7.25
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.7.26
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.25
lastReleaseVersion: 1.7.26

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-all
version: 1.7.26-dev
version: 1.7.27-dev
groups:
- csharp
- solorigate

View File

@@ -1,3 +1,7 @@
## 1.7.26
No user-facing changes.
## 1.7.25
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 1.7.26
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.7.25
lastReleaseVersion: 1.7.26

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-solorigate-queries
version: 1.7.26-dev
version: 1.7.27-dev
groups:
- csharp
- solorigate

View File

@@ -61,8 +61,3 @@ query predicate preBasicBlockConsistency(ControlFlowElement cfe1, ControlFlowEle
bbIntraSuccInconsistency(cfe1, cfe2) and
s = "intra succ inconsistency"
}
query predicate multipleToString(Node n, string s) {
s = strictconcat(n.toString(), ",") and
strictcount(n.toString()) > 1
}

View File

@@ -1,3 +1,19 @@
## 3.0.0
### Breaking Changes
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.
* C#: Remove all CIL tables and related QL library functionality.
### Deprecated APIs
* The class `ThreatModelFlowSource` has been renamed to `ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. `ThreatModelFlowSource` has been marked as deprecated.
### Minor Analysis Improvements
* `DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using `Callable` and other non-dataflow classes to identify such library entities.
* C#: Add extractor support for attributes on indexers.
## 2.0.0
### Breaking Changes

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.

View File

@@ -1,4 +0,0 @@
---
category: breaking
---
* C#: Remove all CIL tables and related QL library functionality.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* C#: Add extractor support for attributes on indexers.

View File

@@ -1,4 +0,0 @@
---
category: minorAnalysis
---
* `DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using `Callable` and other non-dataflow classes to identify such library entities.

View File

@@ -0,0 +1,15 @@
## 3.0.0
### Breaking Changes
* C#: Add support for MaD directly on properties and indexers using *attributes*. Using `Attribute.Getter` or `Attribute.Setter` in the model `ext` field applies the model to the getter or setter for properties and indexers. Prior to this change `Attribute` models unintentionally worked for property setters (if the property is decorated with the matching attribute). That is, a model that uses the `Attribute` feature directly on a property for a property setter needs to be changed to `Attribute.Setter`.
* C#: Remove all CIL tables and related QL library functionality.
### Deprecated APIs
* The class `ThreatModelFlowSource` has been renamed to `ActiveThreatModelSource` to more clearly reflect it only contains the currently active threat model sources. `ThreatModelFlowSource` has been marked as deprecated.
### Minor Analysis Improvements
* `DataFlow::Node` instances are no longer created for library methods and fields that are not callable (either statically or dynamically) or otherwise referred to from source code. This may affect third-party queries that use these nodes to identify library methods or fields that are present in DLL files where those methods or fields are unreferenced. If this presents a problem, consider using `Callable` and other non-dataflow classes to identify such library entities.
* C#: Add extractor support for attributes on indexers.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 2.0.0
lastReleaseVersion: 3.0.0

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-all
version: 2.0.1-dev
version: 3.0.1-dev
groups: csharp
dbscheme: semmlecode.csharp.dbscheme
extractor: csharp

View File

@@ -15,11 +15,19 @@ class CfgScope extends Element, @top_level_exprorstmt_parent {
CfgScope() {
this.getFile().fromSource() and
(
this instanceof Callable
this =
any(Callable c |
c.(Constructor).hasInitializer()
or
InitializerSplitting::constructorInitializes(c, _)
or
c.hasBody()
)
or
// For now, static initializer values have their own scope. Eventually, they
// should be treated like instance initializers.
this.(Assignable).(Modifiable).isStatic()
this.(Assignable).(Modifiable).isStatic() and
expr_parent_top_level_adjusted2(_, _, this)
)
}
}

View File

@@ -318,7 +318,7 @@ private predicate elementSpec(
or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
or
neutralModel(namespace, type, name, signature, _, _) and ext = "" and subtypes = false
neutralModel(namespace, type, name, signature, _, _) and ext = "" and subtypes = true
}
private predicate elementSpec(
@@ -602,7 +602,7 @@ private predicate interpretSummary(
predicate interpretNeutral(UnboundCallable c, string kind, string provenance) {
exists(string namespace, string type, string name, string signature |
neutralModel(namespace, type, name, signature, kind, provenance) and
c = interpretElement(namespace, type, false, name, signature, "")
c = interpretElement(namespace, type, true, name, signature, "")
)
}

View File

@@ -18,7 +18,7 @@ private predicate needsChecks(ActionMethod m) { m.isEdit() and not m.isAdmin() }
* that may indicate that it's used as the ID for some resource
*/
private predicate hasIdParameter(ActionMethod m) {
exists(ThreatModelFlowSource src | src.getEnclosingCallable() = m |
exists(ActiveThreatModelSource src | src.getEnclosingCallable() = m |
src.asParameter().getName().toLowerCase().matches(["%id", "%idx"])
or
// handle cases like `Request.QueryString["Id"]`

View File

@@ -55,7 +55,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { }

View File

@@ -57,7 +57,7 @@ module CommandInjection = TaintTracking::Global<CommandInjectionConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** Command Injection sinks defined through Models as Data. */
private class ExternalCommandInjectionExprSink extends Sink {

View File

@@ -54,7 +54,7 @@ module ConditionalBypass = TaintTracking::Global<ConditionalBypassConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** The result of a reverse dns may be user-controlled. */
class ReverseDnsSource extends Source {

View File

@@ -73,14 +73,14 @@ class ExternalApiDataNode extends DataFlow::Node {
}
}
/** A configuration for tracking flow from `ThreatModelFlowSource`s to `ExternalApiDataNode`s. */
/** A configuration for tracking flow from `ActiveThreatModelSource`s to `ExternalApiDataNode`s. */
private module RemoteSourceToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
}
/** A module for tracking flow from `ThreatModelFlowSource`s to `ExternalApiDataNode`s. */
/** A module for tracking flow from `ActiveThreatModelSource`s to `ExternalApiDataNode`s. */
module RemoteSourceToExternalApi = TaintTracking::Global<RemoteSourceToExternalApiConfig>;
/** A node representing untrusted data being passed to an external API. */

View File

@@ -60,7 +60,7 @@ module LdapInjection = TaintTracking::Global<LdapInjectionConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** LDAP sinks defined through Models as Data. */
private class ExternalLdapExprSink extends Sink {

View File

@@ -43,7 +43,7 @@ private module LogForgingConfig implements DataFlow::ConfigSig {
module LogForging = TaintTracking::Global<LogForgingConfig>;
/** A source of remote user input. */
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
private class HtmlSanitizer extends Sanitizer {
HtmlSanitizer() { this.asExpr() instanceof HtmlSanitizedExpr }

View File

@@ -48,7 +48,7 @@ private module MissingXmlValidationConfig implements DataFlow::ConfigSig {
module MissingXmlValidation = TaintTracking::Global<MissingXmlValidationConfig>;
/**
* DEPRECATED: Use `ThreatModelFlowSource` instead.
* DEPRECATED: Use `ActiveThreatModelSource` instead.
*
* A source of remote user input.
*/
@@ -57,7 +57,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
/**
* A source supported by the current threat model.
*/
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* The input argument to a call to `XmlReader.Create` where the input will not be validated against

View File

@@ -49,7 +49,7 @@ module ReDoS = TaintTracking::Global<ReDoSConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* An expression that represents a regular expression with potential exponential behavior.

View File

@@ -48,7 +48,7 @@ module RegexInjection = TaintTracking::Global<RegexInjectionConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* A `pattern` argument to a construction of a `Regex`.

View File

@@ -54,7 +54,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** An argument to the `ConnectionString` property on a data connection class. */
class SqlConnectionStringSink extends Sink {

View File

@@ -65,7 +65,7 @@ deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource
deprecated class LocalSource extends DataFlow::Node instanceof LocalFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** An SQL expression passed to an API call that executes SQL. */
class SqlInjectionExprSink extends Sink {

View File

@@ -50,7 +50,7 @@ module TaintedPath = TaintTracking::Global<TaintedPathConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* A path argument to a `File` method call.

View File

@@ -49,7 +49,7 @@ abstract private class ConstructorOrStaticMethodSink extends Sink { }
*/
abstract class Sanitizer extends DataFlow::Node { }
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* User input to object method call deserialization flow tracking configuration.

View File

@@ -52,7 +52,7 @@ module UrlRedirect = TaintTracking::Global<UrlRedirectConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** URL Redirection sinks defined through Models as Data. */
private class ExternalUrlRedirectExprSink extends Sink {

View File

@@ -15,7 +15,7 @@ private import semmle.code.csharp.security.Sanitizers
*/
abstract class Source extends DataFlow::Node { }
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* A data flow sink for untrusted user input used in XML processing.

View File

@@ -58,7 +58,7 @@ module XpathInjection = TaintTracking::Global<XpathInjectionConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/** The `xpath` argument to an `XPathExpression.Compile(..)` call. */
class XPathExpressionCompileSink extends Sink {

View File

@@ -165,7 +165,7 @@ module XssTrackingConfig implements DataFlow::ConfigSig {
module XssTracking = TaintTracking::Global<XssTrackingConfig>;
/** A source supported by the current threat model. */
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
private class SimpleTypeSanitizer extends Sanitizer, SimpleTypeSanitizedExpr { }

View File

@@ -56,10 +56,9 @@ class HtmlTextWriterSink extends HtmlSink {
}
/**
* An expression that is used as an argument to an HTML sink method on
* `AttributeCollection`.
* DEPRECATED: Attribute collections are no longer considered HTML sinks.
*/
class AttributeCollectionSink extends HtmlSink {
deprecated class AttributeCollectionSink extends DataFlow::ExprNode {
AttributeCollectionSink() {
exists(SystemWebUIAttributeCollectionClass ac, Parameter p |
p = ac.getAddMethod().getParameter(1) or

View File

@@ -20,11 +20,18 @@ abstract class SourceNode extends DataFlow::Node {
}
/**
* DEPRECATED: Use `ActiveThreatModelSource` instead.
*
* A class of data flow sources that respects the
* current threat model configuration.
*/
class ThreatModelFlowSource extends DataFlow::Node {
ThreatModelFlowSource() {
deprecated class ThreatModelFlowSource = ActiveThreatModelSource;
/**
* A data flow source that is enabled in the current threat model configuration.
*/
class ActiveThreatModelSource extends DataFlow::Node {
ActiveThreatModelSource() {
exists(string kind |
// Specific threat model.
currentThreatModel(kind) and

View File

@@ -1,3 +1,9 @@
## 1.0.9
### Minor Analysis Improvements
* C#: The indexer and `Add` method on `System.Web.UI.AttributeCollection` is no longer considered an HTML sink.
## 1.0.8
No user-facing changes.

View File

@@ -20,7 +20,7 @@ import XmlInjection::PathGraph
* A taint-tracking configuration for untrusted user input used in XML.
*/
module XmlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc |

View File

@@ -21,7 +21,7 @@ import AssemblyPathInjection::PathGraph
* A taint-tracking configuration for untrusted user input used to load a DLL.
*/
module AssemblyPathInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc, string name, int arg |

View File

@@ -17,7 +17,7 @@ import semmle.code.csharp.frameworks.Format
import FormatString::PathGraph
module FormatStringConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(FormatCall call | call.hasInsertions()).getFormatExpr()

View File

@@ -0,0 +1,5 @@
## 1.0.9
### Minor Analysis Improvements
* C#: The indexer and `Add` method on `System.Web.UI.AttributeCollection` is no longer considered an HTML sink.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 1.0.8
lastReleaseVersion: 1.0.9

View File

@@ -61,7 +61,7 @@ module TaintedWebClient = TaintTracking::Global<TaintedWebClientConfig>;
deprecated class RemoteSource extends DataFlow::Node instanceof RemoteFlowSource { }
/** A source supported by the current threat model. */
class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* A path argument to a `WebClient` method call that has an address argument.

View File

@@ -60,7 +60,7 @@ module RequestForgery {
/**
* A dataflow source for Server Side Request Forgery(SSRF) Vulnerabilities.
*/
private class ThreatModelSource extends Source instanceof ThreatModelFlowSource { }
private class ThreatModelSource extends Source instanceof ActiveThreatModelSource { }
/**
* An url argument to a `HttpRequestMessage` constructor call

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 1.0.9-dev
version: 1.0.10-dev
groups:
- csharp
- queries

View File

@@ -9,5 +9,5 @@
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string flow
where flow = captureContentFlow(api)
where flow = ContentSensitive::captureFlow(api, _)
select flow order by flow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture mixed neutral models.
* @description Finds neutral models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/mixed-neutral-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string noflow
where noflow = captureMixedNeutral(api)
select noflow order by noflow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture mixed summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id cs/utils/modelgenerator/mixed-summary-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string flow
where flow = captureMixedFlow(api, _)
select flow order by flow

View File

@@ -6,9 +6,7 @@
* @tags modelgenerator
*/
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import internal.CaptureModels
import internal.CaptureSummaryFlowQuery
from DataFlowSummaryTargetApi api, string noflow
where noflow = captureNoFlow(api)

View File

@@ -6,9 +6,7 @@
* @tags modelgenerator
*/
import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
import internal.CaptureModels
import internal.CaptureSummaryFlowQuery
from DataFlowSummaryTargetApi api, string flow
where flow = captureFlow(api)

View File

@@ -1,635 +1,354 @@
/**
* Provides classes and predicates related to capturing summary, source,
* and sink models of the Standard or a 3rd party library.
*/
private import csharp as CS
private import semmle.code.csharp.commons.Util as Util
private import semmle.code.csharp.commons.Collections as Collections
private import semmle.code.csharp.commons.QualifiedName as QualifiedName
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate
private import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
private import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.csharp.dataflow.internal.DataFlowImplSpecific
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
private import semmle.code.csharp.dataflow.internal.TaintTrackingImplSpecific
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.Location
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
private import CaptureModelsSpecific
private import CaptureModelsPrinting
module ModelGeneratorInput implements ModelGeneratorInputSig<Location, CsharpDataFlow> {
class Type = CS::Type;
/**
* A node from which flow can return to the caller. This is either a regular
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
*/
private class ReturnNodeExt extends DataFlow::Node {
private DataFlowImplCommon::ReturnKindExt kind;
class Parameter = CS::Parameter;
ReturnNodeExt() {
kind = DataFlowImplCommon::getValueReturnPosition(this).getKind() or
kind = DataFlowImplCommon::getParamReturnPosition(this, _).getKind()
class Callable = CS::Callable;
class NodeExtended extends CS::DataFlow::Node {
Callable getAsExprEnclosingCallable() { result = this.asExpr().getEnclosingCallable() }
}
/**
* Gets the kind of the return node.
* Holds if any of the parameters of `api` are `System.Func<>`.
*/
DataFlowImplCommon::ReturnKindExt getKind() { result = kind }
}
bindingset[c]
private signature string printCallableParamSig(Callable c, ParameterPosition p);
private module PrintReturnNodeExt<printCallableParamSig/2 printCallableParam> {
string getOutput(ReturnNodeExt node) {
node.getKind() instanceof DataFlowImplCommon::ValueReturnKind and
result = "ReturnValue"
or
exists(ParameterPosition pos |
pos = node.getKind().(DataFlowImplCommon::ParamUpdateReturnKind).getPosition() and
result = printCallableParam(returnNodeEnclosingCallable(node), pos)
)
}
}
string getOutput(ReturnNodeExt node) {
result = PrintReturnNodeExt<paramReturnNodeAsOutput/2>::getOutput(node)
}
string getContentOutput(ReturnNodeExt node) {
result = PrintReturnNodeExt<paramReturnNodeAsContentOutput/2>::getOutput(node)
}
class DataFlowSummaryTargetApi extends SummaryTargetApi {
DataFlowSummaryTargetApi() { not isUninterestingForDataFlowModels(this) }
}
class DataFlowSourceTargetApi = SourceTargetApi;
class DataFlowSinkTargetApi = SinkTargetApi;
private module ModelPrintingInput implements ModelPrintingSig {
class SummaryApi = DataFlowSummaryTargetApi;
class SourceOrSinkApi = SourceOrSinkTargetApi;
string getProvenance() { result = "df-generated" }
}
module Printing = ModelPrinting<ModelPrintingInput>;
/**
* Holds if `c` is a relevant content kind, where the underlying type is relevant.
*/
private predicate isRelevantTypeInContent(DataFlow::ContentSet c) {
isRelevantType(getUnderlyingContentType(c))
}
/**
* Holds if data can flow from `node1` to `node2` either via a read or a write of an intermediate field `f`.
*/
private predicate isRelevantTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(DataFlow::ContentSet f |
DataFlowPrivate::readStep(node1, f, node2) and
// Partially restrict the content types used for intermediate steps.
(not exists(getUnderlyingContentType(f)) or isRelevantTypeInContent(f))
)
or
exists(DataFlow::ContentSet f | DataFlowPrivate::storeStep(node1, f, node2) | containerContent(f))
}
/**
* Holds if content `c` is either a field, a synthetic field or language specific
* content of a relevant type or a container like content.
*/
pragma[nomagic]
private predicate isRelevantContent0(DataFlow::ContentSet c) {
isRelevantTypeInContent(c) or
containerContent(c)
}
/**
* Gets the MaD string representation of the parameter node `p`.
*/
string parameterNodeAsInput(DataFlow::ParameterNode p) {
result = parameterAccess(p.asParameter())
or
result = qualifierString() and p instanceof InstanceParameterNode
}
/**
* Gets the MaD string representation of the parameter `p`
* when used in content flow.
*/
string parameterNodeAsContentInput(DataFlow::ParameterNode p) {
result = parameterContentAccess(p.asParameter())
or
result = qualifierString() and p instanceof InstanceParameterNode
}
/**
* Gets the MaD input string representation of `source`.
*/
string asInputArgument(DataFlow::Node source) { result = asInputArgumentSpecific(source) }
/**
* Gets the summary model of `api`, if it follows the `fluent` programming pattern (returns `this`).
*/
string captureQualifierFlow(DataFlowSummaryTargetApi api) {
exists(ReturnNodeExt ret |
api = returnNodeEnclosingCallable(ret) and
isOwnInstanceAccessNode(ret)
) and
result = Printing::asLiftedValueModel(api, qualifierString(), "ReturnValue")
}
private int accessPathLimit0() { result = 2 }
private newtype TTaintState =
TTaintRead(int n) { n in [0 .. accessPathLimit0()] } or
TTaintStore(int n) { n in [1 .. accessPathLimit0()] }
abstract private class TaintState extends TTaintState {
abstract string toString();
}
/**
* A FlowState representing a tainted read.
*/
private class TaintRead extends TaintState, TTaintRead {
private int step;
TaintRead() { this = TTaintRead(step) }
/**
* Gets the flow state step number.
*/
int getStep() { result = step }
override string toString() { result = "TaintRead(" + step + ")" }
}
/**
* A FlowState representing a tainted write.
*/
private class TaintStore extends TaintState, TTaintStore {
private int step;
TaintStore() { this = TTaintStore(step) }
/**
* Gets the flow state step number.
*/
int getStep() { result = step }
override string toString() { result = "TaintStore(" + step + ")" }
}
/**
* A data-flow configuration for tracking flow through APIs.
* The sources are the parameters of an API and the sinks are the return values (excluding `this`) and parameters.
*
* This can be used to generate Flow summaries for APIs from parameter to return.
*/
module PropagateFlowConfig implements DataFlow::StateConfigSig {
class FlowState = TaintState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof DataFlow::ParameterNode and
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi and
state.(TaintRead).getStep() = 0
}
predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof ReturnNodeExt and
not isOwnInstanceAccessNode(sink) and
not exists(captureQualifierFlow(sink.asExpr().getEnclosingCallable())) and
(state instanceof TaintRead or state instanceof TaintStore)
}
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
exists(DataFlow::ContentSet c |
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
isRelevantContent0(c) and
(
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
or
state1.(TaintStore).getStep() + 1 = state2.(TaintStore).getStep()
)
)
or
exists(DataFlow::ContentSet c |
DataFlowPrivate::readStep(node1, c, node2) and
isRelevantContent0(c) and
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
private predicate isHigherOrder(Callable api) {
exists(Type t | t = api.getAParameter().getType().getUnboundDeclaration() |
t instanceof SystemLinqExpressions::DelegateExtType
)
}
predicate isBarrier(DataFlow::Node n) {
exists(Type t | t = n.getType() and not isRelevantType(t))
private predicate irrelevantAccessor(CS::Accessor a) {
a.getDeclaration().(CS::Property).isReadWrite()
}
DataFlow::FlowFeature getAFeature() {
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
}
}
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
/**
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
*/
string captureThroughFlow0(
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt
) {
exists(string input, string output |
p.getEnclosingCallable() = api and
returnNodeExt.(DataFlow::Node).getEnclosingCallable() = api and
input = parameterNodeAsInput(p) and
output = getOutput(returnNodeExt) and
input != output and
result = Printing::asLiftedTaintModel(api, input, output)
)
}
/**
* Gets the summary model(s) of `api`, if there is flow from parameters to return value or parameter.
*/
string captureThroughFlow(DataFlowSummaryTargetApi api) {
exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt |
PropagateFlow::flow(p, returnNodeExt) and
result = captureThroughFlow0(api, p, returnNodeExt)
)
}
private module PropagateContentFlowConfig implements ContentDataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof DataFlow::ParameterNode and
source.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
}
predicate isSink(DataFlow::Node sink) {
sink instanceof ReturnNodeExt and
sink.getEnclosingCallable() instanceof DataFlowSummaryTargetApi
}
predicate isAdditionalFlowStep = isAdditionalContentFlowStep/2;
predicate isBarrier(DataFlow::Node n) {
exists(Type t | t = n.getType() and not isRelevantType(t))
}
int accessPathLimit() { result = 2 }
predicate isRelevantContent(DataFlow::ContentSet s) { isRelevantContent0(s) }
DataFlow::FlowFeature getAFeature() {
result instanceof DataFlow::FeatureEqualSourceSinkCallContext
}
}
private module PropagateContentFlow = ContentDataFlow::Global<PropagateContentFlowConfig>;
private string getContent(PropagateContentFlow::AccessPath ap, int i) {
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
head = ap.getHead() and
tail = ap.getTail()
|
i = 0 and
result = "." + printContent(head)
private predicate isUninterestingForModels(Callable api) {
api.getDeclaringType().getNamespace().getFullName() = ""
or
i > 0 and result = getContent(tail, i - 1)
)
}
/**
* Gets the MaD string representation of a store step access path.
*/
private string printStoreAccessPath(PropagateContentFlow::AccessPath ap) {
result = concat(int i | | getContent(ap, i), "" order by i)
}
/**
* Gets the MaD string representation of a read step access path.
*/
private string printReadAccessPath(PropagateContentFlow::AccessPath ap) {
result = concat(int i | | getContent(ap, i), "" order by i desc)
}
/**
* Holds if the access path `ap` contains a field or synthetic field access.
*/
private predicate mentionsField(PropagateContentFlow::AccessPath ap) {
exists(ContentSet head, PropagateContentFlow::AccessPath tail |
head = ap.getHead() and
tail = ap.getTail()
|
mentionsField(tail) or isField(head)
)
}
private predicate apiFlow(
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p, PropagateContentFlow::AccessPath reads,
ReturnNodeExt returnNodeExt, PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
returnNodeExt.getEnclosingCallable() = api and
p.getEnclosingCallable() = api
}
/**
* A class of APIs relevant for modeling using content flow.
* The following heuristic is applied:
* Content flow is only relevant for an API, if
* #content flow <= 2 * #parameters + 3
* If an API produces more content flow, it is likely that
* 1. Types are not sufficiently constrained leading to a combinatorial
* explosion in dispatch and thus in the generated summaries.
* 2. It is a reasonable approximation to use the non-content based flow
* detection instead, as reads and stores would use a significant
* part of an objects internal state.
*/
private class ContentDataFlowSummaryTargetApi extends DataFlowSummaryTargetApi {
ContentDataFlowSummaryTargetApi() {
count(string input, string output |
exists(
DataFlow::ParameterNode p, PropagateContentFlow::AccessPath reads,
ReturnNodeExt returnNodeExt, PropagateContentFlow::AccessPath stores
|
apiFlow(this, p, reads, returnNodeExt, stores, _) and
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores)
)
) <= 2 * this.getNumberOfParameters() + 3
}
}
pragma[nomagic]
private predicate apiContentFlow(
ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p,
PropagateContentFlow::AccessPath reads, ReturnNodeExt returnNodeExt,
PropagateContentFlow::AccessPath stores, boolean preservesValue
) {
PropagateContentFlow::flow(p, reads, returnNodeExt, stores, preservesValue) and
returnNodeExt.getEnclosingCallable() = api and
p.getEnclosingCallable() = api
}
/**
* Holds if any of the content sets in `path` translates into a synthetic field.
*/
private predicate hasSyntheticContent(PropagateContentFlow::AccessPath path) {
exists(PropagateContentFlow::AccessPath tail, ContentSet head |
head = path.getHead() and
tail = path.getTail()
|
exists(getSyntheticName(head)) or
hasSyntheticContent(tail)
)
}
/**
* A module containing predicates for validating access paths containing content sets
* that translates into synthetic fields, when used for generated summary models.
*/
private module AccessPathSyntheticValidation {
/**
* Holds if there exists an API that has content flow from `read` (on type `t1`)
* to `store` (on type `t2`).
*/
private predicate step(
Type t1, PropagateContentFlow::AccessPath read, Type t2, PropagateContentFlow::AccessPath store
) {
exists(DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt |
p.getType() = t1 and
returnNodeExt.getType() = t2 and
apiContentFlow(_, p, read, returnNodeExt, store, _)
api instanceof CS::ConversionOperator
or
api instanceof Util::MainMethod
or
api instanceof CS::Destructor
or
api instanceof CS::AnonymousFunctionExpr
or
api.(CS::Constructor).isParameterless()
or
exists(Type decl | decl = api.getDeclaringType() |
decl instanceof SystemObjectClass or
decl instanceof SystemValueTypeClass
)
}
/**
* Holds if there exists an API that has content flow from `read` (on type `t1`)
* to `store` (on type `t2`), where `read` does not have synthetic content and `store` does.
*
* Step A -> Synth.
*/
private predicate synthPathEntry(
Type t1, PropagateContentFlow::AccessPath read, Type t2, PropagateContentFlow::AccessPath store
) {
not hasSyntheticContent(read) and
hasSyntheticContent(store) and
step(t1, read, t2, store)
}
/**
* Holds if there exists an API that has content flow from `read` (on type `t1`)
* to `store` (on type `t2`), where `read` has synthetic content
* and `store` does not.
*
* Step Synth -> A.
*/
private predicate synthPathExit(
Type t1, PropagateContentFlow::AccessPath read, Type t2, PropagateContentFlow::AccessPath store
) {
hasSyntheticContent(read) and
not hasSyntheticContent(store) and
step(t1, read, t2, store)
}
/**
* Holds if there exists a path of steps from `read` to an exit.
*
* read ->* Synth -> A
*/
private predicate reachesSynthExit(Type t, PropagateContentFlow::AccessPath read) {
synthPathExit(t, read, _, _)
or
hasSyntheticContent(read) and
exists(PropagateContentFlow::AccessPath mid, Type midType |
hasSyntheticContent(mid) and
step(t, read, midType, mid) and
reachesSynthExit(midType, mid.reverse())
)
// Disregard properties that have both a get and a set accessor,
// which implicitly means auto implemented properties.
irrelevantAccessor(api)
}
private predicate relevant(Callable api) {
[api.(CS::Modifiable), api.(CS::Accessor).getDeclaration()].isEffectivelyPublic() and
api.fromSource() and
api.isUnboundDeclaration() and
not isUninterestingForModels(api)
}
private Callable getARelevantOverrideeOrImplementee(Overridable m) {
m.overridesOrImplements(result) and relevant(result)
}
/**
* Holds if there exists a path of steps from an entry to `store`.
*
* A -> Synth ->* store
* Gets the super implementation of `api` if it is relevant.
* If such a super implementation does not exist, returns `api` if it is relevant.
*/
private predicate synthEntryReaches(Type t, PropagateContentFlow::AccessPath store) {
synthPathEntry(_, _, t, store)
or
hasSyntheticContent(store) and
exists(PropagateContentFlow::AccessPath mid, Type midType |
hasSyntheticContent(mid) and
step(midType, mid, t, store) and
synthEntryReaches(midType, mid.reverse())
)
}
/**
* Holds if at least one of the access paths `read` (on type `t1`) and `store` (on type `t2`)
* contain content that will be translated into a synthetic field, when being used in
* a MaD summary model, and if there is a range of APIs, such that
* when chaining their flow access paths, there exists access paths `A` and `B` where
* A ->* read -> store ->* B and where `A` and `B` do not contain content that will
* be translated into a synthetic field.
*
* This is needed because we don't want to include summaries that reads from or
* stores into a "dead" synthetic field.
*
* Example:
* Assume we have a type `t` (in this case `t1` = `t2`) with methods `getX` and
* `setX`, which gets and sets a private field `X` on `t`.
* This would lead to the following content flows
* getX : Argument[this].SyntheticField[t.X] -> ReturnValue.
* setX : Argument[0] -> Argument[this].SyntheticField[t.X]
* As the reads and stores are on synthetic fields we should only make summaries
* if both of these methods exist.
*/
pragma[nomagic]
predicate acceptReadStore(
Type t1, PropagateContentFlow::AccessPath read, Type t2, PropagateContentFlow::AccessPath store
) {
synthPathEntry(t1, read, t2, store) and reachesSynthExit(t2, store.reverse())
or
exists(PropagateContentFlow::AccessPath store0 | store0.reverse() = read |
synthEntryReaches(t1, store0) and synthPathExit(t1, read, t2, store)
private Callable liftedImpl(Callable api) {
(
result = getARelevantOverrideeOrImplementee(api)
or
synthEntryReaches(t1, store0) and
step(t1, read, t2, store) and
reachesSynthExit(t2, store.reverse())
)
result = api and relevant(api)
) and
not exists(getARelevantOverrideeOrImplementee(result))
}
}
/**
* Holds, if the API `api` has relevant flow from `read` on `p` to `store` on `returnNodeExt`.
* Flow is considered relevant,
* 1. If `read` or `store` do not contain a content set that translates into a synthetic field.
* 2. If `read` or `store` contain a content set that translates into a synthetic field, and if
* the synthetic content is "live" on the relevant declaring type.
*/
private predicate apiRelevantContentFlow(
ContentDataFlowSummaryTargetApi api, DataFlow::ParameterNode p,
PropagateContentFlow::AccessPath read, ReturnNodeExt returnNodeExt,
PropagateContentFlow::AccessPath store, boolean preservesValue
) {
apiContentFlow(api, p, read, returnNodeExt, store, preservesValue) and
(
not hasSyntheticContent(read) and not hasSyntheticContent(store)
or
AccessPathSyntheticValidation::acceptReadStore(p.getType(), read, returnNodeExt.getType(), store)
)
}
private predicate hasManualSummaryModel(Callable api) {
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
}
pragma[nomagic]
private predicate captureContentFlow0(
ContentDataFlowSummaryTargetApi api, string input, string output, boolean preservesValue,
boolean lift
) {
exists(
DataFlow::ParameterNode p, ReturnNodeExt returnNodeExt, PropagateContentFlow::AccessPath reads,
PropagateContentFlow::AccessPath stores
|
apiRelevantContentFlow(api, p, reads, returnNodeExt, stores, preservesValue) and
input = parameterNodeAsContentInput(p) + printReadAccessPath(reads) and
output = getContentOutput(returnNodeExt) + printStoreAccessPath(stores) and
input != output and
(if mentionsField(reads) or mentionsField(stores) then lift = false else lift = true)
)
}
private predicate hasManualSourceModel(Callable api) {
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel())
}
/**
* Gets the content based summary model(s) of the API `api` (if there is flow from a parameter to
* the return value or a parameter).
*
* Models are lifted to the best type in case the read and store access paths do not
* contain a field or synthetic field access.
*/
string captureContentFlow(ContentDataFlowSummaryTargetApi api) {
exists(string input, string output, boolean lift, boolean preservesValue |
captureContentFlow0(api, input, output, _, lift) and
preservesValue = max(boolean p | captureContentFlow0(api, input, output, p, lift)) and
result = Printing::asModel(api, input, output, preservesValue, lift)
)
}
private predicate hasManualSinkModel(Callable api) {
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel())
}
/**
* A dataflow configuration used for finding new sources.
* The sources are the already known existing sources and the sinks are the API return nodes.
*
* This can be used to generate Source summaries for an API, if the API expose an already known source
* via its return (then the API itself becomes a source).
*/
module PropagateFromSourceConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
exists(string kind |
isRelevantSourceKind(kind) and
ExternalFlow::sourceNode(source, kind)
predicate isUninterestingForDataFlowModels(Callable api) { isHigherOrder(api) }
class SourceOrSinkTargetApi extends Callable {
SourceOrSinkTargetApi() { relevant(this) }
}
class SinkTargetApi extends SourceOrSinkTargetApi {
SinkTargetApi() { not hasManualSinkModel(this) }
}
class SourceTargetApi extends SourceOrSinkTargetApi {
SourceTargetApi() {
not hasManualSourceModel(this) and
// Do not generate source models for overridable callables
// as virtual dispatch implies that too many methods
// will be considered sources.
not this.(Overridable).overridesOrImplements(_)
}
}
class SummaryTargetApi extends Callable {
private Callable lift;
SummaryTargetApi() {
lift = liftedImpl(this) and
not hasManualSummaryModel(lift)
}
Callable lift() { result = lift }
predicate isRelevant() {
relevant(this) and
not hasManualSummaryModel(this)
}
}
/**
* Holds if `t` is a type that is generally used for bulk data in collection types.
* Eg. char[] is roughly equivalent to string and thus a highly
* relevant type for model generation.
*/
private predicate isPrimitiveTypeUsedForBulkData(CS::Type t) {
t instanceof CS::ByteType or
t instanceof CS::CharType
}
/**
* Holds if the collection type `ct` is irrelevant for model generation.
* Collection types where the type of the elements are
* (1) unknown - are considered relevant.
* (2) known - at least one the child types should be relevant (a non-simple type
* or a type used for bulk data)
*/
private predicate irrelevantCollectionType(CS::Type ct) {
Collections::isCollectionType(ct) and
forex(CS::Type child | child = ct.getAChild() |
child instanceof CS::SimpleType and
not isPrimitiveTypeUsedForBulkData(child)
)
}
predicate isSink(DataFlow::Node sink) {
sink instanceof ReturnNodeExt and
sink.getEnclosingCallable() instanceof DataFlowSourceTargetApi
predicate isRelevantType(CS::Type t) {
not t instanceof CS::SimpleType and
not t instanceof CS::Enum and
not t instanceof SystemDateTimeStruct and
not t instanceof SystemTypeClass and
not irrelevantCollectionType(t)
}
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSinkCallContext }
predicate isBarrier(DataFlow::Node n) {
exists(Type t | t = n.getType() and not isRelevantType(t))
/**
* Gets the underlying type of the content `c`.
*/
private CS::Type getUnderlyingContType(DataFlow::Content c) {
result = c.(DataFlow::FieldContent).getField().getType() or
result = c.(DataFlow::SyntheticFieldContent).getField().getType()
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isRelevantTaintStep(node1, node2)
}
}
private module PropagateFromSource = TaintTracking::Global<PropagateFromSourceConfig>;
/**
* Gets the source model(s) of `api`, if there is flow from an existing known source to the return of `api`.
*/
string captureSource(DataFlowSourceTargetApi api) {
exists(DataFlow::Node source, ReturnNodeExt sink, string kind |
PropagateFromSource::flow(source, sink) and
ExternalFlow::sourceNode(source, kind) and
api = sink.getEnclosingCallable() and
not irrelevantSourceSinkApi(source.getEnclosingCallable(), api) and
result = Printing::asSourceModel(api, getOutput(sink), kind)
)
}
/**
* A dataflow configuration used for finding new sinks.
* The sources are the parameters of the API and the fields of the enclosing type.
*
* This can be used to generate Sink summaries for APIs, if the API propagates a parameter (or enclosing type field)
* into an existing known sink (then the API itself becomes a sink).
*/
module PropagateToSinkConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
apiSource(source) and source.getEnclosingCallable() instanceof DataFlowSinkTargetApi
}
predicate isSink(DataFlow::Node sink) {
exists(string kind | isRelevantSinkKind(kind) and ExternalFlow::sinkNode(sink, kind))
}
predicate isBarrier(DataFlow::Node node) {
exists(Type t | t = node.getType() and not isRelevantType(t))
Type getUnderlyingContentType(DataFlow::ContentSet c) {
exists(DataFlow::Content cont |
c.isSingleton(cont) and
result = getUnderlyingContType(cont)
)
or
sinkModelSanitizer(node)
exists(CS::Property p |
c.isProperty(p) and
result = p.getType()
)
}
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
string qualifierString() { result = "Argument[this]" }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isRelevantTaintStep(node1, node2)
string parameterAccess(CS::Parameter p) {
if Collections::isCollectionType(p.getType())
then result = "Argument[" + p.getPosition() + "].Element"
else result = "Argument[" + p.getPosition() + "]"
}
string parameterContentAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
private signature string parameterAccessSig(Parameter p);
private module ParamReturnNodeAsOutput<parameterAccessSig/1 getParamAccess> {
bindingset[c]
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
result = getParamAccess(c.getParameter(pos.getPosition()))
or
pos.isThisParameter() and
result = qualifierString()
}
}
bindingset[c]
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterAccess/1>::paramReturnNodeAsOutput(c, pos)
}
bindingset[c]
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
}
Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asCallable(_)
}
predicate isOwnInstanceAccessNode(DataFlowPrivate::ReturnNode node) {
node.asExpr() instanceof CS::ThisAccess
}
private predicate isRelevantMemberAccess(DataFlow::Node node) {
exists(CS::MemberAccess access | access = node.asExpr() |
access.hasThisQualifier() and
access.getTarget().isEffectivelyPublic() and
(
access instanceof CS::FieldAccess
or
access.getTarget().(CS::Property).getSetter().isPublic()
)
)
}
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
predicate apiSource(DataFlow::Node source) {
isRelevantMemberAccess(source) or source instanceof DataFlow::ParameterNode
}
private predicate uniquelyCalls(DataFlowCallable dc1, DataFlowCallable dc2) {
exists(DataFlowCall call |
dc1 = call.getEnclosingCallable() and
dc2 = unique(DataFlowCallable dc0 | dc0 = viableCallable(call) | dc0)
)
}
bindingset[dc1, dc2]
private predicate uniquelyCallsPlus(DataFlowCallable dc1, DataFlowCallable dc2) =
fastTC(uniquelyCalls/2)(dc1, dc2)
bindingset[sourceEnclosing, api]
predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) {
not exists(DataFlowCallable dc1, DataFlowCallable dc2 |
uniquelyCallsPlus(dc1, dc2) or dc1 = dc2
|
dc1.getUnderlyingCallable() = api and
dc2.getUnderlyingCallable() = sourceEnclosing
)
}
string getInputArgument(DataFlow::Node source) {
exists(int pos |
pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and
result = "Argument[" + pos + "]"
)
or
source.asExpr() instanceof DataFlowPrivate::FieldOrPropertyAccess and
result = qualifierString()
}
bindingset[kind]
predicate isRelevantSinkKind(string kind) { any() }
bindingset[kind]
predicate isRelevantSourceKind(string kind) { any() }
predicate containerContent(DataFlow::ContentSet c) { c.isElement() }
predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
TaintTrackingPrivate::defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and
not nodeTo.asExpr() instanceof CS::ElementAccess and
not exists(DataFlow::ContentSet c |
DataFlowPrivate::readStep(nodeFrom, c, nodeTo) and containerContent(c)
)
}
bindingset[d]
private string getFullyQualifiedName(Declaration d) {
exists(string qualifier, string name |
d.hasFullyQualifiedName(qualifier, name) and
result = QualifiedName::getQualifiedName(qualifier, name)
)
}
predicate isField(DataFlow::ContentSet c) {
c.isField(_) or c.isSyntheticField(_) or c.isProperty(_)
}
string getSyntheticName(DataFlow::ContentSet c) {
exists(CS::Field f |
not f.isEffectivelyPublic() and
c.isField(f) and
result = getFullyQualifiedName(f)
)
or
exists(CS::Property p |
not p.isEffectivelyPublic() and
c.isProperty(p) and
result = getFullyQualifiedName(p)
)
or
c.isSyntheticField(result)
}
string printContent(DataFlow::ContentSet c) {
exists(CS::Field f, string name | name = getFullyQualifiedName(f) |
c.isField(f) and
f.isEffectivelyPublic() and
result = "Field[" + name + "]"
)
or
exists(CS::Property p, string name | name = getFullyQualifiedName(p) |
c.isProperty(p) and
p.isEffectivelyPublic() and
result = "Property[" + name + "]"
)
or
result = "SyntheticField[" + getSyntheticName(c) + "]"
or
c.isElement() and
result = "Element"
}
predicate partialModel = ExternalFlow::partialModel/6;
predicate sourceNode = ExternalFlow::sourceNode/2;
predicate sinkNode = ExternalFlow::sinkNode/2;
}
private module PropagateToSink = TaintTracking::Global<PropagateToSinkConfig>;
/**
* Gets the sink model(s) of `api`, if there is flow from a parameter to an existing known sink.
*/
string captureSink(DataFlowSinkTargetApi api) {
exists(DataFlow::Node src, DataFlow::Node sink, string kind |
PropagateToSink::flow(src, sink) and
ExternalFlow::sinkNode(sink, kind) and
api = src.getEnclosingCallable() and
result = Printing::asSinkModel(api, asInputArgument(src), kind)
)
}
import MakeModelGenerator<Location, CsharpDataFlow, CsharpTaintTracking, ModelGeneratorInput>

View File

@@ -1,5 +1,5 @@
private import csharp as CS
private import codeql.mad.modelgenerator.ModelPrinting
private import codeql.mad.modelgenerator.internal.ModelPrinting
private import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
private module ModelPrintingLang implements ModelPrintingLangSig {

View File

@@ -1,436 +0,0 @@
/**
* Provides predicates related to capturing summary models of the Standard or a 3rd party library.
*/
private import csharp as CS
private import semmle.code.csharp.commons.Util as Util
private import semmle.code.csharp.commons.Collections as Collections
private import semmle.code.csharp.commons.QualifiedName as QualifiedName
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
private import semmle.code.csharp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate as TaintTrackingPrivate
import semmle.code.csharp.dataflow.internal.ExternalFlow as ExternalFlow
import semmle.code.csharp.dataflow.internal.ContentDataFlow as ContentDataFlow
import semmle.code.csharp.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon
import semmle.code.csharp.dataflow.internal.DataFlowPrivate as DataFlowPrivate
import semmle.code.csharp.dataflow.internal.DataFlowDispatch as DataFlowDispatch
module DataFlow = CS::DataFlow;
module TaintTracking = CS::TaintTracking;
class Type = CS::Type;
class Callable = CS::Callable;
class ContentSet = DataFlow::ContentSet;
/**
* Holds if any of the parameters of `api` are `System.Func<>`.
*/
private predicate isHigherOrder(Callable api) {
exists(Type t | t = api.getAParameter().getType().getUnboundDeclaration() |
t instanceof SystemLinqExpressions::DelegateExtType
)
}
private predicate irrelevantAccessor(CS::Accessor a) {
a.getDeclaration().(CS::Property).isReadWrite()
}
private predicate isUninterestingForModels(Callable api) {
api.getDeclaringType().getNamespace().getFullName() = ""
or
api instanceof CS::ConversionOperator
or
api instanceof Util::MainMethod
or
api instanceof CS::Destructor
or
api instanceof CS::AnonymousFunctionExpr
or
api.(CS::Constructor).isParameterless()
or
exists(Type decl | decl = api.getDeclaringType() |
decl instanceof SystemObjectClass or
decl instanceof SystemValueTypeClass
)
or
// Disregard properties that have both a get and a set accessor,
// which implicitly means auto implemented properties.
irrelevantAccessor(api)
}
private predicate relevant(Callable api) {
[api.(CS::Modifiable), api.(CS::Accessor).getDeclaration()].isEffectivelyPublic() and
api.fromSource() and
api.isUnboundDeclaration() and
not isUninterestingForModels(api)
}
private Callable getARelevantOverrideeOrImplementee(Overridable m) {
m.overridesOrImplements(result) and relevant(result)
}
/**
* Gets the super implementation of `api` if it is relevant.
* If such a super implementation does not exist, returns `api` if it is relevant.
*/
private Callable liftedImpl(Callable api) {
(
result = getARelevantOverrideeOrImplementee(api)
or
result = api and relevant(api)
) and
not exists(getARelevantOverrideeOrImplementee(result))
}
private predicate hasManualSummaryModel(Callable api) {
api = any(FlowSummaryImpl::Public::SummarizedCallable sc | sc.applyManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSummaryCallable sc | sc.hasManualModel())
}
private predicate hasManualSourceModel(Callable api) {
api = any(ExternalFlow::SourceCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSourceCallable sc | sc.hasManualModel())
}
private predicate hasManualSinkModel(Callable api) {
api = any(ExternalFlow::SinkCallable sc | sc.hasManualModel()) or
api = any(FlowSummaryImpl::Public::NeutralSinkCallable sc | sc.hasManualModel())
}
/**
* Holds if it is irrelevant to generate models for `api` based on data flow analysis.
*
* This serves as an extra filter for the `relevant` predicate.
*/
predicate isUninterestingForDataFlowModels(CS::Callable api) { isHigherOrder(api) }
/**
* Holds if it is irrelevant to generate models for `api` based on type-based analysis.
*
* This serves as an extra filter for the `relevant` predicate.
*/
predicate isUninterestingForTypeBasedFlowModels(CS::Callable api) { none() }
/**
* A class of callables that are potentially relevant for generating source or
* sink models.
*/
class SourceOrSinkTargetApi extends Callable {
SourceOrSinkTargetApi() { relevant(this) }
}
/**
* A class of callables that are potentially relevant for generating sink models.
*/
class SinkTargetApi extends SourceOrSinkTargetApi {
SinkTargetApi() { not hasManualSinkModel(this) }
}
/**
* A class of callables that are potentially relevant for generating source models.
*/
class SourceTargetApi extends SourceOrSinkTargetApi {
SourceTargetApi() {
not hasManualSourceModel(this) and
// Do not generate source models for overridable callables
// as virtual dispatch implies that too many methods
// will be considered sources.
not this.(Overridable).overridesOrImplements(_)
}
}
/**
* A class of callables that are potentially relevant for generating summary or
* neutral models.
*
* In the Standard library and 3rd party libraries it is the callables (or callables that have a
* super implementation) that can be called from outside the library itself.
*/
class SummaryTargetApi extends Callable {
private Callable lift;
SummaryTargetApi() {
lift = liftedImpl(this) and
not hasManualSummaryModel(lift)
}
/**
* Gets the callable that a model will be lifted to.
*
* The lifted callable is relevant in terms of model
* generation (this is ensured by `liftedImpl`).
*/
Callable lift() { result = lift }
/**
* Holds if `this` is relevant in terms of model generation.
*/
predicate isRelevant() { relevant(this) }
}
/**
* Holds if `t` is a type that is generally used for bulk data in collection types.
* Eg. char[] is roughly equivalent to string and thus a highly
* relevant type for model generation.
*/
private predicate isPrimitiveTypeUsedForBulkData(CS::Type t) {
t instanceof CS::ByteType or
t instanceof CS::CharType
}
/**
* Holds if the collection type `ct` is irrelevant for model generation.
* Collection types where the type of the elements are
* (1) unknown - are considered relevant.
* (2) known - at least one the child types should be relevant (a non-simple type
* or a type used for bulk data)
*/
private predicate irrelevantCollectionType(CS::Type ct) {
Collections::isCollectionType(ct) and
forex(CS::Type child | child = ct.getAChild() |
child instanceof CS::SimpleType and
not isPrimitiveTypeUsedForBulkData(child)
)
}
/**
* Holds for type `t` for fields that are relevant as an intermediate
* read or write step in the data flow analysis.
* That is, flow through any data-flow node that does not have a relevant type
* will be excluded.
*/
predicate isRelevantType(CS::Type t) {
not t instanceof CS::SimpleType and
not t instanceof CS::Enum and
not t instanceof SystemDateTimeStruct and
not t instanceof SystemTypeClass and
not irrelevantCollectionType(t)
}
/**
* Gets the underlying type of the content `c`.
*/
private CS::Type getUnderlyingContType(DataFlow::Content c) {
result = c.(DataFlow::FieldContent).getField().getType() or
result = c.(DataFlow::SyntheticFieldContent).getField().getType()
}
/**
* Gets the underlying type of the content `c`.
*/
CS::Type getUnderlyingContentType(DataFlow::ContentSet c) {
exists(DataFlow::Content cont |
c.isSingleton(cont) and
result = getUnderlyingContType(cont)
)
or
exists(CS::Property p |
c.isProperty(p) and
result = p.getType()
)
}
/**
* Gets the MaD string representation of the qualifier.
*/
string qualifierString() { result = "Argument[this]" }
string parameterAccess(CS::Parameter p) {
if Collections::isCollectionType(p.getType())
then result = "Argument[" + p.getPosition() + "].Element"
else result = "Argument[" + p.getPosition() + "]"
}
/**
* Gets the MaD string representation of the parameter `p`
* when used in content flow.
*/
string parameterContentAccess(CS::Parameter p) { result = "Argument[" + p.getPosition() + "]" }
class InstanceParameterNode = DataFlowPrivate::InstanceParameterNode;
class ParameterPosition = DataFlowDispatch::ParameterPosition;
private signature string parameterAccessSig(Parameter p);
module ParamReturnNodeAsOutput<parameterAccessSig/1 getParamAccess> {
bindingset[c]
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
result = getParamAccess(c.getParameter(pos.getPosition()))
or
pos.isThisParameter() and
result = qualifierString()
}
}
/**
* Gets the MaD string representation of return through parameter at position
* `pos` of callable `c`.
*/
bindingset[c]
string paramReturnNodeAsOutput(CS::Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterAccess/1>::paramReturnNodeAsOutput(c, pos)
}
bindingset[c]
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
result = ParamReturnNodeAsOutput<parameterContentAccess/1>::paramReturnNodeAsOutput(c, pos)
}
/**
* Gets the enclosing callable of `ret`.
*/
Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
result = DataFlowImplCommon::getNodeEnclosingCallable(ret).asCallable(_)
}
/**
* Holds if `node` is an own instance access.
*/
predicate isOwnInstanceAccessNode(DataFlowPrivate::ReturnNode node) {
node.asExpr() instanceof CS::ThisAccess
}
private predicate isRelevantMemberAccess(DataFlow::Node node) {
exists(CS::MemberAccess access | access = node.asExpr() |
access.hasThisQualifier() and
access.getTarget().isEffectivelyPublic() and
(
access instanceof CS::FieldAccess
or
access.getTarget().(CS::Property).getSetter().isPublic()
)
)
}
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
/**
* Holds if `source` is an api entrypoint relevant for creating sink models.
*/
predicate apiSource(DataFlow::Node source) {
isRelevantMemberAccess(source) or source instanceof DataFlow::ParameterNode
}
private predicate uniquelyCalls(DataFlowCallable dc1, DataFlowCallable dc2) {
exists(DataFlowCall call |
dc1 = call.getEnclosingCallable() and
dc2 = unique(DataFlowCallable dc0 | dc0 = viableCallable(call) | dc0)
)
}
bindingset[dc1, dc2]
private predicate uniquelyCallsPlus(DataFlowCallable dc1, DataFlowCallable dc2) =
fastTC(uniquelyCalls/2)(dc1, dc2)
/**
* Holds if it is not relevant to generate a source model for `api`, even
* if flow is detected from a node within `source` to a sink within `api`.
*/
bindingset[sourceEnclosing, api]
predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) {
not exists(DataFlowCallable dc1, DataFlowCallable dc2 | uniquelyCallsPlus(dc1, dc2) or dc1 = dc2 |
dc1.getUnderlyingCallable() = api and
dc2.getUnderlyingCallable() = sourceEnclosing
)
}
/**
* Gets the MaD input string representation of `source`.
*/
string asInputArgumentSpecific(DataFlow::Node source) {
exists(int pos |
pos = source.(DataFlow::ParameterNode).getParameter().getPosition() and
result = "Argument[" + pos + "]"
)
or
source.asExpr() instanceof DataFlowPrivate::FieldOrPropertyAccess and
result = qualifierString()
}
/**
* Holds if `kind` is a relevant sink kind for creating sink models.
*/
bindingset[kind]
predicate isRelevantSinkKind(string kind) { any() }
/**
* Holds if `kind` is a relevant source kind for creating source models.
*/
bindingset[kind]
predicate isRelevantSourceKind(string kind) { any() }
/**
* Holds if the the content `c` is a container.
*/
predicate containerContent(DataFlow::ContentSet c) { c.isElement() }
/**
* Holds if there is a taint step from `node1` to `node2` in content flow.
*/
predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
TaintTrackingPrivate::defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and
not nodeTo.asExpr() instanceof CS::ElementAccess and
not exists(DataFlow::ContentSet c |
DataFlowPrivate::readStep(nodeFrom, c, nodeTo) and containerContent(c)
)
}
bindingset[d]
private string getFullyQualifiedName(Declaration d) {
exists(string qualifier, string name |
d.hasFullyQualifiedName(qualifier, name) and
result = QualifiedName::getQualifiedName(qualifier, name)
)
}
/**
* Holds if the content set `c` is a field, property or synthetic field.
*/
predicate isField(ContentSet c) { c.isField(_) or c.isSyntheticField(_) or c.isProperty(_) }
/**
* Gets the MaD synthetic name string representation for the content set `c`, if any.
*/
string getSyntheticName(DataFlow::ContentSet c) {
exists(CS::Field f |
not f.isEffectivelyPublic() and
c.isField(f) and
result = getFullyQualifiedName(f)
)
or
exists(CS::Property p |
not p.isEffectivelyPublic() and
c.isProperty(p) and
result = getFullyQualifiedName(p)
)
or
c.isSyntheticField(result)
}
/**
* Gets the MaD string representation of the content set `c`.
*/
string printContent(DataFlow::ContentSet c) {
exists(CS::Field f, string name | name = getFullyQualifiedName(f) |
c.isField(f) and
f.isEffectivelyPublic() and
result = "Field[" + name + "]"
)
or
exists(CS::Property p, string name | name = getFullyQualifiedName(p) |
c.isProperty(p) and
p.isEffectivelyPublic() and
result = "Property[" + name + "]"
)
or
result = "SyntheticField[" + getSyntheticName(c) + "]"
or
c.isElement() and
result = "Element"
}

View File

@@ -1,93 +0,0 @@
private import CaptureModels
/**
* Capture fluent APIs that return `this`.
* Example of a fluent API:
* ```csharp
* public class BasicFlow {
* public BasicFlow ReturnThis(object input)
* {
* // some side effect
* return this;
* }
* ```
* Captured Model:
* ```Summaries;BasicFlow;false;ReturnThis;(System.Object);Argument[this];ReturnValue;value;df-generated```
* Capture APIs that transfer taint from an input parameter to an output return
* value or parameter.
* Allows a sequence of read steps followed by a sequence of store steps.
*
* Examples:
*
* ```csharp
* public class BasicFlow {
* private string tainted;
*
* public String ReturnField()
* {
* return tainted;
* }
*
* public void AssignFieldToArray(object[] target)
* {
* target[0] = tainted;
* }
* }
* ```
* Captured Models:
* ```
* Summaries;BasicFlow;false;ReturnField;();Argument[this];ReturnValue;taint;df-generated |
* Summaries;BasicFlow;false;AssignFieldToArray;(System.Object[]);Argument[this];Argument[0].Element;taint;df-generated
* ```
*
* ```csharp
* public class BasicFlow {
* private string tainted;
*
* public void SetField(string s)
* {
* tainted = s;
* }
* }
* ```
* Captured Model:
* ```Summaries;BasicFlow;false;SetField;(System.String);Argument[0];Argument[this];taint;df-generated```
*
* ```csharp
* public class BasicFlow {
* public void ReturnSubstring(string s)
* {
* return s.Substring(0, 1);
* }
* }
* ```
* Captured Model:
* ```Summaries;BasicFlow;false;ReturnSubstring;(System.String);Argument[0];ReturnValue;taint;df-generated```
*
* ```csharp
* public class BasicFlow {
* public void AssignToArray(int data, int[] target)
* {
* target[0] = data;
* }
* }
* ```
* Captured Model:
* ```Summaries;BasicFlow;false;AssignToArray;(System.Int32,System.Int32[]);Argument[0];Argument[1].Element;taint;df-generated```
*/
string captureFlow(DataFlowSummaryTargetApi api) {
result = captureQualifierFlow(api) or
result = captureThroughFlow(api)
}
/**
* Gets the neutral summary model for `api`, if any.
* A neutral summary model is generated, if we are not generating
* a summary model that applies to `api` and if it relevant to generate
* a model for `api`.
*/
string captureNoFlow(DataFlowSummaryTargetApi api) {
not exists(DataFlowSummaryTargetApi api0 | exists(captureFlow(api0)) and api0.lift() = api.lift()) and
api.isRelevant() and
result = Printing::asNeutralSummaryModel(api)
}

View File

@@ -2,7 +2,7 @@ private import csharp
private import semmle.code.csharp.frameworks.system.collections.Generic as GenericCollections
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
private import semmle.code.csharp.frameworks.system.linq.Expressions
private import CaptureModelsSpecific as Specific
private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput
private import CaptureModelsPrinting
/**
@@ -38,7 +38,7 @@ private predicate localTypeParameter(Callable callable, TypeParameter tp) {
*/
private predicate parameter(Callable callable, string input, TypeParameter tp) {
exists(Parameter p |
input = Specific::parameterAccess(p) and
input = ModelGeneratorInput::parameterAccess(p) and
p = callable.getAParameter() and
(
// Parameter of type tp
@@ -69,7 +69,7 @@ private string implicit(Callable callable, TypeParameter tp) {
then access = ".Element"
else access = getSyntheticField(tp)
|
result = Specific::qualifierString() + access
result = ModelGeneratorInput::qualifierString() + access
)
}
@@ -191,9 +191,7 @@ private module Printing = ModelPrinting<ModelPrintingInput>;
* A class of callables that are relevant generating summaries for based
* on the Theorems for Free approach.
*/
class TypeBasedFlowTargetApi extends Specific::SummaryTargetApi {
TypeBasedFlowTargetApi() { not Specific::isUninterestingForTypeBasedFlowModels(this) }
class TypeBasedFlowTargetApi extends ModelGeneratorInput::SummaryTargetApi {
/**
* Gets the string representation of all type based summaries for `this`
* inspired by the Theorems for Free approach.

View File

@@ -293,7 +293,8 @@ namespace My.Qltest
}
// Test synthetic fields
public class K {
public class K
{
public object MyField;
@@ -309,19 +310,22 @@ namespace My.Qltest
public object GetMyFieldOnSyntheticField() => throw null;
public void M1() {
public void M1()
{
var o = new object();
SetMySyntheticField(o);
Sink(GetMySyntheticField());
}
public void M2() {
public void M2()
{
var o = new object();
SetMyNestedSyntheticField(o);
Sink(GetMyNestedSyntheticField());
}
public void M3() {
public void M3()
{
var o = new object();
SetMyFieldOnSyntheticField(o);
Sink(GetMyFieldOnSyntheticField());
@@ -329,4 +333,19 @@ namespace My.Qltest
static void Sink(object o) { }
}
// Test content data flow provenance.
public class L
{
public void M1()
{
var l = new Library();
var o = new object();
l.SetValue(o);
Sink(l.GetValue());
}
static void Sink(object o) { }
}
}

View File

@@ -13,5 +13,9 @@ namespace My.Qltest
public static object StepArgReturnGenerated(object x) => throw null;
public static object StepArgReturnGeneratedIgnored(object x) => throw null;
public void SetValue(object o) => throw null;
public object GetValue() => throw null;
}
}

View File

@@ -30,6 +30,8 @@ models
| 29 | Summary: My.Qltest; K; false; GetMyNestedSyntheticField; (); ; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]; ReturnValue; value; manual |
| 30 | Summary: My.Qltest; K; false; SetMyFieldOnSyntheticField; (System.Object); ; Argument[0]; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]; value; manual |
| 31 | Summary: My.Qltest; K; false; GetMyFieldOnSyntheticField; (); ; Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]; ReturnValue; value; manual |
| 32 | Summary: My.Qltest; Library; false; SetValue; (System.Object); ; Argument[0]; Argument[this].SyntheticField[X]; value; dfc-generated |
| 33 | Summary: My.Qltest; Library; false; GetValue; (); ; Argument[this].SyntheticField[X]; ReturnValue; value; dfc-generated |
edges
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | ExternalFlow.cs:10:29:10:32 | access to local variable arg1 : Object | provenance | |
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | provenance | |
@@ -127,21 +129,26 @@ edges
| ExternalFlow.cs:279:13:279:23 | [post] this access : J | ExternalFlow.cs:281:18:281:21 | this access : J | provenance | |
| ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | ExternalFlow.cs:279:13:279:23 | [post] this access : J | provenance | MaD:25 |
| ExternalFlow.cs:281:18:281:21 | this access : J | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | provenance | MaD:24 |
| ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | |
| ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | MaD:26 |
| ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | provenance | MaD:27 |
| ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | |
| ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | MaD:28 |
| ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | provenance | MaD:29 |
| ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | |
| ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | MaD:30 |
| ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | provenance | MaD:31 |
| ExternalFlow.cs:315:17:315:17 | access to local variable o : Object | ExternalFlow.cs:316:33:316:33 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:315:21:315:32 | object creation of type Object : Object | ExternalFlow.cs:315:17:315:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:316:13:316:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:317:18:317:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | |
| ExternalFlow.cs:316:33:316:33 | access to local variable o : Object | ExternalFlow.cs:316:13:316:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | provenance | MaD:26 |
| ExternalFlow.cs:317:18:317:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | ExternalFlow.cs:317:18:317:38 | call to method GetMySyntheticField | provenance | MaD:27 |
| ExternalFlow.cs:322:17:322:17 | access to local variable o : Object | ExternalFlow.cs:323:39:323:39 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:322:21:322:32 | object creation of type Object : Object | ExternalFlow.cs:322:17:322:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:323:13:323:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:324:18:324:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | |
| ExternalFlow.cs:323:39:323:39 | access to local variable o : Object | ExternalFlow.cs:323:13:323:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | provenance | MaD:28 |
| ExternalFlow.cs:324:18:324:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | ExternalFlow.cs:324:18:324:44 | call to method GetMyNestedSyntheticField | provenance | MaD:29 |
| ExternalFlow.cs:329:17:329:17 | access to local variable o : Object | ExternalFlow.cs:330:40:330:40 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:329:21:329:32 | object creation of type Object : Object | ExternalFlow.cs:329:17:329:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:330:13:330:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:331:18:331:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | |
| ExternalFlow.cs:330:40:330:40 | access to local variable o : Object | ExternalFlow.cs:330:13:330:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | provenance | MaD:30 |
| ExternalFlow.cs:331:18:331:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | ExternalFlow.cs:331:18:331:45 | call to method GetMyFieldOnSyntheticField | provenance | MaD:31 |
| ExternalFlow.cs:343:17:343:17 | access to local variable o : Object | ExternalFlow.cs:344:24:344:24 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:343:21:343:32 | object creation of type Object : Object | ExternalFlow.cs:343:17:343:17 | access to local variable o : Object | provenance | |
| ExternalFlow.cs:344:13:344:13 | [post] access to local variable l : Library [synthetic X] : Object | ExternalFlow.cs:345:18:345:18 | access to local variable l : Library [synthetic X] : Object | provenance | |
| ExternalFlow.cs:344:24:344:24 | access to local variable o : Object | ExternalFlow.cs:344:13:344:13 | [post] access to local variable l : Library [synthetic X] : Object | provenance | MaD:32 |
| ExternalFlow.cs:345:18:345:18 | access to local variable l : Library [synthetic X] : Object | ExternalFlow.cs:345:18:345:29 | call to method GetValue | provenance | MaD:33 |
nodes
| ExternalFlow.cs:9:20:9:23 | access to local variable arg1 : Object | semmle.label | access to local variable arg1 : Object |
| ExternalFlow.cs:9:27:9:38 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
@@ -261,24 +268,30 @@ nodes
| ExternalFlow.cs:279:22:279:22 | access to local variable j : Object | semmle.label | access to local variable j : Object |
| ExternalFlow.cs:281:18:281:21 | this access : J | semmle.label | this access : J |
| ExternalFlow.cs:281:18:281:27 | access to property Prop1 | semmle.label | access to property Prop1 |
| ExternalFlow.cs:313:17:313:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:314:13:314:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object |
| ExternalFlow.cs:314:33:314:33 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | semmle.label | call to method GetMySyntheticField |
| ExternalFlow.cs:315:18:315:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object |
| ExternalFlow.cs:319:17:319:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:320:13:320:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object |
| ExternalFlow.cs:320:39:320:39 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | semmle.label | call to method GetMyNestedSyntheticField |
| ExternalFlow.cs:321:18:321:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object |
| ExternalFlow.cs:325:17:325:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:326:13:326:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object |
| ExternalFlow.cs:326:40:326:40 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | semmle.label | call to method GetMyFieldOnSyntheticField |
| ExternalFlow.cs:327:18:327:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object |
| ExternalFlow.cs:315:17:315:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:315:21:315:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:316:13:316:34 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField] : Object |
| ExternalFlow.cs:316:33:316:33 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:317:18:317:38 | call to method GetMySyntheticField | semmle.label | call to method GetMySyntheticField |
| ExternalFlow.cs:317:18:317:38 | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField] : Object |
| ExternalFlow.cs:322:17:322:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:322:21:322:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:323:13:323:40 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object |
| ExternalFlow.cs:323:39:323:39 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:324:18:324:44 | call to method GetMyNestedSyntheticField | semmle.label | call to method GetMyNestedSyntheticField |
| ExternalFlow.cs:324:18:324:44 | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField1, synthetic MySyntheticField1.MyNestedSyntheticField] : Object |
| ExternalFlow.cs:329:17:329:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:329:21:329:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:330:13:330:41 | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | [post] this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object |
| ExternalFlow.cs:330:40:330:40 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:331:18:331:45 | call to method GetMyFieldOnSyntheticField | semmle.label | call to method GetMyFieldOnSyntheticField |
| ExternalFlow.cs:331:18:331:45 | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object | semmle.label | this access : K [synthetic My.Qltest.K.MySyntheticField2, field MyField] : Object |
| ExternalFlow.cs:343:17:343:17 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:343:21:343:32 | object creation of type Object : Object | semmle.label | object creation of type Object : Object |
| ExternalFlow.cs:344:13:344:13 | [post] access to local variable l : Library [synthetic X] : Object | semmle.label | [post] access to local variable l : Library [synthetic X] : Object |
| ExternalFlow.cs:344:24:344:24 | access to local variable o : Object | semmle.label | access to local variable o : Object |
| ExternalFlow.cs:345:18:345:18 | access to local variable l : Library [synthetic X] : Object | semmle.label | access to local variable l : Library [synthetic X] : Object |
| ExternalFlow.cs:345:18:345:29 | call to method GetValue | semmle.label | call to method GetValue |
subpaths
| ExternalFlow.cs:84:29:84:32 | access to local variable objs : null [element] : Object | ExternalFlow.cs:84:35:84:35 | o : Object | ExternalFlow.cs:84:40:84:40 | access to parameter o : Object | ExternalFlow.cs:84:25:84:41 | call to method Map<Object,Object> : T[] [element] : Object |
invalidModelRow
@@ -308,6 +321,7 @@ invalidModelRow
| ExternalFlow.cs:240:18:240:18 | access to local variable o | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | ExternalFlow.cs:240:18:240:18 | access to local variable o | $@ | ExternalFlow.cs:238:21:238:28 | object creation of type HC : HC | object creation of type HC : HC |
| ExternalFlow.cs:258:18:258:18 | access to local variable b | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | ExternalFlow.cs:258:18:258:18 | access to local variable b | $@ | ExternalFlow.cs:256:20:256:31 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:281:18:281:27 | access to property Prop1 | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | ExternalFlow.cs:281:18:281:27 | access to property Prop1 | $@ | ExternalFlow.cs:278:21:278:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | ExternalFlow.cs:315:18:315:38 | call to method GetMySyntheticField | $@ | ExternalFlow.cs:313:21:313:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | ExternalFlow.cs:321:18:321:44 | call to method GetMyNestedSyntheticField | $@ | ExternalFlow.cs:319:21:319:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | ExternalFlow.cs:327:18:327:45 | call to method GetMyFieldOnSyntheticField | $@ | ExternalFlow.cs:325:21:325:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:317:18:317:38 | call to method GetMySyntheticField | ExternalFlow.cs:315:21:315:32 | object creation of type Object : Object | ExternalFlow.cs:317:18:317:38 | call to method GetMySyntheticField | $@ | ExternalFlow.cs:315:21:315:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:324:18:324:44 | call to method GetMyNestedSyntheticField | ExternalFlow.cs:322:21:322:32 | object creation of type Object : Object | ExternalFlow.cs:324:18:324:44 | call to method GetMyNestedSyntheticField | $@ | ExternalFlow.cs:322:21:322:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:331:18:331:45 | call to method GetMyFieldOnSyntheticField | ExternalFlow.cs:329:21:329:32 | object creation of type Object : Object | ExternalFlow.cs:331:18:331:45 | call to method GetMyFieldOnSyntheticField | $@ | ExternalFlow.cs:329:21:329:32 | object creation of type Object : Object | object creation of type Object : Object |
| ExternalFlow.cs:345:18:345:29 | call to method GetValue | ExternalFlow.cs:343:21:343:32 | object creation of type Object : Object | ExternalFlow.cs:345:18:345:29 | call to method GetValue | $@ | ExternalFlow.cs:343:21:343:32 | object creation of type Object : Object | object creation of type Object : Object |

View File

@@ -43,6 +43,8 @@ extensions:
- ["My.Qltest", "K", false, "GetMyNestedSyntheticField", "()", "", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField1].SyntheticField[MySyntheticField1.MyNestedSyntheticField]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "K", false, "SetMyFieldOnSyntheticField", "(System.Object)", "", "Argument[0]", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]", "value", "manual"]
- ["My.Qltest", "K", false, "GetMyFieldOnSyntheticField", "()", "", "Argument[this].SyntheticField[My.Qltest.K.MySyntheticField2].Field[My.Qltest.K.MyField]", "ReturnValue", "value", "manual"]
- ["My.Qltest", "Library", false, "SetValue", "(System.Object)", "", "Argument[0]", "Argument[this].SyntheticField[X]", "value", "dfc-generated"]
- ["My.Qltest", "Library", false, "GetValue", "()", "", "Argument[this].SyntheticField[X]", "ReturnValue", "value", "dfc-generated"]
- addsTo:
pack: codeql/csharp-all

View File

@@ -2,5 +2,5 @@ import csharp
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
from DataFlow::Node source
where source instanceof ThreatModelFlowSource
where source instanceof ActiveThreatModelSource
select source

View File

@@ -2,7 +2,7 @@ import csharp
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
module CommandLineFlowConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))

View File

@@ -2,5 +2,5 @@ import csharp
import semmle.code.csharp.security.dataflow.flowsources.FlowSources
from DataFlow::Node source
where source instanceof ThreatModelFlowSource
where source instanceof ActiveThreatModelSource
select source, source.(SourceNode).getThreatModel()

View File

@@ -4,7 +4,7 @@ import TestUtilities.InlineFlowTest
import TaintFlowTest<DatabaseConfig>
module DatabaseConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))

View File

@@ -4,7 +4,7 @@ import TestUtilities.InlineFlowTest
import TaintFlowTest<FilesConfig>
module FilesConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) {
exists(MethodCall mc | mc.getTarget().hasName("Sink") | sink.asExpr() = mc.getArgument(0))

View File

@@ -4,7 +4,7 @@ private import semmle.code.csharp.dataflow.internal.ExternalFlow
private import semmle.code.csharp.security.dataflow.flowsources.FlowSources
private module ThreatModelConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) { sinkNode(sink, _) }
}

View File

@@ -1,5 +1,5 @@
| script.aspx:4:1:4:23 | <%= ... %> | XSS.cs:115:16:115:29 | someJavascript |
| script.aspx:8:1:8:12 | <%= ... %> | XSS.cs:122:24:122:28 | Field |
| script.aspx:4:1:4:23 | <%= ... %> | XSS.cs:120:16:120:29 | someJavascript |
| script.aspx:8:1:8:12 | <%= ... %> | XSS.cs:127:24:127:28 | Field |
| script.aspx:12:1:12:14 | <%= ... %> | <outside test directory> | Request |
| script.aspx:16:1:16:34 | <%= ... %> | <outside test directory> | QueryString |
| script.aspx:20:1:20:41 | <%= ... %> | <outside test directory> | QueryString |

View File

@@ -17,6 +17,7 @@ namespace Test
Table table;
Label label;
string connectionString;
public Button button;
public void WebUIXSS()
{
@@ -100,6 +101,10 @@ namespace Test
// GOOD: HTML encoding
string name = context.Request.QueryString["name"];
new StringContent(HttpUtility.HtmlEncode(name));
// GOOD: Implicit HTML encoding
string html = context.Request.QueryString["html"];
button.Attributes.Add("data-href", html);
}
public void UrlEncoded(HttpContextBase context)

View File

@@ -1,50 +1,50 @@
#select
| XSS.cs:26:32:26:51 | call to method ToString | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | XSS.cs:26:32:26:51 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:27:29:27:48 | call to method ToString | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | XSS.cs:27:29:27:48 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:28:26:28:45 | call to method ToString | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | XSS.cs:28:26:28:45 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:38:36:38:39 | access to local variable name | XSS.cs:37:27:37:53 | access to property QueryString : NameValueCollection | XSS.cs:38:36:38:39 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:37:27:37:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:59:22:59:25 | access to local variable name | XSS.cs:57:27:57:65 | access to property QueryString : NameValueCollection | XSS.cs:59:22:59:25 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:57:27:57:65 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:76:36:76:39 | access to local variable name | XSS.cs:75:27:75:53 | access to property QueryString : NameValueCollection | XSS.cs:76:36:76:39 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:75:27:75:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:79:36:79:40 | access to local variable name2 | XSS.cs:78:28:78:42 | access to property Request : HttpRequestBase | XSS.cs:79:36:79:40 | access to local variable name2 | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:78:28:78:42 | access to property Request : HttpRequestBase | User-provided value |
| XSS.cs:86:28:86:31 | access to local variable name | XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | XSS.cs:86:28:86:31 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:87:31:87:34 | access to local variable name | XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | XSS.cs:87:31:87:34 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:95:31:95:34 | access to local variable name | XSS.cs:94:27:94:53 | access to property QueryString : NameValueCollection | XSS.cs:95:31:95:34 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:94:27:94:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:135:20:135:33 | access to property RawUrl | XSS.cs:135:20:135:33 | access to property RawUrl | XSS.cs:135:20:135:33 | access to property RawUrl | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:135:20:135:33 | access to property RawUrl | User-provided value |
| XSS.cs:27:32:27:51 | call to method ToString | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | XSS.cs:27:32:27:51 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:28:29:28:48 | call to method ToString | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | XSS.cs:28:29:28:48 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:29:26:29:45 | call to method ToString | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | XSS.cs:29:26:29:45 | call to method ToString | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | User-provided value |
| XSS.cs:39:36:39:39 | access to local variable name | XSS.cs:38:27:38:53 | access to property QueryString : NameValueCollection | XSS.cs:39:36:39:39 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:38:27:38:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:60:22:60:25 | access to local variable name | XSS.cs:58:27:58:65 | access to property QueryString : NameValueCollection | XSS.cs:60:22:60:25 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:58:27:58:65 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:77:36:77:39 | access to local variable name | XSS.cs:76:27:76:53 | access to property QueryString : NameValueCollection | XSS.cs:77:36:77:39 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:76:27:76:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:80:36:80:40 | access to local variable name2 | XSS.cs:79:28:79:42 | access to property Request : HttpRequestBase | XSS.cs:80:36:80:40 | access to local variable name2 | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:79:28:79:42 | access to property Request : HttpRequestBase | User-provided value |
| XSS.cs:87:28:87:31 | access to local variable name | XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | XSS.cs:87:28:87:31 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:88:31:88:34 | access to local variable name | XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | XSS.cs:88:31:88:34 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:96:31:96:34 | access to local variable name | XSS.cs:95:27:95:53 | access to property QueryString : NameValueCollection | XSS.cs:96:31:96:34 | access to local variable name | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:95:27:95:53 | access to property QueryString : NameValueCollection | User-provided value |
| XSS.cs:140:20:140:33 | access to property RawUrl | XSS.cs:140:20:140:33 | access to property RawUrl | XSS.cs:140:20:140:33 | access to property RawUrl | $@ flows to here and is written to HTML or JavaScript. | XSS.cs:140:20:140:33 | access to property RawUrl | User-provided value |
| script.aspx:12:1:12:14 | <%= ... %> | script.aspx:12:1:12:14 | <%= ... %> | script.aspx:12:1:12:14 | <%= ... %> | $@ flows to here and is a remote source accessed inline in an ASPX page. | script.aspx:12:1:12:14 | <%= ... %> | User-provided value |
| script.aspx:16:1:16:34 | <%= ... %> | script.aspx:16:1:16:34 | <%= ... %> | script.aspx:16:1:16:34 | <%= ... %> | $@ flows to here and is a remote source accessed inline in an ASPX page. | script.aspx:16:1:16:34 | <%= ... %> | User-provided value |
| script.aspx:20:1:20:41 | <%= ... %> | script.aspx:20:1:20:41 | <%= ... %> | script.aspx:20:1:20:41 | <%= ... %> | $@ flows to here and is a remote source accessed inline in an ASPX page. | script.aspx:20:1:20:41 | <%= ... %> | User-provided value |
edges
| XSS.cs:25:13:25:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:26:32:26:40 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:25:13:25:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:27:29:27:37 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:25:13:25:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:28:26:28:34 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | XSS.cs:25:48:25:67 | access to property Text : String | provenance | MaD:4 |
| XSS.cs:25:48:25:67 | access to property Text : String | XSS.cs:25:13:25:21 | [post] access to local variable userInput : StringBuilder | provenance | MaD:2 |
| XSS.cs:26:32:26:40 | access to local variable userInput : StringBuilder | XSS.cs:26:32:26:51 | call to method ToString | provenance | MaD:3 |
| XSS.cs:27:29:27:37 | access to local variable userInput : StringBuilder | XSS.cs:27:29:27:48 | call to method ToString | provenance | MaD:3 |
| XSS.cs:28:26:28:34 | access to local variable userInput : StringBuilder | XSS.cs:28:26:28:45 | call to method ToString | provenance | MaD:3 |
| XSS.cs:37:20:37:23 | access to local variable name : String | XSS.cs:38:36:38:39 | access to local variable name | provenance | Sink:MaD:5 |
| XSS.cs:37:27:37:53 | access to property QueryString : NameValueCollection | XSS.cs:37:20:37:23 | access to local variable name : String | provenance | |
| XSS.cs:37:27:37:53 | access to property QueryString : NameValueCollection | XSS.cs:37:27:37:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:37:27:37:61 | access to indexer : String | XSS.cs:37:20:37:23 | access to local variable name : String | provenance | |
| XSS.cs:57:20:57:23 | access to local variable name : String | XSS.cs:59:22:59:25 | access to local variable name | provenance | |
| XSS.cs:57:27:57:65 | access to property QueryString : NameValueCollection | XSS.cs:57:20:57:23 | access to local variable name : String | provenance | |
| XSS.cs:57:27:57:65 | access to property QueryString : NameValueCollection | XSS.cs:57:27:57:73 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:57:27:57:73 | access to indexer : String | XSS.cs:57:20:57:23 | access to local variable name : String | provenance | |
| XSS.cs:75:20:75:23 | access to local variable name : String | XSS.cs:76:36:76:39 | access to local variable name | provenance | |
| XSS.cs:75:27:75:53 | access to property QueryString : NameValueCollection | XSS.cs:75:20:75:23 | access to local variable name : String | provenance | |
| XSS.cs:75:27:75:53 | access to property QueryString : NameValueCollection | XSS.cs:75:27:75:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:75:27:75:61 | access to indexer : String | XSS.cs:75:20:75:23 | access to local variable name : String | provenance | |
| XSS.cs:78:20:78:24 | access to local variable name2 : String | XSS.cs:79:36:79:40 | access to local variable name2 | provenance | |
| XSS.cs:78:28:78:42 | access to property Request : HttpRequestBase | XSS.cs:78:20:78:24 | access to local variable name2 : String | provenance | |
| XSS.cs:85:20:85:23 | access to local variable name : String | XSS.cs:86:28:86:31 | access to local variable name | provenance | |
| XSS.cs:85:20:85:23 | access to local variable name : String | XSS.cs:87:31:87:34 | access to local variable name | provenance | |
| XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | XSS.cs:85:20:85:23 | access to local variable name : String | provenance | |
| XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | XSS.cs:85:27:85:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:85:27:85:61 | access to indexer : String | XSS.cs:85:20:85:23 | access to local variable name : String | provenance | |
| XSS.cs:94:20:94:23 | access to local variable name : String | XSS.cs:95:31:95:34 | access to local variable name | provenance | Sink:MaD:1 |
| XSS.cs:94:27:94:53 | access to property QueryString : NameValueCollection | XSS.cs:94:20:94:23 | access to local variable name : String | provenance | |
| XSS.cs:94:27:94:53 | access to property QueryString : NameValueCollection | XSS.cs:94:27:94:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:94:27:94:61 | access to indexer : String | XSS.cs:94:20:94:23 | access to local variable name : String | provenance | |
| XSS.cs:26:13:26:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:27:32:27:40 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:26:13:26:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:28:29:28:37 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:26:13:26:21 | [post] access to local variable userInput : StringBuilder | XSS.cs:29:26:29:34 | access to local variable userInput : StringBuilder | provenance | |
| XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | XSS.cs:26:48:26:67 | access to property Text : String | provenance | MaD:4 |
| XSS.cs:26:48:26:67 | access to property Text : String | XSS.cs:26:13:26:21 | [post] access to local variable userInput : StringBuilder | provenance | MaD:2 |
| XSS.cs:27:32:27:40 | access to local variable userInput : StringBuilder | XSS.cs:27:32:27:51 | call to method ToString | provenance | MaD:3 |
| XSS.cs:28:29:28:37 | access to local variable userInput : StringBuilder | XSS.cs:28:29:28:48 | call to method ToString | provenance | MaD:3 |
| XSS.cs:29:26:29:34 | access to local variable userInput : StringBuilder | XSS.cs:29:26:29:45 | call to method ToString | provenance | MaD:3 |
| XSS.cs:38:20:38:23 | access to local variable name : String | XSS.cs:39:36:39:39 | access to local variable name | provenance | Sink:MaD:5 |
| XSS.cs:38:27:38:53 | access to property QueryString : NameValueCollection | XSS.cs:38:20:38:23 | access to local variable name : String | provenance | |
| XSS.cs:38:27:38:53 | access to property QueryString : NameValueCollection | XSS.cs:38:27:38:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:38:27:38:61 | access to indexer : String | XSS.cs:38:20:38:23 | access to local variable name : String | provenance | |
| XSS.cs:58:20:58:23 | access to local variable name : String | XSS.cs:60:22:60:25 | access to local variable name | provenance | |
| XSS.cs:58:27:58:65 | access to property QueryString : NameValueCollection | XSS.cs:58:20:58:23 | access to local variable name : String | provenance | |
| XSS.cs:58:27:58:65 | access to property QueryString : NameValueCollection | XSS.cs:58:27:58:73 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:58:27:58:73 | access to indexer : String | XSS.cs:58:20:58:23 | access to local variable name : String | provenance | |
| XSS.cs:76:20:76:23 | access to local variable name : String | XSS.cs:77:36:77:39 | access to local variable name | provenance | |
| XSS.cs:76:27:76:53 | access to property QueryString : NameValueCollection | XSS.cs:76:20:76:23 | access to local variable name : String | provenance | |
| XSS.cs:76:27:76:53 | access to property QueryString : NameValueCollection | XSS.cs:76:27:76:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:76:27:76:61 | access to indexer : String | XSS.cs:76:20:76:23 | access to local variable name : String | provenance | |
| XSS.cs:79:20:79:24 | access to local variable name2 : String | XSS.cs:80:36:80:40 | access to local variable name2 | provenance | |
| XSS.cs:79:28:79:42 | access to property Request : HttpRequestBase | XSS.cs:79:20:79:24 | access to local variable name2 : String | provenance | |
| XSS.cs:86:20:86:23 | access to local variable name : String | XSS.cs:87:28:87:31 | access to local variable name | provenance | |
| XSS.cs:86:20:86:23 | access to local variable name : String | XSS.cs:88:31:88:34 | access to local variable name | provenance | |
| XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | XSS.cs:86:20:86:23 | access to local variable name : String | provenance | |
| XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | XSS.cs:86:27:86:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:86:27:86:61 | access to indexer : String | XSS.cs:86:20:86:23 | access to local variable name : String | provenance | |
| XSS.cs:95:20:95:23 | access to local variable name : String | XSS.cs:96:31:96:34 | access to local variable name | provenance | Sink:MaD:1 |
| XSS.cs:95:27:95:53 | access to property QueryString : NameValueCollection | XSS.cs:95:20:95:23 | access to local variable name : String | provenance | |
| XSS.cs:95:27:95:53 | access to property QueryString : NameValueCollection | XSS.cs:95:27:95:61 | access to indexer : String | provenance | MaD:6 |
| XSS.cs:95:27:95:61 | access to indexer : String | XSS.cs:95:20:95:23 | access to local variable name : String | provenance | |
| script.aspx:12:1:12:14 | <%= ... %> | script.aspx:12:1:12:14 | <%= ... %> | provenance | |
| script.aspx:16:1:16:34 | <%= ... %> | script.aspx:16:1:16:34 | <%= ... %> | provenance | |
| script.aspx:20:1:20:41 | <%= ... %> | script.aspx:20:1:20:41 | <%= ... %> | provenance | |
@@ -56,40 +56,40 @@ models
| 5 | Sink: System.Web; HttpResponse; false; Write; ; ; Argument[0]; html-injection; manual |
| 6 | Summary: System.Collections.Specialized; NameValueCollection; false; get_Item; (System.String); ; Argument[this]; ReturnValue; taint; df-generated |
nodes
| XSS.cs:25:13:25:21 | [post] access to local variable userInput : StringBuilder | semmle.label | [post] access to local variable userInput : StringBuilder |
| XSS.cs:25:48:25:62 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
| XSS.cs:25:48:25:67 | access to property Text : String | semmle.label | access to property Text : String |
| XSS.cs:26:32:26:40 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:26:32:26:51 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:27:29:27:37 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:27:29:27:48 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:28:26:28:34 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:28:26:28:45 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:37:20:37:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:37:27:37:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:37:27:37:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:38:36:38:39 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:57:20:57:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:57:27:57:65 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:57:27:57:73 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:59:22:59:25 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:75:20:75:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:75:27:75:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:75:27:75:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:76:36:76:39 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:78:20:78:24 | access to local variable name2 : String | semmle.label | access to local variable name2 : String |
| XSS.cs:78:28:78:42 | access to property Request : HttpRequestBase | semmle.label | access to property Request : HttpRequestBase |
| XSS.cs:79:36:79:40 | access to local variable name2 | semmle.label | access to local variable name2 |
| XSS.cs:85:20:85:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:85:27:85:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:85:27:85:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:86:28:86:31 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:87:31:87:34 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:94:20:94:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:94:27:94:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:94:27:94:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:95:31:95:34 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:135:20:135:33 | access to property RawUrl | semmle.label | access to property RawUrl |
| XSS.cs:26:13:26:21 | [post] access to local variable userInput : StringBuilder | semmle.label | [post] access to local variable userInput : StringBuilder |
| XSS.cs:26:48:26:62 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
| XSS.cs:26:48:26:67 | access to property Text : String | semmle.label | access to property Text : String |
| XSS.cs:27:32:27:40 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:27:32:27:51 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:28:29:28:37 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:28:29:28:48 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:29:26:29:34 | access to local variable userInput : StringBuilder | semmle.label | access to local variable userInput : StringBuilder |
| XSS.cs:29:26:29:45 | call to method ToString | semmle.label | call to method ToString |
| XSS.cs:38:20:38:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:38:27:38:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:38:27:38:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:39:36:39:39 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:58:20:58:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:58:27:58:65 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:58:27:58:73 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:60:22:60:25 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:76:20:76:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:76:27:76:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:76:27:76:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:77:36:77:39 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:79:20:79:24 | access to local variable name2 : String | semmle.label | access to local variable name2 : String |
| XSS.cs:79:28:79:42 | access to property Request : HttpRequestBase | semmle.label | access to property Request : HttpRequestBase |
| XSS.cs:80:36:80:40 | access to local variable name2 | semmle.label | access to local variable name2 |
| XSS.cs:86:20:86:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:86:27:86:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:86:27:86:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:87:28:87:31 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:88:31:88:34 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:95:20:95:23 | access to local variable name : String | semmle.label | access to local variable name : String |
| XSS.cs:95:27:95:53 | access to property QueryString : NameValueCollection | semmle.label | access to property QueryString : NameValueCollection |
| XSS.cs:95:27:95:61 | access to indexer : String | semmle.label | access to indexer : String |
| XSS.cs:96:31:96:34 | access to local variable name | semmle.label | access to local variable name |
| XSS.cs:140:20:140:33 | access to property RawUrl | semmle.label | access to property RawUrl |
| script.aspx:12:1:12:14 | <%= ... %> | semmle.label | <%= ... %> |
| script.aspx:16:1:16:34 | <%= ... %> | semmle.label | <%= ... %> |
| script.aspx:20:1:20:41 | <%= ... %> | semmle.label | <%= ... %> |

View File

@@ -3,7 +3,7 @@ import utils.modelgenerator.internal.CaptureModels
import TestUtilities.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {
string getCapturedModel(Callable c) { result = captureContentFlow(c) }
string getCapturedModel(Callable c) { result = ContentSensitive::captureFlow(c, _) }
string getKind() { result = "contentbased-summary" }
}

View File

@@ -1,5 +1,5 @@
import csharp
import utils.modelgenerator.internal.CaptureSummaryFlowQuery
import utils.modelgenerator.internal.CaptureModels
import TestUtilities.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {

View File

@@ -1,5 +1,5 @@
import csharp
import utils.modelgenerator.internal.CaptureSummaryFlowQuery
import utils.modelgenerator.internal.CaptureModels
import TestUtilities.InlineMadTest
module InlineMadTestConfig implements InlineMadTestConfigSig {

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