зеркало из https://github.com/github/codeql.git
Merge branch 'main' into henrymercer/rc-3.15-mergeback
This commit is contained in:
Коммит
3490067316
|
@ -1 +1 @@
|
|||
7.2.1
|
||||
5f5d70b6c4d2fb1a889479569107f1692239e8a7
|
||||
|
|
|
@ -24,5 +24,5 @@ jobs:
|
|||
extra_args: >
|
||||
buildifier --all-files 2>&1 ||
|
||||
(
|
||||
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
|
||||
echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel/buildifier"; exit 1
|
||||
)
|
||||
|
|
|
@ -37,7 +37,7 @@ jobs:
|
|||
with:
|
||||
languages: cpp
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
|
||||
|
||||
- name: "[Ubuntu] Remove GCC 13 from runner image"
|
||||
shell: bash
|
||||
run: |
|
||||
|
@ -48,7 +48,7 @@ jobs:
|
|||
- name: "Build Swift extractor using Bazel"
|
||||
run: |
|
||||
bazel clean --expunge
|
||||
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local --features=-layering_check
|
||||
bazel run //swift:create-extractor-pack --nouse_action_cache --noremote_accept_cached --noremote_upload_local_results --spawn_strategy=local
|
||||
bazel shutdown
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
.cache
|
||||
|
||||
# qltest projects and artifacts
|
||||
*.actual
|
||||
*/ql/test/**/*.testproj
|
||||
*/ql/test/**/*.actual
|
||||
*/ql/test/**/go.sum
|
||||
|
||||
# Visual studio temporaries, except a file used by QL4VS
|
||||
|
|
|
@ -26,7 +26,7 @@ repos:
|
|||
name: Format bazel files
|
||||
files: \.(bazel|bzl)
|
||||
language: system
|
||||
entry: bazel run //misc/bazel:buildifier
|
||||
entry: bazel run //misc/bazel/buildifier
|
||||
pass_filenames: false
|
||||
|
||||
# DISABLED: can be enabled by copying this config and installing `pre-commit` with `--config` on the copy
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Location extends @location_expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
predicate isExprWithNewBuiltin(Expr expr) {
|
||||
exists(int kind | exprs(expr, kind, _) | 385 <= kind and kind <= 388)
|
||||
}
|
||||
|
||||
from Expr expr, int kind, int kind_new, Location location
|
||||
where
|
||||
exprs(expr, kind, location) and
|
||||
if isExprWithNewBuiltin(expr) then kind_new = 1 else kind_new = kind
|
||||
select expr, kind_new, location
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,14 @@
|
|||
class Expr extends @expr {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Type extends @type {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Expr expr, Type type, int kind
|
||||
where
|
||||
sizeof_bind(expr, type) and
|
||||
exprs(expr, kind, _) and
|
||||
(kind = 93 or kind = 94)
|
||||
select expr, type
|
|
@ -0,0 +1,4 @@
|
|||
description: Add new builtin operations
|
||||
compatibility: partial
|
||||
exprs.rel: run exprs.qlo
|
||||
sizeof_bind.rel: run sizeof_bind.qlo
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
category: feature
|
||||
---
|
||||
* Added subclasses of `BuiltInOperations` for the `__is_scoped_enum`, `__is_trivially_equality_comparable`, and `__is_trivially_relocatable` builtin operations.
|
||||
* Added a subclass of `Expr` for `__datasizeof` expressions.
|
|
@ -1885,3 +1885,59 @@ class BuiltInOperationIsWinInterface extends BuiltInOperation, @iswininterface {
|
|||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsWinInterface" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_trivially_equality_comparable` built-in operation.
|
||||
*
|
||||
* Returns `true` if comparing two objects of type `_Tp` is equivalent to
|
||||
* comparing their object representations.
|
||||
*
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct is_trivially_equality_comparable
|
||||
* : public integral_constant<bool, __is_trivially_equality_comparable(_Tp)>
|
||||
* {};
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsTriviallyEqualityComparable extends BuiltInOperation,
|
||||
@istriviallyequalitycomparable
|
||||
{
|
||||
override string toString() { result = "__is_trivially_equality_comparable" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyEqualityComparable" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_scoped_enum` built-in operation (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* Returns `true` if a type is a scoped enum.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* constexpr bool is_scoped_enum = __is_scoped_enum(_Tp);
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsScopedEnum extends BuiltInOperation, @isscopedenum {
|
||||
override string toString() { result = "__is_scoped_enum" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsScopedEnum" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__is_trivially_relocatable` built-in operation.
|
||||
*
|
||||
* Returns `true` if moving an object of type `_Tp` is equivalent to
|
||||
* copying the underlying bytes.
|
||||
*
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct is_trivially_relocatable
|
||||
* : public integral_constant<bool, __is_trivially_relocatable(_Tp)>
|
||||
* {};
|
||||
* ```
|
||||
*/
|
||||
class BuiltInOperationIsTriviallyRelocatable extends BuiltInOperation, @istriviallyrelocatable {
|
||||
override string toString() { result = "__is_trivially_relocatable" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyRelocatable" }
|
||||
}
|
||||
|
|
|
@ -791,6 +791,53 @@ class AlignofTypeOperator extends AlignofOperator {
|
|||
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__datasizeof` expression (used by some implementations
|
||||
* of the `<type_traits>` header).
|
||||
*
|
||||
* The `__datasizeof` expression behaves identically to `sizeof` except
|
||||
* that the result ignores tail padding.
|
||||
*/
|
||||
class DatasizeofOperator extends Expr, @datasizeof {
|
||||
override int getPrecedence() { result = 16 }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__datasizeof` expression whose operand is an expression.
|
||||
*/
|
||||
class DatasizeofExprOperator extends DatasizeofOperator {
|
||||
DatasizeofExprOperator() { exists(this.getChild(0)) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DatasizeofExprOperator" }
|
||||
|
||||
/** Gets the contained expression. */
|
||||
Expr getExprOperand() { result = this.getChild(0) }
|
||||
|
||||
override string toString() { result = "__datasizeof(<expr>)" }
|
||||
|
||||
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
|
||||
|
||||
override predicate mayBeGloballyImpure() { this.getExprOperand().mayBeGloballyImpure() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++ `__datasizeof` expression whose operand is a type name.
|
||||
*/
|
||||
class DatasizeofTypeOperator extends DatasizeofOperator {
|
||||
DatasizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "DatasizeofTypeOperator" }
|
||||
|
||||
/** Gets the contained type. */
|
||||
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
override string toString() { result = "__datasizeof(" + this.getTypeOperand().getName() + ")" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
override predicate mayBeGloballyImpure() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ array to pointer conversion.
|
||||
*
|
||||
|
|
|
@ -304,6 +304,8 @@ class Expr extends StmtParent, @expr {
|
|||
e instanceof NoExceptExpr
|
||||
or
|
||||
e instanceof AlignofOperator
|
||||
or
|
||||
e instanceof DatasizeofOperator
|
||||
)
|
||||
or
|
||||
exists(Decltype d | d.getExpr() = this.getParentWithConversions*())
|
||||
|
|
|
@ -42,6 +42,7 @@ private import implementations.Accept
|
|||
private import implementations.Poll
|
||||
private import implementations.Select
|
||||
private import implementations.MySql
|
||||
private import implementations.NoexceptFunction
|
||||
private import implementations.ODBC
|
||||
private import implementations.SqLite3
|
||||
private import implementations.PostgreSql
|
||||
|
|
|
@ -9,13 +9,14 @@ import semmle.code.cpp.models.interfaces.DataFlow
|
|||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
/**
|
||||
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
|
||||
* `__builtin___memcpy_chk`.
|
||||
*/
|
||||
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
|
||||
AliasFunction
|
||||
AliasFunction, NonThrowingFunction
|
||||
{
|
||||
MemcpyFunction() {
|
||||
// memcpy(dest, src, num)
|
||||
|
|
|
@ -8,9 +8,10 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
|
|||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
|
||||
SideEffectFunction
|
||||
SideEffectFunction, NonThrowingFunction
|
||||
{
|
||||
MemsetFunctionModel() {
|
||||
this.hasGlobalOrStdOrBslName("memset")
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
/**
|
||||
* A function that is annotated with a `noexcept` specifier (or the equivalent
|
||||
* `throw()` specifier) guaranteeing that the function can not throw exceptions.
|
||||
*
|
||||
* Note: The `throw` specifier was deprecated in C++11 and removed in C++17.
|
||||
*/
|
||||
class NoexceptFunction extends NonThrowingFunction {
|
||||
NoexceptFunction() { this.isNoExcept() or this.isNoThrow() }
|
||||
}
|
|
@ -8,11 +8,12 @@
|
|||
import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
/**
|
||||
* The standard functions `printf`, `wprintf` and their glib variants.
|
||||
*/
|
||||
private class Printf extends FormattingFunction, AliasFunction {
|
||||
private class Printf extends FormattingFunction, AliasFunction, NonThrowingFunction {
|
||||
Printf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
|
@ -36,7 +37,7 @@ private class Printf extends FormattingFunction, AliasFunction {
|
|||
/**
|
||||
* The standard functions `fprintf`, `fwprintf` and their glib variants.
|
||||
*/
|
||||
private class Fprintf extends FormattingFunction {
|
||||
private class Fprintf extends FormattingFunction, NonThrowingFunction {
|
||||
Fprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
|
@ -54,7 +55,7 @@ private class Fprintf extends FormattingFunction {
|
|||
/**
|
||||
* The standard function `sprintf` and its Microsoft and glib variants.
|
||||
*/
|
||||
private class Sprintf extends FormattingFunction {
|
||||
private class Sprintf extends FormattingFunction, NonThrowingFunction {
|
||||
Sprintf() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
|
@ -97,7 +98,7 @@ private class Sprintf extends FormattingFunction {
|
|||
/**
|
||||
* Implements `Snprintf`.
|
||||
*/
|
||||
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction {
|
||||
private class SnprintfImpl extends Snprintf, AliasFunction, SideEffectFunction, NonThrowingFunction {
|
||||
SnprintfImpl() {
|
||||
this instanceof TopLevelFunction and
|
||||
(
|
||||
|
@ -204,7 +205,7 @@ private class StringCchPrintf extends FormattingFunction {
|
|||
/**
|
||||
* The standard function `syslog`.
|
||||
*/
|
||||
private class Syslog extends FormattingFunction {
|
||||
private class Syslog extends FormattingFunction, NonThrowingFunction {
|
||||
Syslog() {
|
||||
this instanceof TopLevelFunction and
|
||||
this.hasGlobalName("syslog") and
|
||||
|
|
|
@ -7,13 +7,16 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
|
|||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
/**
|
||||
* The standard function `strcat` and its wide, sized, and Microsoft variants.
|
||||
*
|
||||
* Does not include `strlcat`, which is covered by `StrlcatFunction`
|
||||
*/
|
||||
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
|
||||
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction,
|
||||
NonThrowingFunction
|
||||
{
|
||||
StrcatFunction() {
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"strcat", // strcat(dst, src)
|
||||
|
|
|
@ -7,11 +7,14 @@ import semmle.code.cpp.models.interfaces.ArrayFunction
|
|||
import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
import semmle.code.cpp.models.interfaces.NonThrowing
|
||||
|
||||
/**
|
||||
* The standard function `strcpy` and its wide, sized, and Microsoft variants.
|
||||
*/
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
|
||||
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction,
|
||||
NonThrowingFunction
|
||||
{
|
||||
StrcpyFunction() {
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
"strcpy", // strcpy(dst, src)
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Provides an abstract class for modeling functions that never throw.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Function
|
||||
import semmle.code.cpp.models.Models
|
||||
|
||||
/**
|
||||
* A function that is guaranteed to never throw.
|
||||
*/
|
||||
abstract class NonThrowingFunction extends Function { }
|
|
@ -1788,6 +1788,10 @@ case @expr.kind of
|
|||
| 382 = @isvalidwinrttype
|
||||
| 383 = @iswinclass
|
||||
| 384 = @iswininterface
|
||||
| 385 = @istriviallyequalitycomparable
|
||||
| 386 = @isscopedenum
|
||||
| 387 = @istriviallyrelocatable
|
||||
| 388 = @datasizeof
|
||||
;
|
||||
|
||||
@var_args_expr = @vastartexpr
|
||||
|
@ -1901,6 +1905,9 @@ case @expr.kind of
|
|||
| @isvalidwinrttype
|
||||
| @iswinclass
|
||||
| @iswininterface
|
||||
| @istriviallyequalitycomparable
|
||||
| @isscopedenum
|
||||
| @istriviallyrelocatable
|
||||
;
|
||||
|
||||
new_allocated_type(
|
||||
|
@ -1961,7 +1968,7 @@ uuidof_bind(
|
|||
int type_id: @type ref
|
||||
);
|
||||
|
||||
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof;
|
||||
@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof | @datasizeof;
|
||||
|
||||
sizeof_bind(
|
||||
unique int expr: @runtime_sizeof_or_alignof ref,
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,2 @@
|
|||
description: Add new builtin operations
|
||||
compatibility: backwards
|
|
@ -16,6 +16,7 @@
|
|||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.models.implementations.NoexceptFunction
|
||||
|
||||
/** Gets the `Constructor` invoked when `newExpr` allocates memory. */
|
||||
Constructor getConstructorForAllocation(NewOrNewArrayExpr newExpr) {
|
||||
|
@ -44,9 +45,8 @@ predicate deleteMayThrow(DeleteOrDeleteArrayExpr deleteExpr) {
|
|||
* like it might throw an exception, and the function does not have a `noexcept` or `throw()` specifier.
|
||||
*/
|
||||
predicate functionMayThrow(Function f) {
|
||||
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock())) and
|
||||
not f.isNoExcept() and
|
||||
not f.isNoThrow()
|
||||
not f instanceof NonThrowingFunction and
|
||||
(not exists(f.getBlock()) or stmtMayThrow(f.getBlock()))
|
||||
}
|
||||
|
||||
/** Holds if the evaluation of `stmt` may throw an exception. */
|
||||
|
@ -172,8 +172,7 @@ class ThrowingAllocator extends Function {
|
|||
not exists(Parameter p | p = this.getAParameter() |
|
||||
p.getUnspecifiedType().stripType() instanceof NoThrowType
|
||||
) and
|
||||
not this.isNoExcept() and
|
||||
not this.isNoThrow()
|
||||
not this instanceof NoexceptFunction
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* 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,4 +1,4 @@
|
|||
// semmle-extractor-options: --clang --clang_version 180000
|
||||
// semmle-extractor-options: --clang --edg --clang_version --edg 190000
|
||||
|
||||
struct S {
|
||||
void f() {}
|
||||
|
@ -108,3 +108,16 @@ bool b_is_unbounded_array2 = __is_unbounded_array(int[42]);
|
|||
|
||||
bool b_is_referenceable1 = __is_referenceable(int);
|
||||
bool b_is_referenceable2 = __is_referenceable(void);
|
||||
|
||||
bool b_is_trivially_equality_comparable1 = __is_trivially_equality_comparable(int);
|
||||
bool b_is_trivially_equality_comparable2 = __is_trivially_equality_comparable(void);
|
||||
|
||||
enum class E {
|
||||
a, b
|
||||
};
|
||||
|
||||
bool b_is_scoped_enum1 = __is_scoped_enum(E);
|
||||
bool b_is_scoped_enum2 = __is_scoped_enum(int);
|
||||
|
||||
bool b_is_trivially_relocatable1 = __is_trivially_relocatable(int);
|
||||
bool b_is_trivially_relocatable2 = __is_trivially_relocatable(void);
|
||||
|
|
|
@ -153,7 +153,21 @@
|
|||
| clang.cpp:109:28:109:50 | int | | <none> |
|
||||
| clang.cpp:110:28:110:51 | __is_referenceable | void | 0 |
|
||||
| clang.cpp:110:28:110:51 | void | | <none> |
|
||||
| clang.cpp:112:44:112:82 | __is_trivially_equality_comparable | int | 1 |
|
||||
| clang.cpp:112:44:112:82 | int | | <none> |
|
||||
| clang.cpp:113:44:113:83 | __is_trivially_equality_comparable | void | 0 |
|
||||
| clang.cpp:113:44:113:83 | void | | <none> |
|
||||
| clang.cpp:119:26:119:44 | E | | <none> |
|
||||
| clang.cpp:119:26:119:44 | __is_scoped_enum | E | 1 |
|
||||
| clang.cpp:120:26:120:46 | __is_scoped_enum | int | 0 |
|
||||
| clang.cpp:120:26:120:46 | int | | <none> |
|
||||
| clang.cpp:122:36:122:66 | __is_trivially_relocatable | int | 1 |
|
||||
| clang.cpp:122:36:122:66 | int | | <none> |
|
||||
| clang.cpp:123:36:123:67 | __is_trivially_relocatable | void | 0 |
|
||||
| clang.cpp:123:36:123:67 | void | | <none> |
|
||||
| file://:0:0:0:0 | 0 | | 0 |
|
||||
| file://:0:0:0:0 | 0 | | 0 |
|
||||
| file://:0:0:0:0 | 1 | | 1 |
|
||||
| file://:0:0:0:0 | 1 | | 1 |
|
||||
| file://:0:0:0:0 | 2 | | 2 |
|
||||
| gcc.cpp:3:25:3:25 | 8 | | 8 |
|
||||
|
|
|
@ -848,6 +848,8 @@ edges
|
|||
| simple.cpp:120:8:120:8 | *a [i] | simple.cpp:120:10:120:10 | i | provenance | |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | *ab [a] | provenance | |
|
||||
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||
| struct_init.c:15:8:15:9 | *ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||
| struct_init.c:20:13:20:14 | *definition of ab [a] | struct_init.c:22:8:22:9 | *ab [a] | provenance | |
|
||||
| struct_init.c:20:13:20:14 | *definition of ab [a] | struct_init.c:24:10:24:12 | *& ... [a] | provenance | |
|
||||
|
@ -1758,6 +1760,8 @@ nodes
|
|||
| simple.cpp:120:10:120:10 | i | semmle.label | i |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:15:8:15:9 | *ab [a] | semmle.label | *ab [a] |
|
||||
| struct_init.c:15:12:15:12 | a | semmle.label | a |
|
||||
| struct_init.c:20:13:20:14 | *definition of ab [a] | semmle.label | *definition of ab [a] |
|
||||
|
|
|
@ -737,6 +737,8 @@ edges
|
|||
| simple.cpp:120:8:120:8 | a [i] | simple.cpp:120:10:120:10 | i | provenance | |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | provenance | |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [a] | provenance | |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | struct_init.c:15:12:15:12 | a | provenance | |
|
||||
| struct_init.c:15:8:15:9 | ab [post update] [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
|
||||
|
@ -1549,6 +1551,8 @@ nodes
|
|||
| simple.cpp:120:10:120:10 | i | semmle.label | i |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:15:8:15:9 | ab [a] | semmle.label | ab [a] |
|
||||
| struct_init.c:15:8:15:9 | ab [post update] [a] | semmle.label | ab [post update] [a] |
|
||||
| struct_init.c:15:12:15:12 | a | semmle.label | a |
|
||||
|
|
|
@ -450,7 +450,7 @@ void test_qualifiers()
|
|||
b.member = source();
|
||||
sink(b); // $ ir MISSING: ast
|
||||
sink(b.member); // $ ast,ir
|
||||
sink(b.getMember()); // $ ir MISSING: ast
|
||||
sink(b.getMember()); // $ MISSING: ir ast
|
||||
|
||||
c = new MyClass2(0);
|
||||
|
||||
|
|
|
@ -115,8 +115,8 @@ void test_vector_swap() {
|
|||
v3.swap(v4);
|
||||
|
||||
sink(v1);
|
||||
sink(v2); // $ ir MISSING:ast
|
||||
sink(v3); // $ ir MISSING:ast
|
||||
sink(v2); // $ MISSING:ir ast
|
||||
sink(v3); // $ MISSING:ir ast
|
||||
sink(v4);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// semmle-extractor-options: --clang --edg --clang_version --edg 190000
|
||||
|
||||
typedef unsigned int size_t;
|
||||
|
||||
class MyClass
|
||||
{
|
||||
public:
|
||||
int x;
|
||||
int *ptr;
|
||||
char c;
|
||||
};
|
||||
|
||||
void func() {
|
||||
int i;
|
||||
char c;
|
||||
int * ptr;
|
||||
MyClass mc;
|
||||
int arr[10];
|
||||
|
||||
size_t sz1 = __datasizeof(int);
|
||||
size_t sz2 = __datasizeof(char);
|
||||
size_t sz3 = __datasizeof(int *);
|
||||
size_t sz4 = __datasizeof(MyClass);
|
||||
size_t sz5 = __datasizeof(i);
|
||||
size_t sz6 = __datasizeof(c);
|
||||
size_t sz7 = __datasizeof(ptr);
|
||||
size_t sz8 = __datasizeof(mc);
|
||||
size_t sz9 = __datasizeof(arr);
|
||||
size_t sz10 = __datasizeof(arr[4]);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
| datasizeof.cpp:20:15:20:31 | __datasizeof(int) | 4 | DatasizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int |
|
||||
| datasizeof.cpp:21:15:21:32 | __datasizeof(char) | 1 | DatasizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char |
|
||||
| datasizeof.cpp:22:15:22:33 | __datasizeof(int *) | 8 | DatasizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * |
|
||||
| datasizeof.cpp:23:15:23:35 | __datasizeof(MyClass) | 24 | DatasizeofTypeOperator.getTypeOperand() | datasizeof.cpp:5:7:5:13 | MyClass |
|
||||
| datasizeof.cpp:24:15:24:29 | __datasizeof(<expr>) | 4 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:24:28:24:28 | i |
|
||||
| datasizeof.cpp:25:15:25:29 | __datasizeof(<expr>) | 1 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:25:28:25:28 | c |
|
||||
| datasizeof.cpp:26:15:26:31 | __datasizeof(<expr>) | 8 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:26:28:26:30 | ptr |
|
||||
| datasizeof.cpp:27:15:27:30 | __datasizeof(<expr>) | 24 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:27:28:27:29 | mc |
|
||||
| datasizeof.cpp:28:15:28:31 | __datasizeof(<expr>) | 40 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:28:28:28:30 | arr |
|
||||
| datasizeof.cpp:29:16:29:35 | __datasizeof(<expr>) | 4 | DatasizeofExprOperator.getExprOperand() | datasizeof.cpp:29:29:29:34 | access to array |
|
|
@ -0,0 +1,10 @@
|
|||
import cpp
|
||||
|
||||
from DatasizeofOperator sto, string elemDesc, Element e
|
||||
where
|
||||
elemDesc = "DatasizeofTypeOperator.getTypeOperand()" and
|
||||
e = sto.(DatasizeofTypeOperator).getTypeOperand()
|
||||
or
|
||||
elemDesc = "DatasizeofExprOperator.getExprOperand()" and
|
||||
e = sto.(DatasizeofExprOperator).getExprOperand()
|
||||
select sto, sto.getValue(), elemDesc, e
|
|
@ -1,10 +1,10 @@
|
|||
| sizeof.cpp:19:15:19:25 | sizeof(int) | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int |
|
||||
| sizeof.cpp:20:15:20:26 | sizeof(char) | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char |
|
||||
| sizeof.cpp:21:15:21:27 | sizeof(int *) | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * |
|
||||
| sizeof.cpp:22:15:22:29 | sizeof(MyClass) | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass |
|
||||
| sizeof.cpp:23:15:23:23 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:23:22:23:22 | i |
|
||||
| sizeof.cpp:24:15:24:23 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:24:22:24:22 | c |
|
||||
| sizeof.cpp:25:15:25:25 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:25:22:25:24 | ptr |
|
||||
| sizeof.cpp:26:15:26:24 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:26:22:26:23 | mc |
|
||||
| sizeof.cpp:27:15:27:25 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:27:22:27:24 | arr |
|
||||
| sizeof.cpp:28:16:28:29 | sizeof(<expr>) | SizeofExprOperator.getExprOperand() | sizeof.cpp:28:23:28:28 | access to array |
|
||||
| sizeof.cpp:19:15:19:25 | sizeof(int) | 4 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int |
|
||||
| sizeof.cpp:20:15:20:26 | sizeof(char) | 1 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | char |
|
||||
| sizeof.cpp:21:15:21:27 | sizeof(int *) | 8 | SizeofTypeOperator.getTypeOperand() | file://:0:0:0:0 | int * |
|
||||
| sizeof.cpp:22:15:22:29 | sizeof(MyClass) | 16 | SizeofTypeOperator.getTypeOperand() | sizeof.cpp:4:7:4:13 | MyClass |
|
||||
| sizeof.cpp:23:15:23:23 | sizeof(<expr>) | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:23:22:23:22 | i |
|
||||
| sizeof.cpp:24:15:24:23 | sizeof(<expr>) | 1 | SizeofExprOperator.getExprOperand() | sizeof.cpp:24:22:24:22 | c |
|
||||
| sizeof.cpp:25:15:25:25 | sizeof(<expr>) | 8 | SizeofExprOperator.getExprOperand() | sizeof.cpp:25:22:25:24 | ptr |
|
||||
| sizeof.cpp:26:15:26:24 | sizeof(<expr>) | 16 | SizeofExprOperator.getExprOperand() | sizeof.cpp:26:22:26:23 | mc |
|
||||
| sizeof.cpp:27:15:27:25 | sizeof(<expr>) | 40 | SizeofExprOperator.getExprOperand() | sizeof.cpp:27:22:27:24 | arr |
|
||||
| sizeof.cpp:28:16:28:29 | sizeof(<expr>) | 4 | SizeofExprOperator.getExprOperand() | sizeof.cpp:28:23:28:28 | access to array |
|
||||
|
|
|
@ -7,4 +7,4 @@ where
|
|||
or
|
||||
elemDesc = "SizeofExprOperator.getExprOperand()" and
|
||||
e = sto.(SizeofExprOperator).getExprOperand()
|
||||
select sto, elemDesc, e
|
||||
select sto, sto.getValue(), elemDesc, e
|
||||
|
|
|
@ -16,7 +16,6 @@ edges
|
|||
| test_free.cpp:152:27:152:27 | pointer to free output argument | test_free.cpp:153:5:153:5 | a | provenance | |
|
||||
| test_free.cpp:233:14:233:15 | pointer to free output argument | test_free.cpp:234:9:234:11 | *... ++ | provenance | |
|
||||
| test_free.cpp:234:9:234:11 | *... ++ | test_free.cpp:236:9:236:10 | * ... | provenance | |
|
||||
| test_free.cpp:238:15:238:17 | *... ++ | test_free.cpp:238:15:238:17 | *... ++ | provenance | |
|
||||
| test_free.cpp:238:15:238:17 | *... ++ | test_free.cpp:241:9:241:10 | * ... | provenance | |
|
||||
| test_free.cpp:239:14:239:15 | pointer to free output argument | test_free.cpp:238:15:238:17 | *... ++ | provenance | |
|
||||
| test_free.cpp:245:10:245:11 | pointer to free output argument | test_free.cpp:246:9:246:10 | * ... | provenance | |
|
||||
|
|
|
@ -22,11 +22,9 @@ edges
|
|||
| test.c:41:5:41:24 | ... = ... | test.c:44:7:44:10 | len2 | provenance | |
|
||||
| test.c:41:5:41:24 | ... = ... | test.c:44:7:44:12 | ... -- | provenance | |
|
||||
| test.c:44:7:44:12 | ... -- | test.c:44:7:44:10 | len2 | provenance | |
|
||||
| test.c:44:7:44:12 | ... -- | test.c:44:7:44:12 | ... -- | provenance | |
|
||||
| test.c:51:5:51:24 | ... = ... | test.c:54:7:54:10 | len3 | provenance | |
|
||||
| test.c:51:5:51:24 | ... = ... | test.c:54:7:54:12 | ... -- | provenance | |
|
||||
| test.c:54:7:54:12 | ... -- | test.c:54:7:54:10 | len3 | provenance | |
|
||||
| test.c:54:7:54:12 | ... -- | test.c:54:7:54:12 | ... -- | provenance | |
|
||||
nodes
|
||||
| test2.cpp:12:21:12:21 | v | semmle.label | v |
|
||||
| test2.cpp:14:11:14:11 | v | semmle.label | v |
|
||||
|
|
|
@ -17,3 +17,4 @@
|
|||
| test.cpp:229:15:229:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:231:16:231:19 | { ... } | This catch block |
|
||||
| test.cpp:242:14:242:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:243:34:243:36 | { ... } | This catch block |
|
||||
| test.cpp:276:17:276:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:277:8:277:12 | ! ... | This check |
|
||||
| test.cpp:288:19:288:47 | new[] | This allocation cannot throw. $@ is unnecessary. | test.cpp:291:30:293:5 | { ... } | This catch block |
|
||||
|
|
|
@ -282,7 +282,7 @@ namespace qhelp {
|
|||
}
|
||||
|
||||
// BAD: the allocation won't throw an exception, but
|
||||
// instead return a null pointer. [NOT DETECTED]
|
||||
// instead return a null pointer.
|
||||
void bad2(std::size_t length) noexcept {
|
||||
try {
|
||||
int* dest = new(std::nothrow) int[length];
|
||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Concurrent;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Semmle.Extraction.Entities;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
|
@ -89,13 +90,21 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||
trapFile.compilation_finished(this, (float)p.Total.Cpu.TotalSeconds, (float)p.Total.Elapsed.TotalSeconds);
|
||||
}
|
||||
|
||||
public void PopulateAggregatedMessages()
|
||||
{
|
||||
ExtractionMessage.groupedMessageCounts.ForEach(pair =>
|
||||
{
|
||||
Context.TrapWriter.Writer.compilation_info(this, $"Extractor message count for group '{pair.Key}'", pair.Value.ToString());
|
||||
});
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.Write(hashCode);
|
||||
trapFile.Write(";compilation");
|
||||
}
|
||||
|
||||
public override Location ReportingLocation => throw new NotImplementedException();
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
|
||||
|
||||
public override bool NeedsPopulation => Context.IsAssemblyScope;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
|||
public override Microsoft.CodeAnalysis.Location ReportingLocation =>
|
||||
IsCompilerGeneratedDelegate()
|
||||
? Symbol.ContainingType.GetSymbolLocation()
|
||||
: Symbol.GetSymbolLocation();
|
||||
: BodyDeclaringSymbol.GetSymbolLocation();
|
||||
|
||||
public override bool NeedsPopulation => base.NeedsPopulation || IsCompilerGeneratedDelegate();
|
||||
|
||||
|
|
|
@ -250,6 +250,8 @@ namespace Semmle.Extraction.CSharp
|
|||
|
||||
public void LogPerformance(Entities.PerformanceMetrics p) => compilationEntity.PopulatePerformance(p);
|
||||
|
||||
public void ExtractAggregatedMessages() => compilationEntity.PopulateAggregatedMessages();
|
||||
|
||||
#nullable restore warnings
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -458,6 +458,7 @@ namespace Semmle.Extraction.CSharp
|
|||
|
||||
sw.Restart();
|
||||
analyser.PerformExtraction(options.Threads);
|
||||
analyser.ExtractAggregatedMessages();
|
||||
sw.Stop();
|
||||
var cpuTime2 = currentProcess.TotalProcessorTime;
|
||||
var userTime2 = currentProcess.UserProcessorTime;
|
||||
|
|
|
@ -26,6 +26,7 @@ codeql_csharp_library(
|
|||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
internals_visible_to = ["Semmle.Extraction.CSharp"],
|
||||
visibility = ["//csharp:__subpackages__"],
|
||||
deps = [
|
||||
"//csharp/extractor/Semmle.Util",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.IO;
|
||||
using System.Collections.Concurrent;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using Semmle.Util;
|
||||
|
||||
|
@ -7,6 +8,8 @@ namespace Semmle.Extraction.Entities
|
|||
internal class ExtractionMessage : FreshEntity
|
||||
{
|
||||
private static readonly int limit = EnvironmentVariables.TryGetExtractorNumberOption<int>("MESSAGE_LIMIT") ?? 10000;
|
||||
|
||||
internal static readonly ConcurrentDictionary<string, int> groupedMessageCounts = [];
|
||||
private static int messageCount = 0;
|
||||
|
||||
private readonly Message msg;
|
||||
|
@ -25,6 +28,10 @@ namespace Semmle.Extraction.Entities
|
|||
|
||||
protected override void Populate(TextWriter trapFile)
|
||||
{
|
||||
// For the time being we're counting the number of messages per severity, we could introduce other groupings in the future
|
||||
var key = msg.Severity.ToString();
|
||||
groupedMessageCounts.AddOrUpdate(key, 1, (_, c) => c + 1);
|
||||
|
||||
if (!bypassLimit)
|
||||
{
|
||||
var val = Interlocked.Increment(ref messageCount);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
|
||||
<InternalsVisibleTo Include="Semmle.Extraction.CSharp" />
|
||||
</ItemGroup>
|
||||
<Import Project="..\..\.paket\Paket.Restore.targets" />
|
||||
</Project>
|
||||
|
|
|
@ -7,3 +7,5 @@ extractorMessagesLeachedLimit
|
|||
compilationInfo
|
||||
| Compiler diagnostic count for CS0103 | 3.0 |
|
||||
| Compiler diagnostic count for CS8019 | 7.0 |
|
||||
| Extractor message count for group 'Error' | 8.0 |
|
||||
| Extractor message count for group 'Warning' | 1.0 |
|
||||
|
|
|
@ -11,7 +11,8 @@ query predicate extractorMessagesLeachedLimit(ExtractorMessage msg) {
|
|||
|
||||
query predicate compilationInfo(string key, float value) {
|
||||
exists(Compilation c, string infoValue |
|
||||
infoValue = c.getInfo(key) and key.matches("Compiler diagnostic count for%")
|
||||
infoValue = c.getInfo(key) and
|
||||
key.matches(["Compiler diagnostic count for%", "Extractor message count for group%"])
|
||||
|
|
||||
value = infoValue.toFloat()
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@ import semmle.code.csharp.commons.Diagnostics
|
|||
query predicate compilationInfo(string key, float value) {
|
||||
key != "Resolved references" and
|
||||
key != "Resolved assembly conflicts" and
|
||||
not key.matches("Compiler diagnostic count for%") and
|
||||
not key.matches(["Compiler diagnostic count for%", "Extractor message count for group%"]) and
|
||||
exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) |
|
||||
key = infoKey and
|
||||
value = infoValue.toFloat()
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Parameters of public methods in abstract controller-like classes are now considered remote flow sources.
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The reported location of `partial` methods has been changed from the definition to the implementation part.
|
|
@ -1,504 +1,4 @@
|
|||
/**
|
||||
* Provides classes for performing global (inter-procedural)
|
||||
* content-sensitive data flow analyses.
|
||||
*
|
||||
* Unlike `DataFlow::Global`, we allow for data to be stored (possibly nested) inside
|
||||
* contents of sources and sinks.
|
||||
* We track flow paths of the form
|
||||
*
|
||||
* ```
|
||||
* source --value-->* node
|
||||
* (--read--> node --value-->* node)*
|
||||
* --(non-value|value)-->* node
|
||||
* (--store--> node --value-->* node)*
|
||||
* --value-->* sink
|
||||
* ```
|
||||
*
|
||||
* where `--value-->` is a value-preserving flow step, `--read-->` is a read
|
||||
* step, `--store-->` is a store step, and `--(non-value)-->` is a
|
||||
* non-value-preserving flow step.
|
||||
*
|
||||
* That is, first a sequence of 0 or more reads, followed by 0 or more additional
|
||||
* steps, followed by 0 or more stores, with value-preserving steps allowed in
|
||||
* between all other steps.
|
||||
*/
|
||||
|
||||
private import csharp
|
||||
private import codeql.util.Boolean
|
||||
private import DataFlowImplCommon
|
||||
private import DataFlowImplSpecific::Private
|
||||
private import DataFlowImplSpecific::Private as DataFlowPrivate
|
||||
|
||||
/**
|
||||
* An input configuration for content data flow.
|
||||
*/
|
||||
signature module ConfigSig {
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
predicate isSource(DataFlow::Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps.
|
||||
*/
|
||||
default predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
/** Holds if data flow into `node` is prohibited. */
|
||||
default predicate isBarrier(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Gets a data flow configuration feature to add restrictions to the set of
|
||||
* valid flow paths.
|
||||
*
|
||||
* - `FeatureHasSourceCallContext`:
|
||||
* Assume that sources have some existing call context to disallow
|
||||
* conflicting return-flow directly following the source.
|
||||
* - `FeatureHasSinkCallContext`:
|
||||
* Assume that sinks have some existing call context to disallow
|
||||
* conflicting argument-to-parameter flow directly preceding the sink.
|
||||
* - `FeatureEqualSourceSinkCallContext`:
|
||||
* Implies both of the above and additionally ensures that the entire flow
|
||||
* path preserves the call context.
|
||||
*/
|
||||
default DataFlow::FlowFeature getAFeature() { none() }
|
||||
|
||||
/** Gets a limit on the number of reads out of sources and number of stores into sinks. */
|
||||
default int accessPathLimit() { result = DataFlowPrivate::accessPathLimit() }
|
||||
|
||||
/** Holds if `c` is relevant for reads out of sources or stores into sinks. */
|
||||
default predicate isRelevantContent(DataFlow::ContentSet c) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a global content data flow computation.
|
||||
*/
|
||||
module Global<ConfigSig ContentConfig> {
|
||||
private module FlowConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState = State;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
ContentConfig::isSource(source) and
|
||||
state.(InitState).decode(true)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
ContentConfig::isSink(sink) and
|
||||
(
|
||||
state instanceof InitState or
|
||||
state instanceof StoreState or
|
||||
state instanceof ReadState
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
storeStep(node1, state1, _, node2, state2) or
|
||||
readStep(node1, state1, _, node2, state2) or
|
||||
additionalStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep = ContentConfig::isAdditionalFlowStep/2;
|
||||
|
||||
predicate isBarrier = ContentConfig::isBarrier/1;
|
||||
|
||||
DataFlow::FlowFeature getAFeature() { result = ContentConfig::getAFeature() }
|
||||
|
||||
predicate accessPathLimit = ContentConfig::accessPathLimit/0;
|
||||
|
||||
// needed to record reads/stores inside summarized callables
|
||||
predicate includeHiddenNodes() { any() }
|
||||
}
|
||||
|
||||
private module Flow = DataFlow::GlobalWithState<FlowConfig>;
|
||||
|
||||
/**
|
||||
* Holds if data stored inside `sourceAp` on `source` flows to `sinkAp` inside `sink`
|
||||
* for this configuration. `preservesValue` indicates whether any of the additional
|
||||
* flow steps defined by `isAdditionalFlowStep` are needed.
|
||||
*
|
||||
* For the source access path, `sourceAp`, the top of the stack represents the content
|
||||
* that was last read from. That is, if `sourceAp` is `Field1.Field2` (with `Field1`
|
||||
* being the top of the stack), then there is flow from `source.Field2.Field1`.
|
||||
*
|
||||
* For the sink access path, `sinkAp`, the top of the stack represents the content
|
||||
* that was last stored into. That is, if `sinkAp` is `Field1.Field2` (with `Field1`
|
||||
* being the top of the stack), then there is flow into `sink.Field1.Field2`.
|
||||
*/
|
||||
predicate flow(
|
||||
DataFlow::Node source, AccessPath sourceAp, DataFlow::Node sink, AccessPath sinkAp,
|
||||
boolean preservesValue
|
||||
) {
|
||||
exists(Flow::PathNode pathSource, Flow::PathNode pathSink |
|
||||
Flow::flowPath(pathSource, pathSink) and
|
||||
nodeReaches(pathSource, TAccessPathNil(), TAccessPathNil(), pathSink, sourceAp, sinkAp) and
|
||||
source = pathSource.getNode() and
|
||||
sink = pathSink.getNode()
|
||||
|
|
||||
pathSink.getState().(InitState).decode(preservesValue)
|
||||
or
|
||||
pathSink.getState().(ReadState).decode(_, preservesValue)
|
||||
or
|
||||
pathSink.getState().(StoreState).decode(_, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TState =
|
||||
TInitState(Boolean preservesValue) or
|
||||
TStoreState(int size, Boolean preservesValue) {
|
||||
size in [1 .. ContentConfig::accessPathLimit()]
|
||||
} or
|
||||
TReadState(int size, Boolean preservesValue) { size in [1 .. ContentConfig::accessPathLimit()] }
|
||||
|
||||
abstract private class State extends TState {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** A flow state representing no reads or stores. */
|
||||
private class InitState extends State, TInitState {
|
||||
private boolean preservesValue_;
|
||||
|
||||
InitState() { this = TInitState(preservesValue_) }
|
||||
|
||||
override string toString() { result = "Init(" + preservesValue_ + ")" }
|
||||
|
||||
predicate decode(boolean preservesValue) { preservesValue = preservesValue_ }
|
||||
}
|
||||
|
||||
/** A flow state representing that content has been stored into. */
|
||||
private class StoreState extends State, TStoreState {
|
||||
private boolean preservesValue_;
|
||||
private int size_;
|
||||
|
||||
StoreState() { this = TStoreState(size_, preservesValue_) }
|
||||
|
||||
override string toString() { result = "StoreState(" + size_ + "," + preservesValue_ + ")" }
|
||||
|
||||
predicate decode(int size, boolean preservesValue) {
|
||||
size = size_ and preservesValue = preservesValue_
|
||||
}
|
||||
}
|
||||
|
||||
/** A flow state representing that content has been read from. */
|
||||
private class ReadState extends State, TReadState {
|
||||
private boolean preservesValue_;
|
||||
private int size_;
|
||||
|
||||
ReadState() { this = TReadState(size_, preservesValue_) }
|
||||
|
||||
override string toString() { result = "ReadState(" + size_ + "," + preservesValue_ + ")" }
|
||||
|
||||
predicate decode(int size, boolean preservesValue) {
|
||||
size = size_ and preservesValue = preservesValue_
|
||||
}
|
||||
}
|
||||
|
||||
private predicate storeStep(
|
||||
DataFlow::Node node1, State state1, DataFlow::ContentSet c, DataFlow::Node node2,
|
||||
StoreState state2
|
||||
) {
|
||||
exists(boolean preservesValue, int size |
|
||||
storeSet(node1, c, node2, _, _) and
|
||||
ContentConfig::isRelevantContent(c) and
|
||||
state2.decode(size + 1, preservesValue)
|
||||
|
|
||||
state1.(InitState).decode(preservesValue) and size = 0
|
||||
or
|
||||
state1.(ReadState).decode(_, preservesValue) and size = 0
|
||||
or
|
||||
state1.(StoreState).decode(size, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate readStep(
|
||||
DataFlow::Node node1, State state1, DataFlow::ContentSet c, DataFlow::Node node2,
|
||||
ReadState state2
|
||||
) {
|
||||
exists(int size |
|
||||
readSet(node1, c, node2) and
|
||||
ContentConfig::isRelevantContent(c) and
|
||||
state2.decode(size + 1, true)
|
||||
|
|
||||
state1.(InitState).decode(true) and
|
||||
size = 0
|
||||
or
|
||||
state1.(ReadState).decode(size, true)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate additionalStep(
|
||||
DataFlow::Node node1, State state1, DataFlow::Node node2, State state2
|
||||
) {
|
||||
ContentConfig::isAdditionalFlowStep(node1, node2) and
|
||||
(
|
||||
state1 instanceof InitState and
|
||||
state2.(InitState).decode(false)
|
||||
or
|
||||
exists(int size |
|
||||
state1.(ReadState).decode(size, _) and
|
||||
state2.(ReadState).decode(size, false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TAccessPath =
|
||||
TAccessPathNil() or
|
||||
TAccessPathCons(DataFlow::ContentSet head, AccessPath tail) {
|
||||
nodeReachesStore(_, _, _, _, head, _, tail)
|
||||
or
|
||||
nodeReachesRead(_, _, _, _, head, tail, _)
|
||||
}
|
||||
|
||||
/** An access path. */
|
||||
class AccessPath extends TAccessPath {
|
||||
/** Gets the head of this access path, if any. */
|
||||
DataFlow::ContentSet getHead() { this = TAccessPathCons(result, _) }
|
||||
|
||||
/** Gets the tail of this access path, if any. */
|
||||
AccessPath getTail() { this = TAccessPathCons(_, result) }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this access path.
|
||||
*
|
||||
* Elements are dot-separated, and the head of the stack is
|
||||
* rendered first.
|
||||
*/
|
||||
string toString() {
|
||||
this = TAccessPathNil() and
|
||||
result = ""
|
||||
or
|
||||
exists(DataFlow::ContentSet head, AccessPath tail |
|
||||
this = TAccessPathCons(head, tail) and
|
||||
result = head + "." + tail
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a big-step flow relation, where flow stops at read/store steps that
|
||||
* must be recorded, and flow via `subpaths` such that reads/stores inside
|
||||
* summarized callables can be recorded as well.
|
||||
*/
|
||||
private module BigStepFlow {
|
||||
private predicate reachesSink(Flow::PathNode node) {
|
||||
FlowConfig::isSink(node.getNode(), node.getState())
|
||||
or
|
||||
reachesSink(node.getASuccessor())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the flow step `pred -> succ` should not be allowed to be included
|
||||
* in the big-step relation.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate excludeStep(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
pred.getASuccessor() = succ and
|
||||
(
|
||||
// we need to record reads/stores inside summarized callables
|
||||
Flow::PathGraph::subpaths(pred, _, _, succ)
|
||||
or
|
||||
// only allow flow into a summarized callable, as part of the big-step
|
||||
// relation, when flow can reach a sink without going back out
|
||||
Flow::PathGraph::subpaths(pred, succ, _, _) and
|
||||
not reachesSink(succ)
|
||||
or
|
||||
// needed to record store steps
|
||||
storeStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState())
|
||||
or
|
||||
// needed to record read steps
|
||||
readStep(pred.getNode(), pred.getState(), _, succ.getNode(), succ.getState())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private DataFlowCallable getEnclosingCallableImpl(Flow::PathNode node) {
|
||||
result = getNodeEnclosingCallable(node.getNode())
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
private DataFlowCallable getEnclosingCallable(Flow::PathNode node) {
|
||||
pragma[only_bind_into](result) = getEnclosingCallableImpl(pragma[only_bind_out](node))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate bigStepEntry(Flow::PathNode node) {
|
||||
(
|
||||
FlowConfig::isSource(node.getNode(), node.getState())
|
||||
or
|
||||
excludeStep(_, node)
|
||||
or
|
||||
Flow::PathGraph::subpaths(_, node, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate bigStepExit(Flow::PathNode node) {
|
||||
(
|
||||
bigStepEntry(node)
|
||||
or
|
||||
FlowConfig::isSink(node.getNode(), node.getState())
|
||||
or
|
||||
excludeStep(node, _)
|
||||
or
|
||||
Flow::PathGraph::subpaths(_, _, node, _)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate step(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
pred.getASuccessor() = succ and
|
||||
not excludeStep(pred, succ)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate stepRec(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
step(pred, succ) and
|
||||
not bigStepEntry(pred)
|
||||
}
|
||||
|
||||
private predicate stepRecPlus(Flow::PathNode n1, Flow::PathNode n2) = fastTC(stepRec/2)(n1, n2)
|
||||
|
||||
/**
|
||||
* Holds if there is flow `pathSucc+(pred) = succ`, and such a flow path does
|
||||
* not go through any reads/stores that need to be recorded, or summarized
|
||||
* steps.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate bigStep(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
exists(Flow::PathNode mid |
|
||||
bigStepEntry(pred) and
|
||||
step(pred, mid)
|
||||
|
|
||||
succ = mid
|
||||
or
|
||||
stepRecPlus(mid, succ)
|
||||
) and
|
||||
bigStepExit(succ)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate bigStepNotLocal(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
bigStep(pred, succ) and
|
||||
not getEnclosingCallable(pred) = getEnclosingCallable(succ)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate bigStepMaybeLocal(Flow::PathNode pred, Flow::PathNode succ) {
|
||||
bigStep(pred, succ) and
|
||||
getEnclosingCallable(pred) = getEnclosingCallable(succ)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `source` can reach `node`, having read `reads` from the source and
|
||||
* written `stores` into `node`.
|
||||
*
|
||||
* `source` is either a source from a configuration, in which case `scReads` and
|
||||
* `scStores` are always empty, or it is the parameter of a summarized callable,
|
||||
* in which case `scReads` and `scStores` record the reads/stores for a summary
|
||||
* context, that is, the reads/stores for an argument that can reach the parameter.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate nodeReaches(
|
||||
Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node,
|
||||
AccessPath reads, AccessPath stores
|
||||
) {
|
||||
node = source and
|
||||
reads = scReads and
|
||||
stores = scStores and
|
||||
(
|
||||
Flow::flowPath(source, _) and
|
||||
scReads = TAccessPathNil() and
|
||||
scStores = TAccessPathNil()
|
||||
or
|
||||
// the argument in a sub path can be reached, so we start flow from the sub path
|
||||
// parameter, while recording the read/store summary context
|
||||
exists(Flow::PathNode arg |
|
||||
nodeReachesSubpathArg(_, _, _, arg, scReads, scStores) and
|
||||
Flow::PathGraph::subpaths(arg, source, _, _)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Flow::PathNode mid |
|
||||
nodeReaches(source, scReads, scStores, mid, reads, stores) and
|
||||
BigStepFlow::bigStepMaybeLocal(mid, node)
|
||||
)
|
||||
or
|
||||
exists(Flow::PathNode mid |
|
||||
nodeReaches(source, scReads, scStores, mid, reads, stores) and
|
||||
BigStepFlow::bigStepNotLocal(mid, node) and
|
||||
// when flow is not local, we cannot flow back out, so we may stop
|
||||
// flow early when computing summary flow
|
||||
Flow::flowPath(source, _) and
|
||||
scReads = TAccessPathNil() and
|
||||
scStores = TAccessPathNil()
|
||||
)
|
||||
or
|
||||
// store step
|
||||
exists(AccessPath storesMid, DataFlow::ContentSet c |
|
||||
nodeReachesStore(source, scReads, scStores, node, c, reads, storesMid) and
|
||||
stores = TAccessPathCons(c, storesMid)
|
||||
)
|
||||
or
|
||||
// read step
|
||||
exists(AccessPath readsMid, DataFlow::ContentSet c |
|
||||
nodeReachesRead(source, scReads, scStores, node, c, readsMid, stores) and
|
||||
reads = TAccessPathCons(c, readsMid)
|
||||
)
|
||||
or
|
||||
// flow-through step; match outer stores/reads with inner store/read summary contexts
|
||||
exists(Flow::PathNode mid, AccessPath innerScReads, AccessPath innerScStores |
|
||||
nodeReachesSubpathArg(source, scReads, scStores, mid, innerScReads, innerScStores) and
|
||||
subpathArgReachesOut(mid, innerScReads, innerScStores, node, reads, stores)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate nodeReachesStore(
|
||||
Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node,
|
||||
DataFlow::ContentSet c, AccessPath reads, AccessPath stores
|
||||
) {
|
||||
exists(Flow::PathNode mid |
|
||||
nodeReaches(source, scReads, scStores, mid, reads, stores) and
|
||||
storeStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState()) and
|
||||
mid.getASuccessor() = node
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate nodeReachesRead(
|
||||
Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode node,
|
||||
DataFlow::ContentSet c, AccessPath reads, AccessPath stores
|
||||
) {
|
||||
exists(Flow::PathNode mid |
|
||||
nodeReaches(source, scReads, scStores, mid, reads, stores) and
|
||||
readStep(mid.getNode(), mid.getState(), c, node.getNode(), node.getState()) and
|
||||
mid.getASuccessor() = node
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate nodeReachesSubpathArg(
|
||||
Flow::PathNode source, AccessPath scReads, AccessPath scStores, Flow::PathNode arg,
|
||||
AccessPath reads, AccessPath stores
|
||||
) {
|
||||
nodeReaches(source, scReads, scStores, arg, reads, stores) and
|
||||
Flow::PathGraph::subpaths(arg, _, _, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate subpathArgReachesOut(
|
||||
Flow::PathNode arg, AccessPath scReads, AccessPath scStores, Flow::PathNode out,
|
||||
AccessPath reads, AccessPath stores
|
||||
) {
|
||||
exists(Flow::PathNode source, Flow::PathNode ret |
|
||||
nodeReaches(source, scReads, scStores, ret, reads, stores) and
|
||||
Flow::PathGraph::subpaths(arg, source, ret, out)
|
||||
)
|
||||
}
|
||||
}
|
||||
private import semmle.code.csharp.Location
|
||||
private import DataFlowImplSpecific
|
||||
private import codeql.dataflow.internal.ContentDataFlowImpl
|
||||
import MakeImplContentDataFlow<Location, CsharpDataFlow>
|
||||
|
|
|
@ -908,19 +908,20 @@ private class Argument extends Expr {
|
|||
*
|
||||
* `postUpdate` indicates whether the store targets a post-update node.
|
||||
*/
|
||||
private predicate fieldOrPropertyStore(Expr e, Content c, Expr src, Expr q, boolean postUpdate) {
|
||||
private predicate fieldOrPropertyStore(Expr e, ContentSet c, Expr src, Expr q, boolean postUpdate) {
|
||||
exists(FieldOrProperty f |
|
||||
c = f.getContent() and
|
||||
c = f.getContentSet() and
|
||||
(
|
||||
f.isFieldLike() and
|
||||
f instanceof InstanceFieldOrProperty
|
||||
or
|
||||
exists(
|
||||
FlowSummaryImpl::Private::SummarizedCallableImpl sc,
|
||||
FlowSummaryImpl::Private::SummaryComponentStack input
|
||||
FlowSummaryImpl::Private::SummaryComponentStack input, ContentSet readSet
|
||||
|
|
||||
sc.propagatesFlow(input, _, _, _) and
|
||||
input.contains(FlowSummaryImpl::Private::SummaryComponent::content(f.getContent()))
|
||||
input.contains(FlowSummaryImpl::Private::SummaryComponent::content(readSet)) and
|
||||
c.getAStoreContent() = readSet.getAReadContent()
|
||||
)
|
||||
)
|
||||
|
|
||||
|
@ -970,28 +971,13 @@ private predicate fieldOrPropertyStore(Expr e, Content c, Expr src, Expr q, bool
|
|||
)
|
||||
}
|
||||
|
||||
/** Holds if property `p1` overrides or implements source declaration property `p2`. */
|
||||
private predicate overridesOrImplementsSourceDecl(Property p1, Property p2) {
|
||||
p1.getOverridee*().getUnboundDeclaration() = p2
|
||||
or
|
||||
p1.getAnUltimateImplementee().getUnboundDeclaration() = p2
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e2` is an expression that reads field or property `c` from
|
||||
* expression `e1`. This takes overriding into account for properties written
|
||||
* from library code.
|
||||
* expression `e1`.
|
||||
*/
|
||||
private predicate fieldOrPropertyRead(Expr e1, Content c, FieldOrPropertyRead e2) {
|
||||
private predicate fieldOrPropertyRead(Expr e1, ContentSet c, FieldOrPropertyRead e2) {
|
||||
e1 = e2.getQualifier() and
|
||||
exists(FieldOrProperty ret | c = ret.getContent() |
|
||||
ret = e2.getTarget()
|
||||
or
|
||||
exists(Property target |
|
||||
target.getGetter() = e2.(PropertyCall).getARuntimeTarget() and
|
||||
overridesOrImplementsSourceDecl(target, ret)
|
||||
)
|
||||
)
|
||||
c = e2.getTarget().(FieldOrProperty).getContentSet()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1208,6 +1194,11 @@ private module Cached {
|
|||
} or
|
||||
TCapturedVariableContent(VariableCapture::CapturedVariable v)
|
||||
|
||||
cached
|
||||
newtype TContentSet =
|
||||
TSingletonContent(Content c) { not c instanceof PropertyContent } or
|
||||
TPropertyContentSet(Property p) { p.isUnboundDeclaration() }
|
||||
|
||||
cached
|
||||
newtype TContentApprox =
|
||||
TFieldApproxContent(string firstChar) { firstChar = approximateFieldContent(_) } or
|
||||
|
@ -2076,10 +2067,10 @@ class FieldOrProperty extends Assignable, Modifiable {
|
|||
}
|
||||
|
||||
/** Gets the content that matches this field or property. */
|
||||
Content getContent() {
|
||||
result.(FieldContent).getField() = this.getUnboundDeclaration()
|
||||
ContentSet getContentSet() {
|
||||
result.isField(this.getUnboundDeclaration())
|
||||
or
|
||||
result.(PropertyContent).getProperty() = this.getUnboundDeclaration()
|
||||
result.isProperty(this.getUnboundDeclaration())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2211,8 +2202,8 @@ private class StoreStepConfiguration extends ControlFlowReachabilityConfiguratio
|
|||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private PropertyContent getResultContent() {
|
||||
result.getProperty() = any(SystemThreadingTasksTaskTClass c_).getResultProperty()
|
||||
private ContentSet getResultContent() {
|
||||
result.isProperty(any(SystemThreadingTasksTaskTClass c_).getResultProperty())
|
||||
}
|
||||
|
||||
private predicate primaryConstructorParameterStore(
|
||||
|
@ -2226,17 +2217,16 @@ private predicate primaryConstructorParameterStore(
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to
|
||||
* content `c`.
|
||||
*/
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
pragma[nomagic]
|
||||
private predicate recordParameter(RecordType t, Parameter p, string name) {
|
||||
p.getName() = name and p.getCallable().getDeclaringType() = t
|
||||
}
|
||||
|
||||
private predicate storeContentStep(Node node1, Content c, Node node2) {
|
||||
exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
|
||||
hasNodePath(x, node1, node) and
|
||||
if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
|
||||
|
|
||||
fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
|
||||
or
|
||||
arrayStore(_, node1.asExpr(), node.getExpr(), postUpdate) and c instanceof ElementContent
|
||||
)
|
||||
or
|
||||
|
@ -2257,26 +2247,59 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
|
|||
c instanceof ElementContent
|
||||
)
|
||||
or
|
||||
primaryConstructorParameterStore(node1, c, node2)
|
||||
or
|
||||
exists(Parameter p, DataFlowCallable callable |
|
||||
node1 = TExplicitParameterNode(p, callable) and
|
||||
node2 = TPrimaryConstructorThisAccessNode(p, true, callable) and
|
||||
not recordParameter(_, p, _) and
|
||||
c.(PrimaryConstructorParameterContent).getParameter() = p
|
||||
)
|
||||
or
|
||||
VariableCapture::storeStep(node1, c, node2)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate recordProperty(RecordType t, ContentSet c, string name) {
|
||||
exists(Property p |
|
||||
c.isProperty(p) and
|
||||
p.getName() = name and
|
||||
p.getDeclaringType() = t
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to
|
||||
* content `c`.
|
||||
*/
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(Content cont |
|
||||
storeContentStep(node1, cont, node2) and
|
||||
c.isSingleton(cont)
|
||||
)
|
||||
or
|
||||
exists(StoreStepConfiguration x, ExprNode node, boolean postUpdate |
|
||||
hasNodePath(x, node1, node) and
|
||||
if postUpdate = true then node = node2.(PostUpdateNode).getPreUpdateNode() else node = node2
|
||||
|
|
||||
fieldOrPropertyStore(_, c, node1.asExpr(), node.getExpr(), postUpdate)
|
||||
)
|
||||
or
|
||||
exists(Expr e |
|
||||
e = node1.asExpr() and
|
||||
node2.(AsyncReturnNode).getExpr() = e and
|
||||
c = getResultContent()
|
||||
)
|
||||
or
|
||||
primaryConstructorParameterStore(node1, c, node2)
|
||||
or
|
||||
exists(Parameter p, DataFlowCallable callable |
|
||||
exists(Parameter p, DataFlowCallable callable, RecordType t, string name |
|
||||
node1 = TExplicitParameterNode(p, callable) and
|
||||
node2 = TPrimaryConstructorThisAccessNode(p, true, callable) and
|
||||
if p.getCallable().getDeclaringType() instanceof RecordType
|
||||
then c.(PropertyContent).getProperty().getName() = p.getName()
|
||||
else c.(PrimaryConstructorParameterContent).getParameter() = p
|
||||
recordParameter(t, p, name) and
|
||||
recordProperty(t, c, name)
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode())
|
||||
or
|
||||
VariableCapture::storeStep(node1, c, node2)
|
||||
}
|
||||
|
||||
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
|
@ -2344,14 +2367,8 @@ private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
|
||||
*/
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
private predicate readContentStep(Node node1, Content c, Node node2) {
|
||||
exists(ReadStepConfiguration x |
|
||||
hasNodePath(x, node1, node2) and
|
||||
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||
or
|
||||
hasNodePath(x, node1, node2) and
|
||||
arrayRead(node1.asExpr(), node2.asExpr()) and
|
||||
c instanceof ElementContent
|
||||
|
@ -2363,10 +2380,6 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
|
|||
c instanceof ElementContent
|
||||
)
|
||||
or
|
||||
hasNodePath(x, node1, node2) and
|
||||
node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
|
||||
c = getResultContent()
|
||||
or
|
||||
node1 =
|
||||
any(InstanceParameterAccessPreNode n |
|
||||
n.getUnderlyingControlFlowNode() = node2.(ExprNode).getControlFlowNode() and
|
||||
|
@ -2404,31 +2417,30 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
|
|||
)
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode())
|
||||
or
|
||||
VariableCapture::readStep(node1, c, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
* Holds if data can flow from `node1` to `node2` via a read of content `c`.
|
||||
*/
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
fieldOrPropertyStore(_, c, _, n.asExpr(), true)
|
||||
or
|
||||
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
|
||||
or
|
||||
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
|
||||
oi = we.getInitializer() and
|
||||
n.asExpr() = oi and
|
||||
f = oi.getAMemberInitializer().getInitializedMember() and
|
||||
c = f.getContent()
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(Content cont |
|
||||
readContentStep(node1, cont, node2) and
|
||||
c.isSingleton(cont)
|
||||
)
|
||||
or
|
||||
exists(ReadStepConfiguration x | hasNodePath(x, node1, node2) |
|
||||
fieldOrPropertyRead(node1.asExpr(), c, node2.asExpr())
|
||||
or
|
||||
node2.asExpr().(AwaitExpr).getExpr() = node1.asExpr() and
|
||||
c = getResultContent()
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
private predicate clearsCont(Node n, Content c) {
|
||||
exists(Argument a, Struct s, Field f |
|
||||
a = n.(PostUpdateNode).getPreUpdateNode().asExpr() and
|
||||
a.getType() = s and
|
||||
|
@ -2442,6 +2454,31 @@ predicate clearsContent(Node n, ContentSet c) {
|
|||
VariableCapture::clearsContent(n, c)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`. For example,
|
||||
* any value stored inside `f` is cleared at the pre-update node associated with `x`
|
||||
* in `x.f = newValue`.
|
||||
*/
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
exists(Content cont |
|
||||
clearsCont(n, cont) and
|
||||
c.isSingleton(cont)
|
||||
)
|
||||
or
|
||||
fieldOrPropertyStore(_, c, _, n.asExpr(), true)
|
||||
or
|
||||
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
|
||||
or
|
||||
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
|
||||
oi = we.getInitializer() and
|
||||
n.asExpr() = oi and
|
||||
f = oi.getAMemberInitializer().getInitializedMember() and
|
||||
c = f.getContentSet()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value that is being tracked is expected to be stored inside content `c`
|
||||
* at node `n`.
|
||||
|
@ -2449,7 +2486,7 @@ predicate clearsContent(Node n, ContentSet c) {
|
|||
predicate expectsContent(Node n, ContentSet c) {
|
||||
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
|
||||
or
|
||||
n.asExpr() instanceof SpreadElementExpr and c instanceof ElementContent
|
||||
n.asExpr() instanceof SpreadElementExpr and c.isElement()
|
||||
}
|
||||
|
||||
class NodeRegion instanceof ControlFlow::BasicBlock {
|
||||
|
@ -3050,8 +3087,3 @@ abstract class SyntheticField extends string {
|
|||
/** Gets the type of this synthetic field. */
|
||||
Type getType() { result instanceof ObjectType }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the the content `c` is a container.
|
||||
*/
|
||||
predicate containerContent(DataFlow::Content c) { c instanceof DataFlow::ElementContent }
|
||||
|
|
|
@ -267,22 +267,82 @@ class CapturedVariableContent extends Content, TCapturedVariableContent {
|
|||
override Location getLocation() { result = v.getLocation() }
|
||||
}
|
||||
|
||||
/** Holds if property `p1` overrides or implements source declaration property `p2`. */
|
||||
private predicate overridesOrImplementsSourceDecl(Property p1, Property p2) {
|
||||
p1.getOverridee*().getUnboundDeclaration() = p2
|
||||
or
|
||||
p1.getAnUltimateImplementee().getUnboundDeclaration() = p2
|
||||
}
|
||||
|
||||
/**
|
||||
* An entity that represents a set of `Content`s.
|
||||
*
|
||||
* The set may be interpreted differently depending on whether it is
|
||||
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
|
||||
*/
|
||||
class ContentSet instanceof Content {
|
||||
class ContentSet extends TContentSet {
|
||||
/** Holds if this content set is the singleton `{c}`. */
|
||||
predicate isSingleton(Content c) { this = TSingletonContent(c) }
|
||||
|
||||
/**
|
||||
* Holds if this content set represents the property `p`.
|
||||
*
|
||||
*
|
||||
* For `getAReadContent`, this set represents all properties that may
|
||||
* (reflexively and transitively) override/implement `p` (or vice versa).
|
||||
*/
|
||||
predicate isProperty(Property p) { this = TPropertyContentSet(p) }
|
||||
|
||||
/** Holds if this content set represent the field `f`. */
|
||||
predicate isField(Field f) { this.isSingleton(TFieldContent(f)) }
|
||||
|
||||
/** Holds if this content set represents an element in a collection. */
|
||||
predicate isElement() { this.isSingleton(TElementContent()) }
|
||||
|
||||
/** Gets a content that may be stored into when storing into this set. */
|
||||
Content getAStoreContent() { result = this }
|
||||
Content getAStoreContent() {
|
||||
this.isSingleton(result)
|
||||
or
|
||||
this.isProperty(result.(PropertyContent).getProperty())
|
||||
}
|
||||
|
||||
/** Gets a content that may be read from when reading from this set. */
|
||||
Content getAReadContent() { result = this }
|
||||
Content getAReadContent() {
|
||||
this.isSingleton(result)
|
||||
or
|
||||
exists(Property p1, Property p2 |
|
||||
this.isProperty(p1) and
|
||||
p2 = result.(PropertyContent).getProperty()
|
||||
|
|
||||
overridesOrImplementsSourceDecl(p2, p1)
|
||||
or
|
||||
overridesOrImplementsSourceDecl(p1, p2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this content set. */
|
||||
string toString() { result = super.toString() }
|
||||
string toString() {
|
||||
exists(Content c |
|
||||
this.isSingleton(c) and
|
||||
result = c.toString()
|
||||
)
|
||||
or
|
||||
exists(Property p |
|
||||
this.isProperty(p) and
|
||||
result = "property " + p.getName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the location of this content set. */
|
||||
Location getLocation() { result = super.getLocation() }
|
||||
Location getLocation() {
|
||||
exists(Content c |
|
||||
this.isSingleton(c) and
|
||||
result = c.getLocation()
|
||||
)
|
||||
or
|
||||
exists(Property p |
|
||||
this.isProperty(p) and
|
||||
result = p.getLocation()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>
|
|||
result = "delegate-self"
|
||||
}
|
||||
|
||||
string encodeContent(ContentSet c, string arg) {
|
||||
private string encodeCont(Content c, string arg) {
|
||||
c = TElementContent() and result = "Element" and arg = ""
|
||||
or
|
||||
exists(Field f, string qualifier, string name |
|
||||
|
@ -56,27 +56,34 @@ module Input implements InputSig<Location, DataFlowImplSpecific::CsharpDataFlow>
|
|||
result = "Field"
|
||||
)
|
||||
or
|
||||
exists(Property p, string qualifier, string name |
|
||||
c = TPropertyContent(p) and
|
||||
p.hasFullyQualifiedName(qualifier, name) and
|
||||
arg = getQualifiedName(qualifier, name) and
|
||||
result = "Property"
|
||||
)
|
||||
or
|
||||
exists(SyntheticField f |
|
||||
c = TSyntheticFieldContent(f) and result = "SyntheticField" and arg = f
|
||||
)
|
||||
}
|
||||
|
||||
string encodeContent(ContentSet c, string arg) {
|
||||
exists(Content cont |
|
||||
c.isSingleton(cont) and
|
||||
result = encodeCont(cont, arg)
|
||||
)
|
||||
or
|
||||
exists(Property p, string qualifier, string name |
|
||||
c.isProperty(p) and
|
||||
p.hasFullyQualifiedName(qualifier, name) and
|
||||
arg = getQualifiedName(qualifier, name) and
|
||||
result = "Property"
|
||||
)
|
||||
}
|
||||
|
||||
string encodeWithoutContent(ContentSet c, string arg) {
|
||||
result = "WithoutElement" and
|
||||
c = TElementContent() and
|
||||
c.isElement() and
|
||||
arg = ""
|
||||
}
|
||||
|
||||
string encodeWithContent(ContentSet c, string arg) {
|
||||
result = "WithElement" and
|
||||
c = TElementContent() and
|
||||
c.isElement() and
|
||||
arg = ""
|
||||
}
|
||||
|
||||
|
@ -103,12 +110,10 @@ private module TypesInput implements Impl::Private::TypesInputSig {
|
|||
result.asGvnType() = Gvn::getGlobalValueNumber(any(ObjectType t))
|
||||
}
|
||||
|
||||
DataFlowType getContentType(ContentSet c) {
|
||||
private DataFlowType getContType(Content c) {
|
||||
exists(Type t | result.asGvnType() = Gvn::getGlobalValueNumber(t) |
|
||||
t = c.(FieldContent).getField().getType()
|
||||
or
|
||||
t = c.(PropertyContent).getProperty().getType()
|
||||
or
|
||||
t = c.(SyntheticFieldContent).getField().getType()
|
||||
or
|
||||
c instanceof ElementContent and
|
||||
|
@ -116,6 +121,17 @@ private module TypesInput implements Impl::Private::TypesInputSig {
|
|||
)
|
||||
}
|
||||
|
||||
DataFlowType getContentType(ContentSet c) {
|
||||
exists(Content cont |
|
||||
c.isSingleton(cont) and
|
||||
result = getContType(cont)
|
||||
)
|
||||
or
|
||||
exists(Property p |
|
||||
c.isProperty(p) and result.asGvnType() = Gvn::getGlobalValueNumber(p.getType())
|
||||
)
|
||||
}
|
||||
|
||||
DataFlowType getParameterType(Impl::Public::SummarizedCallable c, ParameterPosition pos) {
|
||||
exists(Type t | result.asGvnType() = Gvn::getGlobalValueNumber(t) |
|
||||
exists(int i |
|
||||
|
@ -311,17 +327,16 @@ module Private {
|
|||
}
|
||||
|
||||
/** Gets a summary component that represents an element in a collection. */
|
||||
SummaryComponent element() { result = content(any(DataFlow::ElementContent c)) }
|
||||
SummaryComponent element() { result = content(any(ContentSet cs | cs.isElement())) }
|
||||
|
||||
/** Gets a summary component for property `p`. */
|
||||
SummaryComponent property(Property p) {
|
||||
result =
|
||||
content(any(DataFlow::PropertyContent c | c.getProperty() = p.getUnboundDeclaration()))
|
||||
result = content(any(DataFlow::ContentSet c | c.isProperty(p.getUnboundDeclaration())))
|
||||
}
|
||||
|
||||
/** Gets a summary component for field `f`. */
|
||||
SummaryComponent field(Field f) {
|
||||
result = content(any(DataFlow::FieldContent c | c.getField() = f.getUnboundDeclaration()))
|
||||
result = content(any(DataFlow::ContentSet c | c.isField(f.getUnboundDeclaration())))
|
||||
}
|
||||
|
||||
/** Gets a summary component that represents the return value of a call. */
|
||||
|
|
|
@ -122,22 +122,22 @@ private module Cached {
|
|||
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
|
||||
or
|
||||
// Taint collection by adding a tainted element
|
||||
exists(DataFlow::ElementContent c |
|
||||
exists(DataFlow::ContentSet c | c.isElement() |
|
||||
storeStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summarySetterStep(nodeFrom, c, nodeTo, _)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Content c |
|
||||
exists(DataFlow::ContentSet c |
|
||||
readStep(nodeFrom, c, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryGetterStep(nodeFrom, c, nodeTo, _)
|
||||
|
|
||||
// Taint members
|
||||
c = any(TaintedMember m).(FieldOrProperty).getContent()
|
||||
c = any(TaintedMember m).(FieldOrProperty).getContentSet()
|
||||
or
|
||||
// Read from a tainted collection
|
||||
c = TElementContent()
|
||||
c.isElement()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -152,12 +152,12 @@ private module Cached {
|
|||
localTaintStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
// Taint members
|
||||
readStep(nodeFrom, any(TaintedMember m).(FieldOrProperty).getContent(), nodeTo)
|
||||
readStep(nodeFrom, any(TaintedMember m).(FieldOrProperty).getContentSet(), nodeTo)
|
||||
or
|
||||
// Although flow through collections is modeled precisely using stores/reads, we still
|
||||
// allow flow out of a _tainted_ collection. This is needed in order to support taint-
|
||||
// tracking configurations where the source is a collection
|
||||
readStep(nodeFrom, TElementContent(), nodeTo)
|
||||
readStep(nodeFrom, any(DataFlow::ContentSet c | c.isElement()), nodeTo)
|
||||
or
|
||||
nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
|
||||
) and
|
||||
|
|
|
@ -282,12 +282,12 @@ module EntityFramework {
|
|||
* If `t2` is a column type, `c2` will be included in the model (see
|
||||
* https://docs.microsoft.com/en-us/ef/core/modeling/entity-types?tabs=data-annotations).
|
||||
*/
|
||||
private predicate step(Content c1, Type t1, Content c2, Type t2, int dist) {
|
||||
private predicate step(ContentSet c1, Type t1, ContentSet c2, Type t2, int dist) {
|
||||
exists(Property p1 |
|
||||
p1 = this.getADbSetProperty(t2) and
|
||||
c1.(PropertyContent).getProperty() = p1 and
|
||||
c1.isProperty(p1) and
|
||||
t1 = p1.getType() and
|
||||
c2 instanceof ElementContent and
|
||||
c2.isElement() and
|
||||
dist = 0
|
||||
)
|
||||
or
|
||||
|
@ -299,17 +299,17 @@ module EntityFramework {
|
|||
exists(Property p2 |
|
||||
p2.getDeclaringType().(Class) = t1 and
|
||||
not isColumnType(t1) and
|
||||
c2.(PropertyContent).getProperty() = p2 and
|
||||
c2.isProperty(p2) and
|
||||
t2 = p2.getType() and
|
||||
not isNotMapped(p2)
|
||||
)
|
||||
or
|
||||
exists(ConstructedInterface ci |
|
||||
c1 instanceof PropertyContent and
|
||||
c1.isProperty(_) and
|
||||
t1.(ValueOrRefType).getABaseType*() = ci and
|
||||
not t1 instanceof StringType and
|
||||
ci.getUnboundDeclaration() instanceof SystemCollectionsGenericIEnumerableTInterface and
|
||||
c2 instanceof ElementContent and
|
||||
c2.isElement() and
|
||||
t2 = ci.getTypeArgument(0)
|
||||
)
|
||||
)
|
||||
|
@ -340,16 +340,16 @@ module EntityFramework {
|
|||
* ```
|
||||
*/
|
||||
Property getAColumnProperty(int dist) {
|
||||
exists(PropertyContent c, Type t |
|
||||
exists(ContentSet c, Type t |
|
||||
this.step(_, _, c, t, dist) and
|
||||
c.getProperty() = result and
|
||||
c.isProperty(result) and
|
||||
isColumnType(t)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate stepRev(Content c1, Type t1, Content c2, Type t2, int dist) {
|
||||
private predicate stepRev(ContentSet c1, Type t1, ContentSet c2, Type t2, int dist) {
|
||||
this.step(c1, t1, c2, t2, dist) and
|
||||
c2.(PropertyContent).getProperty() = this.getAColumnProperty(dist)
|
||||
c2.isProperty(this.getAColumnProperty(dist))
|
||||
or
|
||||
this.stepRev(c2, t2, _, _, dist + 1) and
|
||||
this.step(c1, t1, c2, t2, dist)
|
||||
|
@ -364,13 +364,13 @@ module EntityFramework {
|
|||
|
||||
/** Holds if component stack `head :: tail` is required for the input specification. */
|
||||
predicate requiresComponentStackIn(
|
||||
Content head, Type headType, SummaryComponentStack tail, int dist
|
||||
ContentSet head, Type headType, SummaryComponentStack tail, int dist
|
||||
) {
|
||||
tail = SummaryComponentStack::qualifier() and
|
||||
this.stepRev(head, headType, _, _, 0) and
|
||||
dist = -1
|
||||
or
|
||||
exists(Content tailHead, Type tailType, SummaryComponentStack tailTail |
|
||||
exists(ContentSet tailHead, Type tailType, SummaryComponentStack tailTail |
|
||||
this.requiresComponentStackIn(tailHead, tailType, tailTail, dist - 1) and
|
||||
tail = SummaryComponentStack::push(SummaryComponent::content(tailHead), tailTail) and
|
||||
this.stepRev(tailHead, tailType, head, headType, dist)
|
||||
|
@ -379,18 +379,18 @@ module EntityFramework {
|
|||
|
||||
/** Holds if component stack `head :: tail` is required for the output specification. */
|
||||
predicate requiresComponentStackOut(
|
||||
Content head, Type headType, SummaryComponentStack tail, int dist,
|
||||
ContentSet head, Type headType, SummaryComponentStack tail, int dist,
|
||||
DbContextClassSetProperty dbSetProp
|
||||
) {
|
||||
exists(PropertyContent c1 |
|
||||
exists(ContentSet c1 |
|
||||
dbSetProp = this.getADbSetProperty(headType) and
|
||||
this.stepRev(c1, _, head, headType, 0) and
|
||||
c1.getProperty() = dbSetProp and
|
||||
c1.isProperty(dbSetProp) and
|
||||
tail = SummaryComponentStack::return() and
|
||||
dist = 0
|
||||
)
|
||||
or
|
||||
exists(Content tailHead, SummaryComponentStack tailTail, Type tailType |
|
||||
exists(ContentSet tailHead, SummaryComponentStack tailTail, Type tailType |
|
||||
this.requiresComponentStackOut(tailHead, tailType, tailTail, dist - 1, dbSetProp) and
|
||||
tail = SummaryComponentStack::push(SummaryComponent::content(tailHead), tailTail) and
|
||||
this.stepRev(tailHead, tailType, head, headType, dist)
|
||||
|
@ -402,9 +402,9 @@ module EntityFramework {
|
|||
*/
|
||||
pragma[noinline]
|
||||
predicate input(SummaryComponentStack input, Property mapped) {
|
||||
exists(PropertyContent head, SummaryComponentStack tail |
|
||||
exists(ContentSet head, SummaryComponentStack tail |
|
||||
this.requiresComponentStackIn(head, _, tail, _) and
|
||||
head.getProperty() = mapped and
|
||||
head.isProperty(mapped) and
|
||||
mapped = this.getAColumnProperty(_) and
|
||||
input = SummaryComponentStack::push(SummaryComponent::content(head), tail)
|
||||
)
|
||||
|
@ -418,9 +418,9 @@ module EntityFramework {
|
|||
private predicate output(
|
||||
SummaryComponentStack output, Property mapped, DbContextClassSetProperty dbSet
|
||||
) {
|
||||
exists(PropertyContent head, SummaryComponentStack tail |
|
||||
exists(ContentSet head, SummaryComponentStack tail |
|
||||
this.requiresComponentStackOut(head, _, tail, _, dbSet) and
|
||||
head.getProperty() = mapped and
|
||||
head.isProperty(mapped) and
|
||||
mapped = this.getAColumnProperty(_) and
|
||||
output = SummaryComponentStack::push(SummaryComponent::content(head), tail)
|
||||
)
|
||||
|
@ -505,7 +505,7 @@ module EntityFramework {
|
|||
private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack
|
||||
{
|
||||
override predicate required(SummaryComponent head, SummaryComponentStack tail) {
|
||||
exists(Content c | head = SummaryComponent::content(c) |
|
||||
exists(ContentSet c | head = SummaryComponent::content(c) |
|
||||
any(DbContextClass cls).requiresComponentStackIn(c, _, tail, _)
|
||||
or
|
||||
any(DbContextClass cls).requiresComponentStackOut(c, _, tail, _, _)
|
||||
|
|
|
@ -205,7 +205,6 @@ class MicrosoftAspNetCoreMvcController extends Class {
|
|||
)
|
||||
) and
|
||||
this.isPublic() and
|
||||
(not this.isAbstract() or this instanceof MicrosoftAspNetCoreMvcControllerBaseClass) and
|
||||
not this instanceof Generic and
|
||||
(
|
||||
this.getABaseType*() instanceof MicrosoftAspNetCoreMvcControllerBaseClass
|
||||
|
|
|
@ -12,6 +12,7 @@ import DatabaseQuality
|
|||
|
||||
predicate compilationInfo(string key, float value) {
|
||||
not key.matches("Compiler diagnostic count for%") and
|
||||
not key.matches("Extractor message count for group%") and
|
||||
exists(Compilation c, string infoKey, string infoValue | infoValue = c.getInfo(infoKey) |
|
||||
key = infoKey and
|
||||
value = infoValue.toFloat()
|
||||
|
@ -22,6 +23,16 @@ predicate compilationInfo(string key, float value) {
|
|||
)
|
||||
}
|
||||
|
||||
predicate compilerDiagnostics(string key, int value) {
|
||||
key.matches("Compiler diagnostic count for%") and
|
||||
strictsum(Compilation c | | c.getInfo(key).toInt()) = value
|
||||
}
|
||||
|
||||
predicate extractorMessages(string key, int value) {
|
||||
key.matches("Extractor message count for group%") and
|
||||
strictsum(Compilation c | | c.getInfo(key).toInt()) = value
|
||||
}
|
||||
|
||||
predicate fileCount(string key, int value) {
|
||||
key = "Number of files" and
|
||||
value = strictcount(File f)
|
||||
|
@ -140,6 +151,8 @@ from string key, float value
|
|||
where
|
||||
(
|
||||
compilationInfo(key, value) or
|
||||
compilerDiagnostics(key, value) or
|
||||
extractorMessages(key, value) or
|
||||
fileCount(key, value) or
|
||||
fileCountByExtension(key, value) or
|
||||
totalNumberOfLines(key, value) or
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @name Capture Summary Models Partial Path
|
||||
* @description Capture Summary Models Partial Path
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @id csharp/utils/modelgenerator/summary-models-partial-path
|
||||
* @severity info
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import PartialFlow::PartialPathGraph
|
||||
|
||||
int explorationLimit() { result = 3 }
|
||||
|
||||
module PartialFlow = PropagateFlow::FlowExplorationFwd<explorationLimit/0>;
|
||||
|
||||
from
|
||||
PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink,
|
||||
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p
|
||||
where
|
||||
PartialFlow::partialFlow(source, sink, _) and
|
||||
p = source.getNode() and
|
||||
p.asParameter() = api.getAParameter()
|
||||
select sink.getNode(), source, sink, "There is flow from a $@ to $@.", source.getNode(),
|
||||
"parameter", sink.getNode(), "intermediate value"
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @name Capture Summary Models Path
|
||||
* @description Capture Summary Models Path
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @id csharp/utils/modelgenerator/summary-models-path
|
||||
* @severity warning
|
||||
* @tags modelgenerator
|
||||
*/
|
||||
|
||||
import csharp
|
||||
import utils.modelgenerator.internal.CaptureModels
|
||||
import PropagateFlow::PathGraph
|
||||
|
||||
from
|
||||
PropagateFlow::PathNode source, PropagateFlow::PathNode sink, DataFlowSummaryTargetApi api,
|
||||
DataFlow::Node p, DataFlow::Node returnNodeExt
|
||||
where
|
||||
PropagateFlow::flowPath(source, sink) and
|
||||
p = source.getNode() and
|
||||
returnNodeExt = sink.getNode() and
|
||||
exists(captureThroughFlow0(api, p, returnNodeExt))
|
||||
select sink.getNode(), source, sink, "There is flow from $@ to the $@.", source.getNode(),
|
||||
"parameter", sink.getNode(), "return value"
|
|
@ -0,0 +1 @@
|
|||
The queries in this directory are purely used for model generator debugging purposes in VS Code.
|
|
@ -50,7 +50,7 @@ module Printing = ModelPrinting<ModelPrintingInput>;
|
|||
/**
|
||||
* Holds if `c` is a relevant content kind, where the underlying type is relevant.
|
||||
*/
|
||||
private predicate isRelevantTypeInContent(DataFlow::Content c) {
|
||||
private predicate isRelevantTypeInContent(DataFlow::ContentSet c) {
|
||||
isRelevantType(getUnderlyingContentType(c))
|
||||
}
|
||||
|
||||
|
@ -58,24 +58,22 @@ private predicate isRelevantTypeInContent(DataFlow::Content 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::Content f |
|
||||
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::Content f | DataFlowPrivate::storeStep(node1, f, node2) |
|
||||
DataFlowPrivate::containerContent(f)
|
||||
)
|
||||
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.
|
||||
*/
|
||||
private predicate isRelevantContent(DataFlow::Content c) {
|
||||
private predicate isRelevantContent(DataFlow::ContentSet c) {
|
||||
isRelevantTypeInContent(c) or
|
||||
DataFlowPrivate::containerContent(c)
|
||||
containerContent(c)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -170,8 +168,8 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
|||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(DataFlow::Content c |
|
||||
DataFlowImplCommon::store(node1, c, node2, _, _) and
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowImplCommon::store(node1, c.getAStoreContent(), node2, _, _) and
|
||||
isRelevantContent(c) and
|
||||
(
|
||||
state1 instanceof TaintRead and state2.(TaintStore).getStep() = 1
|
||||
|
@ -180,7 +178,7 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
|||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Content c |
|
||||
exists(DataFlow::ContentSet c |
|
||||
DataFlowPrivate::readStep(node1, c, node2) and
|
||||
isRelevantContent(c) and
|
||||
state1.(TaintRead).getStep() + 1 = state2.(TaintRead).getStep()
|
||||
|
@ -196,14 +194,13 @@ module PropagateFlowConfig implements DataFlow::StateConfigSig {
|
|||
}
|
||||
}
|
||||
|
||||
private module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
module PropagateFlow = TaintTracking::GlobalWithState<PropagateFlowConfig>;
|
||||
|
||||
/**
|
||||
* 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, string input, string output |
|
||||
PropagateFlow::flow(p, returnNodeExt) and
|
||||
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 = returnNodeExt.getOutput() and
|
||||
|
@ -212,6 +209,16 @@ string captureThroughFlow(DataFlowSummaryTargetApi api) {
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A dataflow configuration used for finding new sources.
|
||||
* The sources are the already known existing sources and the sinks are the API return nodes.
|
||||
|
|
|
@ -210,10 +210,24 @@ predicate isRelevantType(CS::Type t) {
|
|||
/**
|
||||
* Gets the underlying type of the content `c`.
|
||||
*/
|
||||
CS::Type getUnderlyingContentType(DataFlow::Content c) {
|
||||
private CS::Type getUnderlyingContType(DataFlow::Content c) {
|
||||
result = c.(DataFlow::FieldContent).getField().getType() or
|
||||
result = c.(DataFlow::SyntheticFieldContent).getField().getType() or
|
||||
result = c.(DataFlow::PropertyContent).getProperty().getType()
|
||||
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()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -325,3 +339,8 @@ predicate isRelevantSinkKind(string kind) { any() }
|
|||
*/
|
||||
bindingset[kind]
|
||||
predicate isRelevantSourceKind(string kind) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the the content `c` is a container.
|
||||
*/
|
||||
predicate containerContent(DataFlow::ContentSet c) { c.isElement() }
|
||||
|
|
|
@ -52,12 +52,10 @@ edges
|
|||
| CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | provenance | MaD:2 |
|
||||
| CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | provenance | MaD:8 |
|
||||
| CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | provenance | MaD:16 |
|
||||
| CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | provenance | MaD:16 |
|
||||
| CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:70 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | provenance | |
|
||||
| CollectionFlow.cs:32:67:32:70 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | provenance | MaD:1 |
|
||||
| CollectionFlow.cs:32:67:32:70 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | provenance | MaD:7 |
|
||||
| CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | provenance | MaD:16 |
|
||||
| CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | provenance | MaD:16 |
|
||||
| CollectionFlow.cs:34:57:34:60 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | provenance | |
|
||||
| CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:66:34:77 | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A | provenance | MaD:16 |
|
||||
| CollectionFlow.cs:34:66:34:77 | call to method First<KeyValuePair<T,Int32>> : KeyValuePair<T,Int32> [property Key] : A | CollectionFlow.cs:34:66:34:81 | access to property Key : A | provenance | |
|
||||
|
@ -378,14 +376,10 @@ nodes
|
|||
| CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | semmle.label | dict : Dictionary<T,T> [element, property Value] : A |
|
||||
| CollectionFlow.cs:30:69:30:72 | access to parameter dict : Dictionary<T,T> [element, property Value] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Value] : A |
|
||||
| CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | semmle.label | access to property Values : ICollection<T> [element] : A |
|
||||
| CollectionFlow.cs:30:69:30:79 | access to property Values : ICollection<T> [element] : A | semmle.label | access to property Values : ICollection<T> [element] : A |
|
||||
| CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | semmle.label | call to method First<T> : A |
|
||||
| CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | semmle.label | call to method First<T> : A |
|
||||
| CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | semmle.label | dict : Dictionary<T,T> [element, property Key] : A |
|
||||
| CollectionFlow.cs:32:67:32:70 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Key] : A |
|
||||
| CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | semmle.label | access to property Keys : ICollection<T> [element] : A |
|
||||
| CollectionFlow.cs:32:67:32:75 | access to property Keys : ICollection<T> [element] : A | semmle.label | access to property Keys : ICollection<T> [element] : A |
|
||||
| CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | semmle.label | call to method First<T> : A |
|
||||
| CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | semmle.label | call to method First<T> : A |
|
||||
| CollectionFlow.cs:34:57:34:60 | dict : Dictionary<T,T> [element, property Key] : A | semmle.label | dict : Dictionary<T,T> [element, property Key] : A |
|
||||
| CollectionFlow.cs:34:66:34:69 | access to parameter dict : Dictionary<T,T> [element, property Key] : A | semmle.label | access to parameter dict : Dictionary<T,T> [element, property Key] : A |
|
||||
|
@ -671,20 +665,15 @@ subpaths
|
|||
| CollectionFlow.cs:156:28:156:31 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:58:26:61 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:67:26:73 | access to indexer : A | CollectionFlow.cs:156:14:156:32 | call to method DictIndexZero<A> |
|
||||
| CollectionFlow.cs:157:29:157:32 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:59:28:62 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:68:28:85 | access to property Value : A | CollectionFlow.cs:157:14:157:33 | call to method DictFirstValue<A> |
|
||||
| CollectionFlow.cs:158:30:158:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:158:14:158:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:158:30:158:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:158:14:158:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:178:28:178:31 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:58:26:61 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:67:26:73 | access to indexer : A | CollectionFlow.cs:178:14:178:32 | call to method DictIndexZero<A> |
|
||||
| CollectionFlow.cs:179:29:179:32 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:59:28:62 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:68:28:85 | access to property Value : A | CollectionFlow.cs:179:14:179:33 | call to method DictFirstValue<A> |
|
||||
| CollectionFlow.cs:180:30:180:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:180:14:180:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:180:30:180:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:180:14:180:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:199:28:199:31 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:58:26:61 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:26:67:26:73 | access to indexer : A | CollectionFlow.cs:199:14:199:32 | call to method DictIndexZero<A> |
|
||||
| CollectionFlow.cs:200:29:200:32 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:59:28:62 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:28:68:28:85 | access to property Value : A | CollectionFlow.cs:200:14:200:33 | call to method DictFirstValue<A> |
|
||||
| CollectionFlow.cs:201:30:201:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:201:14:201:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:201:30:201:33 | access to local variable dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:60:30:63 | dict : Dictionary<T,T> [element, property Value] : A | CollectionFlow.cs:30:69:30:87 | call to method First<T> : A | CollectionFlow.cs:201:14:201:34 | call to method DictValuesFirst<A> |
|
||||
| CollectionFlow.cs:221:28:221:31 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | CollectionFlow.cs:221:14:221:32 | call to method DictKeysFirst<A> |
|
||||
| CollectionFlow.cs:221:28:221:31 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | CollectionFlow.cs:221:14:221:32 | call to method DictKeysFirst<A> |
|
||||
| CollectionFlow.cs:222:27:222:30 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:57:34:60 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:66:34:81 | access to property Key : A | CollectionFlow.cs:222:14:222:31 | call to method DictFirstKey<A> |
|
||||
| CollectionFlow.cs:240:28:240:31 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | CollectionFlow.cs:240:14:240:32 | call to method DictKeysFirst<A> |
|
||||
| CollectionFlow.cs:240:28:240:31 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:58:32:61 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:32:67:32:83 | call to method First<T> : A | CollectionFlow.cs:240:14:240:32 | call to method DictKeysFirst<A> |
|
||||
| CollectionFlow.cs:241:27:241:30 | access to local variable dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:57:34:60 | dict : Dictionary<T,T> [element, property Key] : A | CollectionFlow.cs:34:66:34:81 | access to property Key : A | CollectionFlow.cs:241:14:241:31 | call to method DictFirstKey<A> |
|
||||
| CollectionFlow.cs:334:23:334:23 | access to local variable a : A | CollectionFlow.cs:328:32:328:38 | element : A | CollectionFlow.cs:328:23:328:27 | array [Return] : A[] [element] : A | CollectionFlow.cs:334:18:334:20 | [post] access to local variable as : A[] [element] : A |
|
||||
| CollectionFlow.cs:337:20:337:22 | access to local variable as : A[] [element] : A | CollectionFlow.cs:22:34:22:35 | ts : A[] [element] : A | CollectionFlow.cs:22:41:22:45 | access to array element : A | CollectionFlow.cs:337:14:337:23 | call to method First<A> |
|
||||
|
|
|
@ -16,10 +16,10 @@ query predicate summaryThroughStep(
|
|||
preservesValue = false
|
||||
}
|
||||
|
||||
query predicate summaryGetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) {
|
||||
query predicate summaryGetterStep(DataFlow::Node arg, DataFlow::Node out, ContentSet c) {
|
||||
FlowSummaryImpl::Private::Steps::summaryGetterStep(arg, c, out, _)
|
||||
}
|
||||
|
||||
query predicate summarySetterStep(DataFlow::Node arg, DataFlow::Node out, Content c) {
|
||||
query predicate summarySetterStep(DataFlow::Node arg, DataFlow::Node out, ContentSet c) {
|
||||
FlowSummaryImpl::Private::Steps::summarySetterStep(arg, c, out, _)
|
||||
}
|
||||
|
|
|
@ -58,4 +58,9 @@ namespace Testing
|
|||
app.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AbstractTestController : Controller
|
||||
{
|
||||
public void MyActionMethod(string param) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,3 +12,4 @@ remoteFlowSources
|
|||
| AspRemoteFlowSource.cs:53:63:53:73 | mapPutParam |
|
||||
| AspRemoteFlowSource.cs:54:69:54:82 | mapDeleteParam |
|
||||
| AspRemoteFlowSource.cs:56:41:56:44 | item |
|
||||
| AspRemoteFlowSource.cs:64:43:64:47 | param |
|
||||
|
|
|
@ -301,14 +301,22 @@ edges
|
|||
| GlobalDataFlow.cs:89:13:89:18 | access to local variable sink17 : String | GlobalDataFlow.cs:90:15:90:20 | access to local variable sink17 | provenance | |
|
||||
| GlobalDataFlow.cs:89:22:89:110 | call to method Aggregate<String,String,String> : String | GlobalDataFlow.cs:89:13:89:18 | access to local variable sink17 : String | provenance | |
|
||||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:89:22:89:110 | call to method Aggregate<String,String,String> : String | provenance | MaD:2 |
|
||||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:89:89:89:89 | s : String | provenance | MaD:2 |
|
||||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:89:104:89:104 | x : String | provenance | MaD:2 |
|
||||
| GlobalDataFlow.cs:89:57:89:66 | { ..., ... } : null [element] : String | GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | provenance | |
|
||||
| GlobalDataFlow.cs:89:59:89:64 | access to local variable sink14 : String | GlobalDataFlow.cs:89:57:89:66 | { ..., ... } : null [element] : String | provenance | |
|
||||
| GlobalDataFlow.cs:89:89:89:89 | s : String | GlobalDataFlow.cs:89:95:89:101 | ... + ... : String | provenance | |
|
||||
| GlobalDataFlow.cs:89:104:89:104 | x : String | GlobalDataFlow.cs:89:109:89:109 | access to parameter x : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | GlobalDataFlow.cs:92:15:92:20 | access to local variable sink18 | provenance | |
|
||||
| GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | GlobalDataFlow.cs:94:24:94:29 | access to local variable sink18 : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | GlobalDataFlow.cs:97:23:97:28 | access to local variable sink18 : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | GlobalDataFlow.cs:100:24:100:29 | access to local variable sink18 : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:22:91:110 | call to method Aggregate<String,String,String> : String | GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | GlobalDataFlow.cs:91:22:91:110 | call to method Aggregate<String,String,String> : String | provenance | MaD:3 |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | GlobalDataFlow.cs:91:84:91:86 | acc : String | provenance | MaD:3 |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | GlobalDataFlow.cs:91:104:91:104 | x : String | provenance | MaD:3 |
|
||||
| GlobalDataFlow.cs:91:84:91:86 | acc : String | GlobalDataFlow.cs:91:95:91:101 | ... + ... : String | provenance | |
|
||||
| GlobalDataFlow.cs:91:104:91:104 | x : String | GlobalDataFlow.cs:91:109:91:109 | access to parameter x : String | provenance | |
|
||||
| GlobalDataFlow.cs:94:24:94:29 | access to local variable sink18 : String | GlobalDataFlow.cs:94:36:94:41 | access to local variable sink21 : Int32 | provenance | MaD:22 |
|
||||
| GlobalDataFlow.cs:94:36:94:41 | access to local variable sink21 : Int32 | GlobalDataFlow.cs:95:15:95:20 | access to local variable sink21 | provenance | |
|
||||
| GlobalDataFlow.cs:97:23:97:28 | access to local variable sink18 : String | GlobalDataFlow.cs:97:35:97:40 | access to local variable sink22 : Boolean | provenance | MaD:20 |
|
||||
|
@ -788,10 +796,18 @@ nodes
|
|||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | semmle.label | (...) ... : null [element] : String |
|
||||
| GlobalDataFlow.cs:89:57:89:66 | { ..., ... } : null [element] : String | semmle.label | { ..., ... } : null [element] : String |
|
||||
| GlobalDataFlow.cs:89:59:89:64 | access to local variable sink14 : String | semmle.label | access to local variable sink14 : String |
|
||||
| GlobalDataFlow.cs:89:89:89:89 | s : String | semmle.label | s : String |
|
||||
| GlobalDataFlow.cs:89:95:89:101 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| GlobalDataFlow.cs:89:104:89:104 | x : String | semmle.label | x : String |
|
||||
| GlobalDataFlow.cs:89:109:89:109 | access to parameter x : String | semmle.label | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:90:15:90:20 | access to local variable sink17 | semmle.label | access to local variable sink17 |
|
||||
| GlobalDataFlow.cs:91:13:91:18 | access to local variable sink18 : String | semmle.label | access to local variable sink18 : String |
|
||||
| GlobalDataFlow.cs:91:22:91:110 | call to method Aggregate<String,String,String> : String | semmle.label | call to method Aggregate<String,String,String> : String |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | semmle.label | access to local variable sink14 : String |
|
||||
| GlobalDataFlow.cs:91:84:91:86 | acc : String | semmle.label | acc : String |
|
||||
| GlobalDataFlow.cs:91:95:91:101 | ... + ... : String | semmle.label | ... + ... : String |
|
||||
| GlobalDataFlow.cs:91:104:91:104 | x : String | semmle.label | x : String |
|
||||
| GlobalDataFlow.cs:91:109:91:109 | access to parameter x : String | semmle.label | access to parameter x : String |
|
||||
| GlobalDataFlow.cs:92:15:92:20 | access to local variable sink18 | semmle.label | access to local variable sink18 |
|
||||
| GlobalDataFlow.cs:94:24:94:29 | access to local variable sink18 : String | semmle.label | access to local variable sink18 : String |
|
||||
| GlobalDataFlow.cs:94:36:94:41 | access to local variable sink21 : Int32 | semmle.label | access to local variable sink21 : Int32 |
|
||||
|
@ -1102,6 +1118,10 @@ subpaths
|
|||
| GlobalDataFlow.cs:83:23:83:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:315:31:315:40 | sinkParam8 : String | GlobalDataFlow.cs:318:16:318:25 | access to parameter sinkParam8 : String | GlobalDataFlow.cs:83:22:83:87 | call to method Select<String,String> : IEnumerable<T> [element] : String |
|
||||
| GlobalDataFlow.cs:85:23:85:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:85:118:85:118 | x : String | GlobalDataFlow.cs:85:127:85:127 | access to parameter x : String | GlobalDataFlow.cs:85:22:85:128 | call to method Zip<String,String,String> : IEnumerable<T> [element] : String |
|
||||
| GlobalDataFlow.cs:87:70:87:113 | (...) ... : null [element] : String | GlobalDataFlow.cs:87:121:87:121 | y : String | GlobalDataFlow.cs:87:127:87:127 | access to parameter y : String | GlobalDataFlow.cs:87:22:87:128 | call to method Zip<String,String,String> : IEnumerable<T> [element] : String |
|
||||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:89:89:89:89 | s : String | GlobalDataFlow.cs:89:95:89:101 | ... + ... : String | GlobalDataFlow.cs:89:22:89:110 | call to method Aggregate<String,String,String> : String |
|
||||
| GlobalDataFlow.cs:89:23:89:66 | (...) ... : null [element] : String | GlobalDataFlow.cs:89:104:89:104 | x : String | GlobalDataFlow.cs:89:109:89:109 | access to parameter x : String | GlobalDataFlow.cs:89:22:89:110 | call to method Aggregate<String,String,String> : String |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | GlobalDataFlow.cs:91:84:91:86 | acc : String | GlobalDataFlow.cs:91:95:91:101 | ... + ... : String | GlobalDataFlow.cs:91:22:91:110 | call to method Aggregate<String,String,String> : String |
|
||||
| GlobalDataFlow.cs:91:75:91:80 | access to local variable sink14 : String | GlobalDataFlow.cs:91:104:91:104 | x : String | GlobalDataFlow.cs:91:109:91:109 | access to parameter x : String | GlobalDataFlow.cs:91:22:91:110 | call to method Aggregate<String,String,String> : String |
|
||||
| GlobalDataFlow.cs:138:63:138:63 | access to parameter x : String | GlobalDataFlow.cs:387:46:387:46 | x : String | GlobalDataFlow.cs:389:16:389:19 | delegate call : String | GlobalDataFlow.cs:138:45:138:64 | call to method ApplyFunc<String,String> : String |
|
||||
| GlobalDataFlow.cs:139:29:139:33 | access to local variable sink3 : String | GlobalDataFlow.cs:138:40:138:40 | x : String | GlobalDataFlow.cs:138:45:138:64 | call to method ApplyFunc<String,String> : String | GlobalDataFlow.cs:139:21:139:34 | delegate call : String |
|
||||
| GlobalDataFlow.cs:147:39:147:43 | access to local variable sink4 : String | GlobalDataFlow.cs:387:46:387:46 | x : String | GlobalDataFlow.cs:389:16:389:19 | delegate call : String | GlobalDataFlow.cs:147:21:147:44 | call to method ApplyFunc<String,String> : String |
|
||||
|
|
|
@ -56,6 +56,15 @@ public class HomeController5 : HomeController4
|
|||
}
|
||||
}
|
||||
|
||||
// is abstract
|
||||
public abstract class HomeController6 : Controller
|
||||
{
|
||||
public string Index()
|
||||
{
|
||||
return "This is Home Controller";
|
||||
}
|
||||
}
|
||||
|
||||
// is not public
|
||||
internal class NotHomeController : Controller
|
||||
{
|
||||
|
@ -65,17 +74,8 @@ internal class NotHomeController : Controller
|
|||
}
|
||||
}
|
||||
|
||||
// is abstract
|
||||
public abstract class NotHomeController2 : Controller
|
||||
{
|
||||
public string Index()
|
||||
{
|
||||
return "This is Home Controller";
|
||||
}
|
||||
}
|
||||
|
||||
// contains generic parameters
|
||||
public class NotHomeController3<T> : Controller
|
||||
public class NotHomeController2<T> : Controller
|
||||
{
|
||||
public string Index()
|
||||
{
|
||||
|
@ -85,7 +85,7 @@ public class NotHomeController3<T> : Controller
|
|||
|
||||
// has [NonController] attribute
|
||||
[NonController]
|
||||
public class NotHomeController4 : Controller
|
||||
public class NotHomeController3 : Controller
|
||||
{
|
||||
public string Index()
|
||||
{
|
||||
|
@ -94,10 +94,10 @@ public class NotHomeController4 : Controller
|
|||
}
|
||||
|
||||
// derived from a class that has [NonController] attribute
|
||||
public class NotController : NotHomeController4
|
||||
public class NotController : NotHomeController3
|
||||
{
|
||||
public string Index()
|
||||
{
|
||||
return "This is Home Controller";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
| AspNetCore.cs:32:14:32:28 | HomeController3 |
|
||||
| AspNetCore.cs:42:14:42:28 | HomeController4 |
|
||||
| AspNetCore.cs:51:14:51:28 | HomeController5 |
|
||||
| AspNetCore.cs:60:23:60:37 | HomeController6 |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | true |
|
||||
| Partial.cs:5:17:5:23 | Method2 | false |
|
||||
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:11:17:11:23 | Method3 | false |
|
||||
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | true |
|
||||
| Partial.cs:17:17:17:23 | Method4 | false |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
| Partial.cs:1:15:1:26 | TwoPartClass |
|
||||
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass |
|
||||
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:14:15:14:33 | OnePartPartialClass |
|
||||
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
|
||||
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:1:15:1:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:3:18:3:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:5:17:5:23 | Method2 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:10:18:10:39 | PartialMethodWithBody1 |
|
||||
| Partial.cs:8:15:8:26 | TwoPartClass | Partial.cs:11:17:11:23 | Method3 |
|
||||
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 |
|
||||
| Partial.cs:14:15:14:33 | OnePartPartialClass | Partial.cs:17:17:17:23 | Method4 |
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
| Partial.cs:3:18:3:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:4:18:4:42 | PartialMethodWithoutBody1 | false |
|
||||
| Partial.cs:10:18:10:39 | PartialMethodWithBody1 | true |
|
||||
| Partial.cs:16:18:16:42 | PartialMethodWithoutBody2 | false |
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
Partial.cs:
|
||||
# 1| [Class] TwoPartClass
|
||||
# 3| 5: [Method] PartialMethodWithBody1
|
||||
# 3| -1: [TypeMention] Void
|
||||
# 10| 4: [BlockStmt] {...}
|
||||
# 4| 6: [Method] PartialMethodWithoutBody1
|
||||
# 4| 5: [Method] PartialMethodWithoutBody1
|
||||
# 4| -1: [TypeMention] Void
|
||||
# 5| 7: [Method] Method2
|
||||
# 5| 6: [Method] Method2
|
||||
# 5| -1: [TypeMention] Void
|
||||
# 5| 4: [BlockStmt] {...}
|
||||
# 10| 7: [Method] PartialMethodWithBody1
|
||||
# 3| -1: [TypeMention] Void
|
||||
# 10| 4: [BlockStmt] {...}
|
||||
# 11| 8: [Method] Method3
|
||||
# 11| -1: [TypeMention] Void
|
||||
# 11| 4: [BlockStmt] {...}
|
||||
|
|
|
@ -10,7 +10,12 @@ namespace Test
|
|||
using System.Data;
|
||||
using System.Data.Entity;
|
||||
using System.Data.SqlClient;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.UI.WebControls;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
public class EntityFrameworkContext : DbContext
|
||||
{
|
||||
|
@ -110,4 +115,28 @@ namespace Test
|
|||
|
||||
System.Windows.Forms.TextBox box1;
|
||||
}
|
||||
|
||||
public abstract class MyController : Controller
|
||||
{
|
||||
[HttpPost("{userId:string}")]
|
||||
public async Task<IActionResult> GetUserById([FromRoute] string userId, CancellationToken cancellationToken)
|
||||
{
|
||||
// This is a vulnerable method due to SQL injection
|
||||
string query = "SELECT * FROM Users WHERE UserId = '" + userId + "'";
|
||||
|
||||
using (SqlConnection connection = new SqlConnection("YourConnectionString"))
|
||||
{
|
||||
SqlCommand command = new SqlCommand(query, connection);
|
||||
connection.Open();
|
||||
|
||||
SqlDataReader reader = command.ExecuteReader();
|
||||
while (reader.Read())
|
||||
{
|
||||
Console.WriteLine(String.Format("{0}, {1}", reader["UserId"], reader["Username"]));
|
||||
}
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#select
|
||||
| SecondOrderSqlInjection.cs:25:71:25:145 | ... + ... | SecondOrderSqlInjection.cs:20:48:20:78 | call to method ExecuteReader : SqlDataReader | SecondOrderSqlInjection.cs:25:71:25:145 | ... + ... | This query depends on $@. | SecondOrderSqlInjection.cs:20:48:20:78 | call to method ExecuteReader : SqlDataReader | this database input |
|
||||
| SecondOrderSqlInjection.cs:45:57:45:59 | access to local variable sql | SecondOrderSqlInjection.cs:33:36:33:78 | object creation of type FileStream : FileStream | SecondOrderSqlInjection.cs:45:57:45:59 | access to local variable sql | This query depends on $@. | SecondOrderSqlInjection.cs:33:36:33:78 | object creation of type FileStream : FileStream | this file stream |
|
||||
| SqlInjection.cs:34:50:34:55 | access to local variable query1 | SqlInjection.cs:33:21:33:35 | access to field categoryTextBox : TextBox | SqlInjection.cs:34:50:34:55 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:33:21:33:35 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:69:56:69:61 | access to local variable query1 | SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:69:56:69:61 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:70:55:70:60 | access to local variable query1 | SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:70:55:70:60 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:83:50:83:55 | access to local variable query1 | SqlInjection.cs:82:21:82:29 | access to property Text : String | SqlInjection.cs:83:50:83:55 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:82:21:82:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:93:42:93:52 | access to local variable queryString | SqlInjection.cs:92:21:92:29 | access to property Text : String | SqlInjection.cs:93:42:93:52 | access to local variable queryString | This query depends on $@. | SqlInjection.cs:92:21:92:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:94:50:94:52 | access to local variable cmd | SqlInjection.cs:92:21:92:29 | access to property Text : String | SqlInjection.cs:94:50:94:52 | access to local variable cmd | This query depends on $@. | SqlInjection.cs:92:21:92:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:104:42:104:52 | access to local variable queryString | SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | SqlInjection.cs:104:42:104:52 | access to local variable queryString | This query depends on $@. | SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | this read from stdin |
|
||||
| SqlInjection.cs:105:50:105:52 | access to local variable cmd | SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | SqlInjection.cs:105:50:105:52 | access to local variable cmd | This query depends on $@. | SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | this read from stdin |
|
||||
| SqlInjection.cs:39:50:39:55 | access to local variable query1 | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | SqlInjection.cs:39:50:39:55 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
|
||||
| SqlInjection.cs:88:50:88:55 | access to local variable query1 | SqlInjection.cs:87:21:87:29 | access to property Text : String | SqlInjection.cs:88:50:88:55 | access to local variable query1 | This query depends on $@. | SqlInjection.cs:87:21:87:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:98:42:98:52 | access to local variable queryString | SqlInjection.cs:97:21:97:29 | access to property Text : String | SqlInjection.cs:98:42:98:52 | access to local variable queryString | This query depends on $@. | SqlInjection.cs:97:21:97:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:99:50:99:52 | access to local variable cmd | SqlInjection.cs:97:21:97:29 | access to property Text : String | SqlInjection.cs:99:50:99:52 | access to local variable cmd | This query depends on $@. | SqlInjection.cs:97:21:97:29 | access to property Text : String | this TextBox text |
|
||||
| SqlInjection.cs:109:42:109:52 | access to local variable queryString | SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | SqlInjection.cs:109:42:109:52 | access to local variable queryString | This query depends on $@. | SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | this read from stdin |
|
||||
| SqlInjection.cs:110:50:110:52 | access to local variable cmd | SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | SqlInjection.cs:110:50:110:52 | access to local variable cmd | This query depends on $@. | SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | this read from stdin |
|
||||
| SqlInjection.cs:129:53:129:57 | access to local variable query | SqlInjection.cs:122:73:122:78 | userId : String | SqlInjection.cs:129:53:129:57 | access to local variable query | This query depends on $@. | SqlInjection.cs:122:73:122:78 | userId : String | this ASP.NET Core MVC action method parameter |
|
||||
| SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | This query depends on $@. | SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | this TextBox text |
|
||||
| SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | This query depends on $@. | SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | this TextBox text |
|
||||
| SqlInjectionDapper.cs:39:63:39:67 | access to local variable query | SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | SqlInjectionDapper.cs:39:63:39:67 | access to local variable query | This query depends on $@. | SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | this TextBox text |
|
||||
|
@ -40,27 +41,29 @@ edges
|
|||
| SecondOrderSqlInjection.cs:40:25:40:27 | access to local variable sql : String | SecondOrderSqlInjection.cs:45:57:45:59 | access to local variable sql | provenance | Sink:MaD:10 |
|
||||
| SecondOrderSqlInjection.cs:40:31:40:33 | access to local variable sql : String | SecondOrderSqlInjection.cs:40:31:40:40 | call to method Trim : String | provenance | MaD:28 |
|
||||
| SecondOrderSqlInjection.cs:40:31:40:40 | call to method Trim : String | SecondOrderSqlInjection.cs:40:25:40:27 | access to local variable sql : String | provenance | |
|
||||
| SqlInjection.cs:32:21:32:26 | access to local variable query1 : String | SqlInjection.cs:34:50:34:55 | access to local variable query1 | provenance | Sink:MaD:18 |
|
||||
| SqlInjection.cs:33:21:33:35 | access to field categoryTextBox : TextBox | SqlInjection.cs:33:21:33:40 | access to property Text : String | provenance | MaD:26 |
|
||||
| SqlInjection.cs:33:21:33:40 | access to property Text : String | SqlInjection.cs:32:21:32:26 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:67:25:67:30 | access to local variable query1 : String | SqlInjection.cs:69:56:69:61 | access to local variable query1 | provenance | Sink:MaD:7 |
|
||||
| SqlInjection.cs:67:25:67:30 | access to local variable query1 : String | SqlInjection.cs:70:55:70:60 | access to local variable query1 | provenance | Sink:MaD:8 |
|
||||
| SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:68:33:68:52 | access to property Text : String | provenance | MaD:26 |
|
||||
| SqlInjection.cs:68:33:68:52 | access to property Text : String | SqlInjection.cs:67:25:67:30 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:81:21:81:26 | access to local variable query1 : String | SqlInjection.cs:83:50:83:55 | access to local variable query1 | provenance | Sink:MaD:18 |
|
||||
| SqlInjection.cs:82:21:82:29 | access to property Text : String | SqlInjection.cs:81:21:81:26 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:91:21:91:31 | access to local variable queryString : String | SqlInjection.cs:93:42:93:52 | access to local variable queryString | provenance | Sink:MaD:15 |
|
||||
| SqlInjection.cs:91:21:91:31 | access to local variable queryString : String | SqlInjection.cs:93:42:93:52 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:92:21:92:29 | access to property Text : String | SqlInjection.cs:91:21:91:31 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:93:21:93:23 | access to local variable cmd : SqlCommand | SqlInjection.cs:94:50:94:52 | access to local variable cmd | provenance | Sink:MaD:17 |
|
||||
| SqlInjection.cs:93:27:93:53 | object creation of type SqlCommand : SqlCommand | SqlInjection.cs:93:21:93:23 | access to local variable cmd : SqlCommand | provenance | |
|
||||
| SqlInjection.cs:93:42:93:52 | access to local variable queryString : String | SqlInjection.cs:93:27:93:53 | object creation of type SqlCommand : SqlCommand | provenance | MaD:19 |
|
||||
| SqlInjection.cs:102:21:102:31 | access to local variable queryString : String | SqlInjection.cs:104:42:104:52 | access to local variable queryString | provenance | Sink:MaD:15 |
|
||||
| SqlInjection.cs:102:21:102:31 | access to local variable queryString : String | SqlInjection.cs:104:42:104:52 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | SqlInjection.cs:102:21:102:31 | access to local variable queryString : String | provenance | Src:MaD:27 |
|
||||
| SqlInjection.cs:104:21:104:23 | access to local variable cmd : SqlCommand | SqlInjection.cs:105:50:105:52 | access to local variable cmd | provenance | Sink:MaD:17 |
|
||||
| SqlInjection.cs:104:27:104:53 | object creation of type SqlCommand : SqlCommand | SqlInjection.cs:104:21:104:23 | access to local variable cmd : SqlCommand | provenance | |
|
||||
| SqlInjection.cs:104:42:104:52 | access to local variable queryString : String | SqlInjection.cs:104:27:104:53 | object creation of type SqlCommand : SqlCommand | provenance | MaD:19 |
|
||||
| SqlInjection.cs:37:21:37:26 | access to local variable query1 : String | SqlInjection.cs:39:50:39:55 | access to local variable query1 | provenance | Sink:MaD:18 |
|
||||
| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | SqlInjection.cs:38:21:38:40 | access to property Text : String | provenance | MaD:26 |
|
||||
| SqlInjection.cs:38:21:38:40 | access to property Text : String | SqlInjection.cs:37:21:37:26 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:72:25:72:30 | access to local variable query1 : String | SqlInjection.cs:74:56:74:61 | access to local variable query1 | provenance | Sink:MaD:7 |
|
||||
| SqlInjection.cs:72:25:72:30 | access to local variable query1 : String | SqlInjection.cs:75:55:75:60 | access to local variable query1 | provenance | Sink:MaD:8 |
|
||||
| SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:73:33:73:52 | access to property Text : String | provenance | MaD:26 |
|
||||
| SqlInjection.cs:73:33:73:52 | access to property Text : String | SqlInjection.cs:72:25:72:30 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:86:21:86:26 | access to local variable query1 : String | SqlInjection.cs:88:50:88:55 | access to local variable query1 | provenance | Sink:MaD:18 |
|
||||
| SqlInjection.cs:87:21:87:29 | access to property Text : String | SqlInjection.cs:86:21:86:26 | access to local variable query1 : String | provenance | |
|
||||
| SqlInjection.cs:96:21:96:31 | access to local variable queryString : String | SqlInjection.cs:98:42:98:52 | access to local variable queryString | provenance | Sink:MaD:15 |
|
||||
| SqlInjection.cs:96:21:96:31 | access to local variable queryString : String | SqlInjection.cs:98:42:98:52 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:97:21:97:29 | access to property Text : String | SqlInjection.cs:96:21:96:31 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:98:21:98:23 | access to local variable cmd : SqlCommand | SqlInjection.cs:99:50:99:52 | access to local variable cmd | provenance | Sink:MaD:17 |
|
||||
| SqlInjection.cs:98:27:98:53 | object creation of type SqlCommand : SqlCommand | SqlInjection.cs:98:21:98:23 | access to local variable cmd : SqlCommand | provenance | |
|
||||
| SqlInjection.cs:98:42:98:52 | access to local variable queryString : String | SqlInjection.cs:98:27:98:53 | object creation of type SqlCommand : SqlCommand | provenance | MaD:19 |
|
||||
| SqlInjection.cs:107:21:107:31 | access to local variable queryString : String | SqlInjection.cs:109:42:109:52 | access to local variable queryString | provenance | Sink:MaD:15 |
|
||||
| SqlInjection.cs:107:21:107:31 | access to local variable queryString : String | SqlInjection.cs:109:42:109:52 | access to local variable queryString : String | provenance | |
|
||||
| SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | SqlInjection.cs:107:21:107:31 | access to local variable queryString : String | provenance | Src:MaD:27 |
|
||||
| SqlInjection.cs:109:21:109:23 | access to local variable cmd : SqlCommand | SqlInjection.cs:110:50:110:52 | access to local variable cmd | provenance | Sink:MaD:17 |
|
||||
| SqlInjection.cs:109:27:109:53 | object creation of type SqlCommand : SqlCommand | SqlInjection.cs:109:21:109:23 | access to local variable cmd : SqlCommand | provenance | |
|
||||
| SqlInjection.cs:109:42:109:52 | access to local variable queryString : String | SqlInjection.cs:109:27:109:53 | object creation of type SqlCommand : SqlCommand | provenance | MaD:19 |
|
||||
| SqlInjection.cs:122:73:122:78 | userId : String | SqlInjection.cs:125:20:125:24 | access to local variable query : String | provenance | |
|
||||
| SqlInjection.cs:125:20:125:24 | access to local variable query : String | SqlInjection.cs:129:53:129:57 | access to local variable query | provenance | Sink:MaD:16 |
|
||||
| SqlInjectionDapper.cs:20:21:20:25 | access to local variable query : String | SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | provenance | Sink:MaD:4 |
|
||||
| SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | SqlInjectionDapper.cs:20:21:20:25 | access to local variable query : String | provenance | |
|
||||
| SqlInjectionDapper.cs:29:21:29:25 | access to local variable query : String | SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | provenance | Sink:MaD:5 |
|
||||
|
@ -144,32 +147,35 @@ nodes
|
|||
| SecondOrderSqlInjection.cs:40:31:40:33 | access to local variable sql : String | semmle.label | access to local variable sql : String |
|
||||
| SecondOrderSqlInjection.cs:40:31:40:40 | call to method Trim : String | semmle.label | call to method Trim : String |
|
||||
| SecondOrderSqlInjection.cs:45:57:45:59 | access to local variable sql | semmle.label | access to local variable sql |
|
||||
| SqlInjection.cs:32:21:32:26 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:33:21:33:35 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
|
||||
| SqlInjection.cs:33:21:33:40 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:34:50:34:55 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:67:25:67:30 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:68:33:68:47 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
|
||||
| SqlInjection.cs:68:33:68:52 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:69:56:69:61 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:70:55:70:60 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:81:21:81:26 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:82:21:82:29 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:83:50:83:55 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:91:21:91:31 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:92:21:92:29 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:93:21:93:23 | access to local variable cmd : SqlCommand | semmle.label | access to local variable cmd : SqlCommand |
|
||||
| SqlInjection.cs:93:27:93:53 | object creation of type SqlCommand : SqlCommand | semmle.label | object creation of type SqlCommand : SqlCommand |
|
||||
| SqlInjection.cs:93:42:93:52 | access to local variable queryString | semmle.label | access to local variable queryString |
|
||||
| SqlInjection.cs:93:42:93:52 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:94:50:94:52 | access to local variable cmd | semmle.label | access to local variable cmd |
|
||||
| SqlInjection.cs:102:21:102:31 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:103:21:103:38 | call to method ReadLine : String | semmle.label | call to method ReadLine : String |
|
||||
| SqlInjection.cs:104:21:104:23 | access to local variable cmd : SqlCommand | semmle.label | access to local variable cmd : SqlCommand |
|
||||
| SqlInjection.cs:104:27:104:53 | object creation of type SqlCommand : SqlCommand | semmle.label | object creation of type SqlCommand : SqlCommand |
|
||||
| SqlInjection.cs:104:42:104:52 | access to local variable queryString | semmle.label | access to local variable queryString |
|
||||
| SqlInjection.cs:104:42:104:52 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:105:50:105:52 | access to local variable cmd | semmle.label | access to local variable cmd |
|
||||
| SqlInjection.cs:37:21:37:26 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
|
||||
| SqlInjection.cs:38:21:38:40 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:39:50:39:55 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:72:25:72:30 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
|
||||
| SqlInjection.cs:73:33:73:52 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:74:56:74:61 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:75:55:75:60 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:86:21:86:26 | access to local variable query1 : String | semmle.label | access to local variable query1 : String |
|
||||
| SqlInjection.cs:87:21:87:29 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:88:50:88:55 | access to local variable query1 | semmle.label | access to local variable query1 |
|
||||
| SqlInjection.cs:96:21:96:31 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:97:21:97:29 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjection.cs:98:21:98:23 | access to local variable cmd : SqlCommand | semmle.label | access to local variable cmd : SqlCommand |
|
||||
| SqlInjection.cs:98:27:98:53 | object creation of type SqlCommand : SqlCommand | semmle.label | object creation of type SqlCommand : SqlCommand |
|
||||
| SqlInjection.cs:98:42:98:52 | access to local variable queryString | semmle.label | access to local variable queryString |
|
||||
| SqlInjection.cs:98:42:98:52 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:99:50:99:52 | access to local variable cmd | semmle.label | access to local variable cmd |
|
||||
| SqlInjection.cs:107:21:107:31 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:108:21:108:38 | call to method ReadLine : String | semmle.label | call to method ReadLine : String |
|
||||
| SqlInjection.cs:109:21:109:23 | access to local variable cmd : SqlCommand | semmle.label | access to local variable cmd : SqlCommand |
|
||||
| SqlInjection.cs:109:27:109:53 | object creation of type SqlCommand : SqlCommand | semmle.label | object creation of type SqlCommand : SqlCommand |
|
||||
| SqlInjection.cs:109:42:109:52 | access to local variable queryString | semmle.label | access to local variable queryString |
|
||||
| SqlInjection.cs:109:42:109:52 | access to local variable queryString : String | semmle.label | access to local variable queryString : String |
|
||||
| SqlInjection.cs:110:50:110:52 | access to local variable cmd | semmle.label | access to local variable cmd |
|
||||
| SqlInjection.cs:122:73:122:78 | userId : String | semmle.label | userId : String |
|
||||
| SqlInjection.cs:125:20:125:24 | access to local variable query : String | semmle.label | access to local variable query : String |
|
||||
| SqlInjection.cs:129:53:129:57 | access to local variable query | semmle.label | access to local variable query |
|
||||
| SqlInjectionDapper.cs:20:21:20:25 | access to local variable query : String | semmle.label | access to local variable query : String |
|
||||
| SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | semmle.label | access to property Text : String |
|
||||
| SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | semmle.label | access to local variable query |
|
||||
|
|
|
@ -3,3 +3,4 @@ semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resour
|
|||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SqlClient/4.8.5/System.Data.SqlClient.csproj
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/System.Data.SQLite/1.0.118/System.Data.SQLite.csproj
|
||||
semmle-extractor-options: ${testdir}/../../../resources/stubs/System.Windows.cs
|
||||
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.App.csproj
|
||||
|
|
|
@ -12,13 +12,11 @@ edges
|
|||
| InsecureRandomness.cs:29:57:29:60 | access to local variable data : Byte[] [element] : Byte | InsecureRandomness.cs:29:27:29:61 | call to method GetString : String | provenance | MaD:1 |
|
||||
| InsecureRandomness.cs:31:16:31:21 | access to local variable result : StringBuilder | InsecureRandomness.cs:31:16:31:32 | call to method ToString : String | provenance | MaD:3 |
|
||||
| InsecureRandomness.cs:31:16:31:32 | call to method ToString : String | InsecureRandomness.cs:12:27:12:50 | call to method InsecureRandomString | provenance | |
|
||||
| InsecureRandomness.cs:60:13:60:18 | access to local variable result : String | InsecureRandomness.cs:60:13:60:18 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:60:13:60:18 | access to local variable result : String | InsecureRandomness.cs:62:16:62:21 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:60:23:60:40 | access to array element : String | InsecureRandomness.cs:60:13:60:18 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:60:31:60:39 | call to method Next : Int32 | InsecureRandomness.cs:60:23:60:40 | access to array element : String | provenance | Config |
|
||||
| InsecureRandomness.cs:62:16:62:21 | access to local variable result : String | InsecureRandomness.cs:62:16:62:32 | call to method ToString : String | provenance | MaD:4 |
|
||||
| InsecureRandomness.cs:62:16:62:32 | call to method ToString : String | InsecureRandomness.cs:13:20:13:56 | call to method InsecureRandomStringFromSelection | provenance | |
|
||||
| InsecureRandomness.cs:72:13:72:18 | access to local variable result : String | InsecureRandomness.cs:72:13:72:18 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:72:13:72:18 | access to local variable result : String | InsecureRandomness.cs:74:16:74:21 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:72:23:72:40 | access to indexer : String | InsecureRandomness.cs:72:13:72:18 | access to local variable result : String | provenance | |
|
||||
| InsecureRandomness.cs:72:31:72:39 | call to method Next : Int32 | InsecureRandomness.cs:72:23:72:40 | access to indexer : String | provenance | Config |
|
||||
|
|
|
@ -47,6 +47,7 @@ codeql_pkg_files(
|
|||
"//go/extractor/cli/go-autobuilder",
|
||||
"//go/extractor/cli/go-bootstrap",
|
||||
"//go/extractor/cli/go-build-runner",
|
||||
"//go/extractor/cli/go-configure-baseline",
|
||||
"//go/extractor/cli/go-extractor",
|
||||
"//go/extractor/cli/go-gen-dbscheme",
|
||||
"//go/extractor/cli/go-tokenizer",
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"paths-ignore": []
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"paths-ignore": [
|
||||
"vendor/**"
|
||||
]
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
@echo off
|
||||
if exist vendor\modules.txt (
|
||||
type "%CODEQL_EXTRACTOR_GO_ROOT%\tools\baseline-config-vendor.json"
|
||||
) else (
|
||||
type "%CODEQL_EXTRACTOR_GO_ROOT%\tools\baseline-config-empty.json"
|
||||
)
|
||||
|
||||
type NUL && "%CODEQL_EXTRACTOR_GO_ROOT%/tools/%CODEQL_PLATFORM%/go-configure-baseline.exe"
|
||||
exit /b %ERRORLEVEL%
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
if [ -f vendor/modules.txt ]; then
|
||||
cat "$CODEQL_EXTRACTOR_GO_ROOT/tools/baseline-config-vendor.json"
|
||||
else
|
||||
cat "$CODEQL_EXTRACTOR_GO_ROOT/tools/baseline-config-empty.json"
|
||||
fi
|
||||
"$CODEQL_EXTRACTOR_GO_ROOT/tools/$CODEQL_PLATFORM/go-configure-baseline"
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
# generated running `bazel run //go/gazelle`, do not edit
|
||||
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
load("//go:rules.bzl", "codeql_go_binary")
|
||||
|
||||
go_library(
|
||||
name = "go-configure-baseline_lib",
|
||||
srcs = ["go-configure-baseline.go"],
|
||||
importpath = "github.com/github/codeql-go/extractor/cli/go-configure-baseline",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["//go/extractor/configurebaseline"],
|
||||
)
|
||||
|
||||
codeql_go_binary(
|
||||
name = "go-configure-baseline",
|
||||
embed = [":go-configure-baseline_lib"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
|
@ -0,0 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/github/codeql-go/extractor/configurebaseline"
|
||||
)
|
||||
|
||||
func main() {
|
||||
jsonResult, err := configurebaseline.GetConfigBaselineAsJSON(".")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
} else {
|
||||
fmt.Println(string(jsonResult))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
# generated running `bazel run //go/gazelle`, do not edit
|
||||
|
||||
load("@rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "configurebaseline",
|
||||
srcs = ["configurebaseline.go"],
|
||||
importpath = "github.com/github/codeql-go/extractor/configurebaseline",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//go/extractor/util"],
|
||||
)
|
|
@ -0,0 +1,52 @@
|
|||
package configurebaseline
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/github/codeql-go/extractor/util"
|
||||
)
|
||||
|
||||
func fileExists(path string) bool {
|
||||
stat, err := os.Stat(path)
|
||||
return err == nil && stat.Mode().IsRegular()
|
||||
}
|
||||
|
||||
// Decides if `dirPath` is a vendor directory by testing whether it is called `vendor`
|
||||
// and contains a `modules.txt` file.
|
||||
func isGolangVendorDirectory(dirPath string) bool {
|
||||
return filepath.Base(dirPath) == "vendor" && fileExists(filepath.Join(dirPath, "modules.txt"))
|
||||
}
|
||||
|
||||
type BaselineConfig struct {
|
||||
PathsIgnore []string `json:"paths-ignore"`
|
||||
}
|
||||
|
||||
func GetConfigBaselineAsJSON(rootDir string) ([]byte, error) {
|
||||
vendorDirs := make([]string, 0)
|
||||
|
||||
if util.IsVendorDirExtractionEnabled() {
|
||||
// The user wants vendor directories scanned; emit an empty report.
|
||||
} else {
|
||||
filepath.WalkDir(rootDir, func(dirPath string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
// Ignore any unreadable paths -- if this script can't see it, very likely
|
||||
// it will not be extracted either.
|
||||
return nil
|
||||
}
|
||||
if isGolangVendorDirectory(dirPath) {
|
||||
// Note that CodeQL expects a forward-slash-separated path, even on Windows.
|
||||
vendorDirs = append(vendorDirs, path.Join(filepath.ToSlash(dirPath), "**"))
|
||||
return filepath.SkipDir
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
outputStruct := BaselineConfig{PathsIgnore: vendorDirs}
|
||||
return json.Marshal(outputStruct)
|
||||
}
|
|
@ -199,7 +199,7 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error {
|
|||
|
||||
// If CODEQL_EXTRACTOR_GO_EXTRACT_VENDOR_DIRS is "true", we extract `vendor` directories;
|
||||
// otherwise (the default) is to exclude them from extraction
|
||||
includeVendor := os.Getenv("CODEQL_EXTRACTOR_GO_EXTRACT_VENDOR_DIRS") == "true"
|
||||
includeVendor := util.IsVendorDirExtractionEnabled()
|
||||
if !includeVendor {
|
||||
excludedDirs = append(excludedDirs, "vendor")
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ load("@rules_go//go:def.bzl", "go_library", "go_test")
|
|||
go_library(
|
||||
name = "util",
|
||||
srcs = [
|
||||
"extractvendordirs.go",
|
||||
"semver.go",
|
||||
"util.go",
|
||||
],
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func IsVendorDirExtractionEnabled() bool {
|
||||
return os.Getenv("CODEQL_EXTRACTOR_GO_EXTRACT_VENDOR_DIRS") == "true"
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче