Merge branch 'main' into henrymercer/rc-3.15-mergeback

This commit is contained in:
Henry Mercer 2024-08-29 19:48:01 +01:00
Родитель d5bccd5373 72e2910d17
Коммит 3490067316
927 изменённых файлов: 15314 добавлений и 11766 удалений

Просмотреть файл

@ -1 +1 @@
7.2.1
5f5d70b6c4d2fb1a889479569107f1692239e8a7

2
.github/workflows/buildifier.yml поставляемый
Просмотреть файл

@ -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
)

4
.github/workflows/cpp-swift-analysis.yml поставляемый
Просмотреть файл

@ -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

2
.gitignore поставляемый
Просмотреть файл

@ -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"

18
go/extractor/cli/go-configure-baseline/BUILD.bazel сгенерированный Normal file
Просмотреть файл

@ -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))
}
}

11
go/extractor/configurebaseline/BUILD.bazel сгенерированный Normal file
Просмотреть файл

@ -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")
}

1
go/extractor/util/BUILD.bazel сгенерированный
Просмотреть файл

@ -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"
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше