Compare commits

..

79 Commits

Author SHA1 Message Date
Calum Grant
60076dc8a8 C++: Remove potential FPs from cpp/integer-multiplication-cast-to-long in BMN 2025-01-23 19:45:44 +00:00
Calum Grant
d3e469f989 C++: Test for buildless IntMultToLong 2025-01-23 16:50:03 +00:00
Anders Schack-Mulligen
5bfd22e60a Merge pull request #18552 from aschackmull/java/xss-regex-perf
Java: Improve performance of XSS regex.
2025-01-22 11:28:49 +01:00
Jeroen Ketema
7fa9167ef9 Merge pull request #18553 from jketema/preprocblock
C++: Update `PreprocBlock.qll` QLDoc and add C++23 test
2025-01-22 10:31:51 +01:00
Asger F
f845ac1dd8 Merge pull request #18550 from asgerf/js/vue-ts-notsconfig
JS: Avoid inconsistent DB when embedded TS has no associated tsconfig.json
2025-01-22 09:51:06 +01:00
Erik Krogh Kristensen
f183bc9a65 Merge pull request #18557 from erik-krogh/ts57
JS: update missing TS support doc
2025-01-21 23:13:31 +01:00
erik-krogh
28dd2ca83c update missing TS support doc 2025-01-21 22:27:57 +01:00
Jeroen Ketema
442dad4ff9 C++: Update PreprocBlock.qll QLDoc and add C++23 test 2025-01-21 18:02:28 +01:00
Jeroen Ketema
91f6498e16 Merge pull request #18537 from jketema/elifdef
C++: Support `#elifdef`, `#elifndef`, and MSVC's `#import`
2025-01-21 16:44:27 +01:00
Owen Mansel-Chan
b4c8390991 Merge pull request #18137 from owen-mc/java/jax-rs-annotation-inheritance
Java: Update JAX-RS annotation inheritance
2025-01-21 15:26:47 +00:00
Jeroen Ketema
ac18e7494f C++: Update stats file 2025-01-21 16:14:29 +01:00
Jeroen Ketema
32ff8dc0f6 C++: Add upgrade and downgrade scripts 2025-01-21 16:14:27 +01:00
Jeroen Ketema
e0acf262d5 C++: Add change note 2025-01-21 16:14:18 +01:00
Jeroen Ketema
9fd95381dc C++: Support #elifdef #elifndef, and MSVC's #import 2025-01-21 16:14:16 +01:00
Jeroen Ketema
a0ef2888c7 C++: Add more preprocessor tests 2025-01-21 16:14:13 +01:00
Chris Smowton
531e637009 Merge pull request #18551 from github/post-release-prep/codeql-cli-2.20.2
Post-release preparation for codeql-cli-2.20.2
2025-01-21 14:21:56 +00:00
github-actions[bot]
ebe9088458 Post-release preparation for codeql-cli-2.20.2 2025-01-21 13:58:45 +00:00
Chris Smowton
9fa1ad9d8d Fix changelog typos 2025-01-21 13:58:44 +00:00
github-actions[bot]
f21784db9d Release preparation for version 2.20.2 2025-01-21 13:58:43 +00:00
Chris Smowton
fb140404b6 Revert "Release preparation for version 2.20.2" 2025-01-21 13:58:38 +00:00
Anders Schack-Mulligen
0f96e79264 Java: Improve performance of XSS regex. 2025-01-21 14:41:08 +01:00
Asger F
0b9187d76c JS: Add change note 2025-01-21 14:17:35 +01:00
Asger F
a9d21e70c2 JS: Bump extractor version string 2025-01-21 14:04:12 +01:00
Asger F
dd55460d7f JS: Update test output 2025-01-21 14:03:30 +01:00
Asger F
784d07c95b JS: Ensure embedded TypeScript is extracted even when not associated with a tsconfig 2025-01-21 14:02:32 +01:00
Asger F
f3b52adde6 JS: Add test showing DB-CHECK failure 2025-01-21 14:02:17 +01:00
Michael Nebel
43bc3e5d99 Merge pull request #17911 from michaelnebel/csharp/deprecateexperimental
C#: Deprecate experimental queries.
2025-01-21 13:29:38 +01:00
Michael Nebel
93562950bb C#: Add change-note. 2025-01-21 13:14:27 +01:00
Michael Nebel
0932a0edb5 C#: Updated expected test output. 2025-01-21 13:14:26 +01:00
Michael Nebel
00de19ce13 C#: Deprecate experimental queries and libraries. 2025-01-21 13:14:24 +01:00
Geoffrey White
ab9ab0e22f Merge pull request #18536 from GeekMasher/rust-postgres
Rust: Add Postgres crate Models
2025-01-21 11:17:15 +00:00
Owen Mansel-Chan
7b071ba91e Merge pull request #18544 from github/workflow/coverage/update
Update CSV framework coverage reports
2025-01-21 10:04:15 +00:00
Mathew Payne
2b74061167 fix(rust): Update TaintFlowStep 2025-01-21 09:58:33 +00:00
Owen Mansel-Chan
19df33fb43 Remove another erroneous comment
Co-authored-by: Jami <57204504+jcogs33@users.noreply.github.com>
2025-01-21 09:25:37 +00:00
github-actions[bot]
35462a4d09 Add changed framework coverage reports 2025-01-21 00:20:17 +00:00
Chris Smowton
fc841023c6 Merge pull request #18541 from github/post-release-prep/codeql-cli-2.20.2
Post-release preparation for codeql-cli-2.20.2
2025-01-20 22:11:14 +00:00
Owen Mansel-Chan
6fa18be0cc Fix QLDocs 2025-01-20 22:07:01 +00:00
github-actions[bot]
fbb7f0a0c6 Post-release preparation for codeql-cli-2.20.2 2025-01-20 21:11:14 +00:00
Chris Smowton
cf9d773de0 Fix change-note typo 2025-01-20 21:11:13 +00:00
github-actions[bot]
a0512a50f2 Release preparation for version 2.20.2 2025-01-20 21:11:12 +00:00
Nick Rolfe
3e5707154a Merge pull request #18542 from github/nickrolfe/java-stats
Java: fix stats for databaseMetadata relation
2025-01-20 17:28:51 +00:00
Nick Rolfe
6b5974a372 Java: fix stats for databaseMetadata relation 2025-01-20 17:02:25 +00:00
Joe Farebrother
d248fbfe57 Merge pull request #18301 from joefarebrother/python-model-missing-builtins
Python: Add models for builtins `map`, `filter`, `zip`, and `enumerate`.
2025-01-20 16:39:37 +00:00
Owen Mansel-Chan
4e59ac4819 Merge pull request #14873 from Kwstubbs/go-rs-cors
Go: Add Rs Cors Support
2025-01-20 16:16:50 +00:00
Ian Lynagh
66777e6282 Merge pull request #18450 from igfoo/igfoo/kot2.1.20b1
Kotlin: Add support for 2.1.20-Beta1
2025-01-20 15:32:19 +00:00
Nick Rolfe
3846be450d Merge pull request #18529 from github/nickrolfe/java-databaseMetadata
Java: add `databaseMetadata` relation to dbscheme
2025-01-20 15:25:01 +00:00
Chris Smowton
411f3cd2f5 Merge pull request #17701 from smowton/smowton/feature/read-fields-before-executetemplate
Go: `template/text.Template` execution methods: support reading arbitrary content
2025-01-20 15:01:06 +00:00
Mathew Payne
7edb397de1 Merge branch 'main' into rust-postgres 2025-01-20 15:01:00 +00:00
Ian Lynagh
cec503eecd Kotlin: Fix build with 2.1.20-Beta1 2025-01-20 14:31:58 +00:00
Ian Lynagh
4e798b3db4 Kotlin: Add 2.1.20-Beta1 2025-01-20 14:31:57 +00:00
Ian Lynagh
ff328d6c04 Kotlin: Add 2.1.20-Beta1 deps 2025-01-20 14:31:57 +00:00
Mathew Payne
121f0584e4 feat(rust): Add models + tests 2025-01-20 12:06:09 +00:00
Mathew Payne
04ee557b31 feat(rust): Add initial Postgres support + tests 2025-01-20 12:01:23 +00:00
Kevin Stubbings
217bc74278 Fix documentation 2025-01-19 22:43:14 -08:00
Kevin Stubbings
e1c601dc52 oops 2025-01-17 10:18:59 -08:00
Nick Rolfe
64f33955b5 Java: add databaseMetadata to dbscheme 2025-01-17 15:18:07 +00:00
Joe Farebrother
344dd2dab5 Qldoc fix 2025-01-15 10:26:37 +00:00
Joe Farebrother
2aea356756 Add change note + fix tests 2025-01-15 10:24:18 +00:00
Joe Farebrother
6a6585e415 Add tests for zip and enumerate 2025-01-15 09:57:15 +00:00
Chris Smowton
9504f3611f Restrict text/template modelling to known call targets
Otherwise it's too easy to define a common interface to both text/template, which doesn't sanitize, and html/template, which does.
2025-01-14 17:52:02 +00:00
Chris Smowton
016bda04a5 Autoformat 2025-01-14 17:52:01 +00:00
Chris Smowton
24eb774921 Change note 2025-01-14 17:52:00 +00:00
Chris Smowton
bf34860ad0 Test deeply ntested taint 2025-01-14 17:51:59 +00:00
Chris Smowton
3573ff10c7 Update to account for changes on main 2025-01-14 17:51:58 +00:00
Chris Smowton
9c409f1280 Apply cosmetic review feedback 2025-01-14 17:51:57 +00:00
Chris Smowton
5548662a74 Switch to implementation using a universal read-only ContentSet 2025-01-14 17:51:55 +00:00
Chris Smowton
ae34a9c80e template/text.Template execution methods: support reading arbitrary content 2025-01-14 17:51:54 +00:00
Joe Farebrother
460de3f7d5 Reduce generality of map and zip for performance 2025-01-14 09:39:57 +00:00
Joe Farebrother
4e36008ed9 Add tests 2025-01-14 09:39:56 +00:00
Joe Farebrother
642f9dcbea Model missing builtins 2025-01-14 09:39:54 +00:00
Owen Mansel-Chan
7688f46650 Add change note 2025-01-07 17:08:23 +00:00
Owen Mansel-Chan
9cc614ac2d Allow jax-rs path annotation inheritance 2025-01-07 16:44:12 +00:00
Owen Mansel-Chan
de1b374e0e Test JAX-RS class/interface annotation inheritance 2025-01-07 15:28:41 +00:00
Kevin Stubbings
4b95ea0987 Merge branch 'main' into go-rs-cors 2024-12-17 17:35:29 -08:00
Kevin Stubbings
8277c602ac depstubber 2023-11-21 14:31:52 -08:00
Kevin Stubbings
d7e2fbc11d Finish 2023-11-21 14:27:17 -08:00
Kevin Stubbings
9958ad904c thesame 2023-11-20 23:40:55 -08:00
Kevin Stubbings
28288e0d23 basic2 2023-11-20 23:40:55 -08:00
Kevin Stubbings
3b78477406 Basics 2023-11-20 23:40:55 -08:00
210 changed files with 17490 additions and 780 deletions

View File

@@ -218,6 +218,7 @@ use_repo(
"kotlin-compiler-2.0.0-RC1",
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
@@ -232,6 +233,7 @@ use_repo(
"kotlin-compiler-embeddable-2.0.0-RC1",
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
@@ -246,6 +248,7 @@ use_repo(
"kotlin-stdlib-2.0.0-RC1",
"kotlin-stdlib-2.0.20-Beta2",
"kotlin-stdlib-2.1.0-Beta1",
"kotlin-stdlib-2.1.20-Beta1",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -1,5 +1,5 @@
name: codeql/actions-all
version: 0.4.1
version: 0.4.2-dev
library: true
warnOnImplicitThis: true
dependencies:

View File

@@ -1,5 +1,5 @@
name: codeql/actions-queries
version: 0.4.1
version: 0.4.2-dev
library: false
warnOnImplicitThis: true
groups: [actions, queries]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,21 @@
class PreprocessorDirective extends @preprocdirect {
string toString() { none() }
}
class Location extends @location_default {
string toString() { none() }
}
bindingset[kind]
int getKind(int kind) {
if kind = 14
then result = 6 // Represent MSFT #import as #include
else
if kind = 15 or kind = 6
then result = 3 // Represent #elifdef and #elifndef as #elif
else result = kind
}
from PreprocessorDirective ppd, int kind, Location l
where preprocdirects(ppd, kind, l)
select ppd, getKind(kind), l

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Support #elifdef, #elifndef and #import
compatibility: full
preprocdirects.rel: run preprocdirects.qlo

View File

@@ -0,0 +1,5 @@
---
category: feature
---
* New classes `PreprocessorElifdef` and `PreprocessorElifndef` were introduced, which represents the C23/C++23 `#elifdef` and `#elifndef` preprocessor directives.
* A new class `TypeLibraryImport` was introduced, which represents the `#import` preprocessor directive as used by the Microsoft Visual C++ for importing type libraries.

View File

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

View File

@@ -57,9 +57,9 @@ class IncludeNext extends Include, @ppd_include_next {
}
/**
* A `#import` preprocessor directive (used heavily in Objective C, and
* supported by GCC as an extension in C). For example the following code
* contains one `Import` directive:
* An Objective C `#import` preprocessor directive (supported by GCC as
* an extension in C). For example the following code contains one `Import`
* directive:
* ```
* #import <header3.h>
* ```
@@ -67,3 +67,14 @@ class IncludeNext extends Include, @ppd_include_next {
class Import extends Include, @ppd_objc_import {
override string toString() { result = "#import " + this.getIncludeText() }
}
/**
* A Microsoft `#import` preprocessor directive for importing a type library.
* For example the following code contains one `TypeLibraryImport` directive:
* ```
* #import "library.tlb"
* ```
*/
class TypeLibraryImport extends Include, @ppd_ms_import {
override string toString() { result = "#import " + this.getIncludeText() }
}

View File

@@ -42,7 +42,7 @@ private class TPreprocessorBranchDirective = @ppd_branch or @ppd_else or @ppd_en
/**
* A C/C++ preprocessor branch related directive: `#if`, `#ifdef`,
* `#ifndef`, `#elif`, `#else` or `#endif`.
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, `#else` or `#endif`.
*/
class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBranchDirective {
/**
@@ -74,8 +74,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
}
/**
* Gets the next `#elif`, `#else` or `#endif` matching this branching
* directive.
* Gets the next `#elif`, `#elifdef`, `#elifndef`, `#else` or `#endif` matching
* this branching directive.
*
* For example `somePreprocessorBranchDirective.getIf().getNext()` gets
* the second directive in the same construct as
@@ -88,8 +88,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
}
/**
* Gets the index of this branching directive within the matching #if,
* #ifdef or #ifndef.
* Gets the index of this branching directive within the matching `#if`,
* `#ifdef` or `#ifndef`.
*/
private int getIndexInBranch(PreprocessorBranch branch) {
this =
@@ -102,8 +102,8 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
}
/**
* A C/C++ preprocessor branching directive: `#if`, `#ifdef`, `#ifndef`, or
* `#elif`.
* A C/C++ preprocessor branching directive: `#if`, `#ifdef`, `#ifndef`,
* `#elif`, `#elifdef`, or `#elifndef`.
*
* A branching directive has a condition and that condition may be evaluated
* at compile-time. As a result, the preprocessor will either take the
@@ -151,8 +151,8 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
* #endif
* ```
* For the related notion of a directive which causes branching (which
* includes `#if`, plus also `#ifdef`, `#ifndef`, and `#elif`), see
* `PreprocessorBranch`.
* includes `#if`, plus also `#ifdef`, `#ifndef`, `#elif`, `#elifdef`,
* and `#elifndef`), see `PreprocessorBranch`.
*/
class PreprocessorIf extends PreprocessorBranch, @ppd_if {
override string toString() { result = "#if " + this.getHead() }
@@ -222,6 +222,40 @@ class PreprocessorElif extends PreprocessorBranch, @ppd_elif {
override string toString() { result = "#elif " + this.getHead() }
}
/**
* A C/C++ preprocessor `#elifdef` directive. For example there is a
* `PreprocessorElifdef` on the third line of the following code:
* ```
* #ifdef MYDEFINE1
* // ...
* #elifdef MYDEFINE2
* // ...
* #else
* // ...
* #endif
* ```
*/
class PreprocessorElifdef extends PreprocessorBranch, @ppd_elifdef {
override string toString() { result = "#elifdef " + this.getHead() }
}
/**
* A C/C++ preprocessor `#elifndef` directive. For example there is a
* `PreprocessorElifndef` on the third line of the following code:
* ```
* #ifdef MYDEFINE1
* // ...
* #elifndef MYDEFINE2
* // ...
* #else
* // ...
* #endif
* ```
*/
class PreprocessorElifndef extends PreprocessorBranch, @ppd_elifndef {
override string toString() { result = "#elifndef " + this.getHead() }
}
/**
* A C/C++ preprocessor `#endif` directive. For example there is a
* `PreprocessorEndif` on the third line of the following code:

View File

@@ -1,8 +1,9 @@
/**
* This library offers a view of preprocessor branches (`#if`, `#ifdef`,
* `#ifndef`, `#elif` and `#else`) as blocks of code between the opening and
* closing directives, with navigable parent-child relationships to other
* blocks. The main class is `PreprocessorBlock`.
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, and `#else`) as blocks of
* code between the opening and closing directives, with navigable
* parent-child relationships to other blocks. The main class is
* `PreprocessorBlock`.
*/
import cpp
@@ -32,10 +33,10 @@ private int getPreprocIndex(PreprocessorBranchDirective directive) {
/**
* A chunk of code from one preprocessor branch (`#if`, `#ifdef`,
* `#ifndef`, `#elif` or `#else`) to the directive that closes it
* (`#elif`, `#else` or `#endif`). The `getParent()` method
* allows these blocks to be navigated as a tree, with the root
* being the entire file.
* `#ifndef`, `#elif`, `#elifdef`, `#elifndef`, or `#else`) to the
* directive that closes it (`#elif`, `#elifdef`, `#elifndef`, `#else`,
* or `#endif`). The `getParent()` method allows these blocks to be
* navigated as a tree, with the root being the entire file.
*/
class PreprocessorBlock extends @element {
PreprocessorBlock() {

View File

@@ -2318,12 +2318,15 @@ case @preprocdirect.kind of
| 11 = @ppd_pragma
| 12 = @ppd_objc_import
| 13 = @ppd_include_next
| 14 = @ppd_ms_import
| 15 = @ppd_elifdef
| 16 = @ppd_elifndef
| 18 = @ppd_warning
;
@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next;
@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next | @ppd_ms_import;
@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif;
@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif | @ppd_elifdef | @ppd_elifndef;
preprocpair(
int begin : @ppd_branch ref,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Support #elifdef, #elifndef and #import
compatibility: partial

View File

@@ -177,6 +177,12 @@ predicate overflows(MulExpr me, Type t) {
)
}
predicate buildModeNoneIntLongConversion(IntType argType, LongType resultType) {
exists(argType) and
exists(resultType) and
exists(Compilation c | c.buildModeNone())
}
from MulExpr me, Type t1, Type t2
where
t1 = me.getType().getUnderlyingType() and
@@ -218,7 +224,10 @@ where
// only report if we cannot prove that the result of the
// multiplication will be less (resp. greater) than the
// maximum (resp. minimum) number we can compute.
overflows(me, t1)
overflows(me, t1) and
// In build mode none, many conversions from integer to long are caused by incorrect types,
// so exclude those results
not buildModeNoneIntLongConversion(t1, t2)
select me,
"Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '"
+ me.getFullyConverted().getType().toString() + "'."

View File

@@ -1,5 +1,5 @@
name: codeql/cpp-queries
version: 1.3.2
version: 1.3.3-dev
groups:
- cpp
- queries

View File

@@ -1,10 +1,16 @@
| #elif defined GREEN | preprocblock.cpp:10:0:11:0 | #ifndef BLUE |
| #elif defined GREEN | preprocblock.cpp:14:0:15:0 | #if 0 |
| #elif defined GREEN | preprocblock.cpp:16:0:17:0 | #else |
| #elifdef GREEN | preprocblock23.cpp:11:0:12:0 | #if 0 |
| #elifdef GREEN | preprocblock23.cpp:13:0:14:0 | #elifndef BLUE |
| (no parent) | file://:0:0:0:0 | |
| (no parent) | header.h:0:0:8:0 | header.h |
| (no parent) | preprocblock23.cpp:0:0:22:0 | preprocblock23.cpp |
| (no parent) | preprocblock.cpp:0:0:25:0 | preprocblock.cpp |
| header.h | header.h:3:0:7:0 | #ifndef HEADER_H |
| preprocblock23.cpp | preprocblock23.cpp:7:0:7:0 | #ifdef RED |
| preprocblock23.cpp | preprocblock23.cpp:8:0:17:0 | #elifdef GREEN |
| preprocblock23.cpp | preprocblock23.cpp:18:0:21:0 | #else |
| preprocblock.cpp | preprocblock.cpp:6:0:6:0 | #ifdef RED |
| preprocblock.cpp | preprocblock.cpp:7:0:20:0 | #elif defined GREEN |
| preprocblock.cpp | preprocblock.cpp:21:0:24:0 | #else |

View File

@@ -0,0 +1,22 @@
// preprocblock23.cpp
// semmle-extractor-options: -std=c++23
#include "header.h"
#define GREEN
#ifdef RED
#elifdef GREEN
#include "header.h"
#if 0
#include "header.h" // not reached
#elifndef BLUE
#include "header.h"
#endif
#include "header.h"
#else
// ...
#endif

View File

@@ -1,3 +1,7 @@
| preprocblock23.cpp:4:1:4:19 | #include "header.h" | preprocblock23.cpp:0:0:22:0 | preprocblock23.cpp |
| preprocblock23.cpp:9:2:9:20 | #include "header.h" | preprocblock23.cpp:8:0:17:0 | #elifdef GREEN |
| preprocblock23.cpp:14:3:14:21 | #include "header.h" | preprocblock23.cpp:13:0:14:0 | #elifndef BLUE |
| preprocblock23.cpp:17:2:17:20 | #include "header.h" | preprocblock23.cpp:8:0:17:0 | #elifdef GREEN |
| preprocblock.cpp:3:1:3:19 | #include "header.h" | preprocblock.cpp:0:0:25:0 | preprocblock.cpp |
| preprocblock.cpp:8:2:8:20 | #include "header.h" | preprocblock.cpp:7:0:20:0 | #elif defined GREEN |
| preprocblock.cpp:11:3:11:21 | #include "header.h" | preprocblock.cpp:10:0:11:0 | #ifndef BLUE |

View File

@@ -0,0 +1,15 @@
// semmle-extractor-options: -std=c++23
#define BAR
#ifdef FOO
#warning C++23 1
#elifdef BAR
#warning C++23 2
#endif
#ifdef FOO
#warning C++23 3
#elifndef FOO
#warning C++23 3
#endif

View File

@@ -0,0 +1,3 @@
// semmle-extractor-options: --microsoft
#import "test.tlb"

View File

@@ -1,4 +1,13 @@
| a.h:0:0:0:0 | a.h | 1 | 1 | 1 | 19 | IncludeNext | "a.h" | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 3 | 1 | 3 | 11 | Macro | BAR | |
| pp23.cpp:0:0:0:0 | pp23.cpp | 5 | 1 | 5 | 10 | PreprocessorIfdef | FOO | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 7 | 1 | 7 | 12 | PreprocessorElifdef | BAR | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 8 | 1 | 8 | 16 | PreprocessorWarning | C++23 2 | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 9 | 1 | 9 | 6 | PreprocessorEndif | N/A | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 11 | 1 | 11 | 10 | PreprocessorIfdef | FOO | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 13 | 1 | 13 | 13 | PreprocessorElifndef | FOO | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 14 | 1 | 14 | 16 | PreprocessorWarning | C++23 3 | N/A |
| pp23.cpp:0:0:0:0 | pp23.cpp | 15 | 1 | 15 | 6 | PreprocessorEndif | N/A | N/A |
| pp.cpp:0:0:0:0 | pp.cpp | 1 | 1 | 1 | 16 | PreprocessorIf | defined(FOO) | N/A |
| pp.cpp:0:0:0:0 | pp.cpp | 3 | 1 | 3 | 19 | PreprocessorElif | !defined(BAR) | N/A |
| pp.cpp:0:0:0:0 | pp.cpp | 4 | 1 | 4 | 11 | Macro | BAR | |
@@ -40,3 +49,6 @@
| pp.h:0:0:0:0 | pp.h | 7 | 1 | 11 | 8 | Macro | MULTILINE | world a long |
| pp.h:0:0:0:0 | pp.h | 13 | 1 | 14 | 11 | PreprocessorUndef | MULTILINE | N/A |
| pp.h:0:0:0:0 | pp.h | 16 | 1 | 17 | 8 | Include | "pp.h" | N/A |
| ppms.cpp:0:0:0:0 | ppms.cpp | 3 | 1 | 3 | 18 | TypeLibraryImport | "test.tlb" | N/A |
| test.tlh:0:0:0:0 | test.tlh | 1 | 1 | 1 | 12 | PreprocessorPragma | once | N/A |
| test.tlh:0:0:0:0 | test.tlh | 3 | 1 | 3 | 21 | PreprocessorWarning | type library | N/A |

View File

@@ -0,0 +1,3 @@
#pragma once
#warning type library

View File

@@ -0,0 +1,10 @@
// semmle-extractor-options: --build-mode none
int f();
void test() {
int i = f();
unsigned u = i;
long j = i * i; // GOOD: build mode none
unsigned long k = u * u; // GOOD: build mode none
}

View File

@@ -0,0 +1 @@
Likely Bugs/Arithmetic/IntMultToLong.ql

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* All *experimental* queries have been deprecated. The queries are instead available as part of the *default* query suite in [CodeQL-Community-Packs](https://github.com/GitHubSecurityLab/CodeQL-Community-Packs).

View File

@@ -15,10 +15,16 @@
*/
import csharp
import TaintedWebClientLib
import TaintedWebClient::PathGraph
deprecated import TaintedWebClientLib
deprecated import TaintedWebClient::PathGraph
from TaintedWebClient::PathNode source, TaintedWebClient::PathNode sink
where TaintedWebClient::flowPath(source, sink)
select sink.getNode(), source, sink, "A method of WebClient depepends on a $@.", source.getNode(),
"user-provided value"
deprecated query predicate problems(
DataFlow::Node sinkNode, TaintedWebClient::PathNode source, TaintedWebClient::PathNode sink,
string message1, DataFlow::Node sourceNode, string message2
) {
TaintedWebClient::flowPath(source, sink) and
sinkNode = sink.getNode() and
message1 = "A method of WebClient depepends on a $@." and
sourceNode = source.getNode() and
message2 = "user-provided value"
}

View File

@@ -1,3 +1,5 @@
deprecated module;
import csharp
import semmle.code.csharp.frameworks.system.Net
import semmle.code.csharp.frameworks.System

View File

@@ -11,10 +11,16 @@
*/
import csharp
import RequestForgery::RequestForgery
import RequestForgeryFlow::PathGraph
deprecated import RequestForgery::RequestForgery
deprecated import RequestForgeryFlow::PathGraph
from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink
where RequestForgeryFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "The URL of this request depends on a $@.", source.getNode(),
"user-provided value"
deprecated query predicate problems(
DataFlow::Node sinkNode, RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink,
string message1, DataFlow::Node sourceNode, string message2
) {
RequestForgeryFlow::flowPath(source, sink) and
sinkNode = sink.getNode() and
message1 = "The URL of this request depends on a $@." and
sourceNode = source.getNode() and
message2 = "user-provided value"
}

View File

@@ -1,3 +1,5 @@
deprecated module;
import csharp
module RequestForgery {

View File

@@ -17,89 +17,91 @@ import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
import experimental.dataflow.flowsources.AuthCookie
deprecated import experimental.dataflow.flowsources.AuthCookie
from Expr httpOnlySink
where
exists(Assignment a, Expr val |
httpOnlySink = a.getRValue() and
val.getValue() = "false" and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "HttpOnly") = val and
(
deprecated query predicate problems(Expr httpOnlySink, string message) {
(
exists(Assignment a, Expr val |
httpOnlySink = a.getRValue() and
val.getValue() = "false" and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "HttpOnly") = val and
(
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0))
or
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
// Passed as third argument to `IResponseCookies.Append`
exists(DataFlow::Node creation, DataFlow::Node append |
CookieOptionsTracking::flow(creation, append) and
creation.asExpr() = oc and
append.asExpr() = mc.getArgument(2)
)
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "HttpOnly" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue())
)
)
)
or
exists(Call c |
httpOnlySink = c and
(
exists(MicrosoftAspNetCoreHttpResponseCookies iResponse, MethodCall mc |
// default is not configured or is not set to `Always`
not getAValueForCookiePolicyProp("HttpOnly").getValue() = "1" and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
(
// `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "HttpOnly") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
or
// IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
mc = c and
mc.getNumberOfArguments() < 3
)
)
or
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0))
or
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
// Passed as third argument to `IResponseCookies.Append`
exists(DataFlow::Node creation, DataFlow::Node append |
CookieOptionsTracking::flow(creation, append) and
creation.asExpr() = oc and
append.asExpr() = mc.getArgument(2)
)
isCookieWithSensitiveName(oc.getArgument(0)) and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "HttpOnly") and
// the default in config is not set to `true`
not exists(XmlElement element |
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isHttpOnlyCookies()
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "HttpOnly" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue())
)
)
)
or
exists(Call c |
httpOnlySink = c and
(
exists(MicrosoftAspNetCoreHttpResponseCookies iResponse, MethodCall mc |
// default is not configured or is not set to `Always`
not getAValueForCookiePolicyProp("HttpOnly").getValue() = "1" and
// there is no callback `OnAppendCookie` that sets `HttpOnly` to true
not OnAppendCookieHttpOnlyTracking::flowTo(_) and
iResponse.getAppendMethod() = mc.getTarget() and
isCookieWithSensitiveName(mc.getArgument(0)) and
(
// `HttpOnly` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "HttpOnly") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
or
// IResponseCookies.Append(String, String) was called, `HttpOnly` is set to `false` by default
mc = c and
mc.getNumberOfArguments() < 3
)
)
or
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
isCookieWithSensitiveName(oc.getArgument(0)) and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "HttpOnly") and
// the default in config is not set to `true`
not exists(XmlElement element |
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isHttpOnlyCookies()
)
)
)
)
select httpOnlySink, "Cookie attribute 'HttpOnly' is not set to true."
) and
message = "Cookie attribute 'HttpOnly' is not set to true."
}

View File

@@ -68,15 +68,14 @@ predicate isExprAnAccessToSafeClientSideEncryptionVersionValue(Expr e) {
)
}
from Expr e, Class c, Assembly asm
where
asm = c.getLocation() and
(
deprecated query predicate problems(Expr e, string message) {
exists(Class c, Assembly asm | asm = c.getLocation() |
exists(Expr e2 |
isCreatingAzureClientSideEncryptionObject(e, c, e2) and
not isObjectCreationArgumentSafeAndUsingSafeVersionOfAssembly(e2, asm)
)
or
isCreatingOutdatedAzureClientSideEncryptionObject(e, c)
)
select e, "Unsafe usage of v1 version of Azure Storage client-side encryption."
) and
message = "Unsafe usage of v1 version of Azure Storage client-side encryption."
}

View File

@@ -17,89 +17,91 @@ import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web
import semmle.code.csharp.frameworks.microsoft.AspNetCore
import experimental.dataflow.flowsources.AuthCookie
deprecated import experimental.dataflow.flowsources.AuthCookie
from Expr secureSink
where
exists(Call c |
secureSink = c and
(
// default is not configured or is not set to `Always` or `SameAsRequest`
not (
getAValueForCookiePolicyProp("Secure").getValue() = "0" or
getAValueForCookiePolicyProp("Secure").getValue() = "1"
) and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
deprecated query predicate problems(Expr secureSink, string message) {
(
exists(Call c |
secureSink = c and
(
// `Secure` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "Secure") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
// default is not configured or is not set to `Always` or `SameAsRequest`
not (
getAValueForCookiePolicyProp("Secure").getValue() = "0" or
getAValueForCookiePolicyProp("Secure").getValue() = "1"
) and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
(
// `Secure` property in `CookieOptions` passed to IResponseCookies.Append(...) wasn't set
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
not isPropertySet(oc, "Secure") and
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
or
// IResponseCookies.Append(String, String) was called, `Secure` is set to `false` by default
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
mc = c and
iResponse.getAppendMethod() = mc.getTarget() and
mc.getNumberOfArguments() < 3
)
)
or
// IResponseCookies.Append(String, String) was called, `Secure` is set to `false` by default
exists(MethodCall mc, MicrosoftAspNetCoreHttpResponseCookies iResponse |
mc = c and
iResponse.getAppendMethod() = mc.getTarget() and
mc.getNumberOfArguments() < 3
)
)
or
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "Secure") and
// the default in config is not set to `true`
// the `exists` below covers the `cs/web/requiressl-not-set`
not exists(XmlElement element |
element instanceof FormsElement and
element.(FormsElement).isRequireSsl()
or
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isRequireSsl()
)
)
)
)
or
exists(Assignment a, Expr val |
secureSink = a.getRValue() and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "Secure") = val and
val.getValue() = "false" and
(
oc.getType() instanceof SystemWebHttpCookie
or
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
// the cookie option is passed to `Append`
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
exists(ObjectCreation oc |
oc = c and
oc.getType() instanceof SystemWebHttpCookie and
// the property wasn't explicitly set, so a default value from config is used
not isPropertySet(oc, "Secure") and
// the default in config is not set to `true`
// the `exists` below covers the `cs/web/requiressl-not-set`
not exists(XmlElement element |
element instanceof FormsElement and
element.(FormsElement).isRequireSsl()
or
element instanceof HttpCookiesElement and
element.(HttpCookiesElement).isRequireSsl()
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "SecurePolicy" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue()) and
val.getValue() = "2" // None
)
or
exists(Assignment a, Expr val |
secureSink = a.getRValue() and
(
exists(ObjectCreation oc |
getAValueForProp(oc, a, "Secure") = val and
val.getValue() = "false" and
(
oc.getType() instanceof SystemWebHttpCookie
or
oc.getType() instanceof MicrosoftAspNetCoreHttpCookieOptions and
// there is no callback `OnAppendCookie` that sets `Secure` to true
not OnAppendCookieSecureTracking::flowTo(_) and
// the cookie option is passed to `Append`
exists(DataFlow::Node creation |
CookieOptionsTracking::flow(creation, _) and
creation.asExpr() = oc
)
)
)
or
exists(PropertyWrite pw |
(
pw.getProperty().getDeclaringType() instanceof MicrosoftAspNetCoreHttpCookieBuilder or
pw.getProperty().getDeclaringType() instanceof
MicrosoftAspNetCoreAuthenticationCookiesCookieAuthenticationOptions
) and
pw.getProperty().getName() = "SecurePolicy" and
a.getLValue() = pw and
DataFlow::localExprFlow(val, a.getRValue()) and
val.getValue() = "2" // None
)
)
)
)
select secureSink, "Cookie attribute 'Secure' is not set to true."
) and
message = "Cookie attribute 'Secure' is not set to true."
}

View File

@@ -192,7 +192,13 @@ module HashWithoutSaltConfig implements DataFlow::ConfigSig {
module HashWithoutSalt = TaintTracking::Global<HashWithoutSaltConfig>;
from HashWithoutSalt::PathNode source, HashWithoutSalt::PathNode sink
where HashWithoutSalt::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ is hashed without a salt.", source.getNode(),
"The password"
deprecated query predicate problems(
DataFlow::Node sinkNode, HashWithoutSalt::PathNode source, HashWithoutSalt::PathNode sink,
string message, DataFlow::Node sourceNode, string password
) {
sinkNode = sink.getNode() and
sourceNode = source.getNode() and
HashWithoutSalt::flowPath(source, sink) and
message = "$@ is hashed without a salt." and
password = "The password"
}

View File

@@ -1,3 +1,5 @@
deprecated module;
import csharp
import DataFlow

View File

@@ -14,11 +14,17 @@
import csharp
import DataFlow
import JsonWebTokenHandlerLib
deprecated import JsonWebTokenHandlerLib
import semmle.code.csharp.commons.QualifiedName
from TokenValidationParametersProperty p, CallableAlwaysReturnsTrue e, string qualifier, string name
where e = p.getAnAssignedValue() and p.hasFullyQualifiedName(qualifier, name)
select e,
"JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns \"true\".",
p, getQualifiedName(qualifier, name)
deprecated query predicate problems(
CallableAlwaysReturnsTrue e, string message, TokenValidationParametersProperty p,
string fullyQualifiedName
) {
exists(string qualifier, string name | p.hasFullyQualifiedName(qualifier, name) |
fullyQualifiedName = getQualifiedName(qualifier, name)
) and
e = p.getAnAssignedValue() and
message =
"JsonWebTokenHandler security-sensitive property $@ is being delegated to this callable that always returns \"true\"."
}

View File

@@ -12,15 +12,18 @@
*/
import csharp
import JsonWebTokenHandlerLib
deprecated import JsonWebTokenHandlerLib
import semmle.code.csharp.commons.QualifiedName
from
DataFlow::Node source, DataFlow::Node sink,
TokenValidationParametersPropertySensitiveValidation pw, string qualifier, string name
where
deprecated query predicate problems(
DataFlow::Node sink, string message, TokenValidationParametersPropertySensitiveValidation pw,
string fullyQualifiedName, DataFlow::Node source, string value
) {
FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation::flow(source, sink) and
sink.asExpr() = pw.getAnAssignedValue() and
pw.hasFullyQualifiedName(qualifier, name)
select sink, "The security sensitive property $@ is being disabled by the following value: $@.", pw,
getQualifiedName(qualifier, name), source, "false"
exists(string qualifier, string name | pw.hasFullyQualifiedName(qualifier, name) |
fullyQualifiedName = getQualifiedName(qualifier, name)
) and
message = "The security sensitive property $@ is being disabled by the following value: $@." and
value = "false"
}

View File

@@ -3,6 +3,7 @@
*
* Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details.
*/
deprecated module;
import csharp

View File

@@ -9,9 +9,10 @@
*/
import csharp
import DataSetSerialization
deprecated import DataSetSerialization
from DataSetOrTableRelatedClass dstc
where dstc.fromSource()
select dstc,
"Defining a class that inherits or has a property derived from the obsolete DataSet or DataTable types. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details."
deprecated query predicate problems(DataSetOrTableRelatedClass dstc, string message) {
dstc.fromSource() and
message =
"Defining a class that inherits or has a property derived from the obsolete DataSet or DataTable types. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details."
}

View File

@@ -10,12 +10,17 @@
*/
import csharp
import DataSetSerialization
deprecated import DataSetSerialization
from UnsafeXmlSerializerImplementation c, Member m
where
deprecated query predicate problems(
Member m, string message, UnsafeXmlSerializerImplementation c, string classMessage, Member member,
string memberMessage
) {
c.fromSource() and
isClassUnsafeXmlSerializerImplementation(c, m)
select m,
"Defining an serializable class $@ that has member $@ of a type that is derived from DataSet or DataTable types and may lead to a security problem. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details.",
c, c.toString(), m, m.toString()
isClassUnsafeXmlSerializerImplementation(c, m) and
message =
"Defining an serializable class $@ that has member $@ of a type that is derived from DataSet or DataTable types and may lead to a security problem. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details." and
classMessage = c.toString() and
member = m and
memberMessage = m.toString()
}

View File

@@ -10,7 +10,7 @@
*/
import csharp
import DataSetSerialization
deprecated import DataSetSerialization
predicate xmlSerializerConstructorArgument(Expr e) {
exists(ObjectCreation oc, Constructor c | e = oc.getArgument(0) |
@@ -21,7 +21,7 @@ predicate xmlSerializerConstructorArgument(Expr e) {
)
}
predicate unsafeDataContractTypeCreation(Expr e) {
deprecated predicate unsafeDataContractTypeCreation(Expr e) {
exists(MethodCall gt |
gt.getTarget().getName() = "GetType" and
e = gt and
@@ -31,16 +31,20 @@ predicate unsafeDataContractTypeCreation(Expr e) {
e.(TypeofExpr).getTypeAccess().getTarget() instanceof DataSetOrTableRelatedClass
}
module FlowToDataSerializerConstructorConfig implements DataFlow::ConfigSig {
deprecated module FlowToDataSerializerConstructorConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { unsafeDataContractTypeCreation(node.asExpr()) }
predicate isSink(DataFlow::Node node) { xmlSerializerConstructorArgument(node.asExpr()) }
}
module FlowToDataSerializerConstructor = DataFlow::Global<FlowToDataSerializerConstructorConfig>;
deprecated module FlowToDataSerializerConstructor =
DataFlow::Global<FlowToDataSerializerConstructorConfig>;
from DataFlow::Node source, DataFlow::Node sink
where FlowToDataSerializerConstructor::flow(source, sink)
select sink,
"Unsafe type is used in data contract serializer. Make sure $@ comes from the trusted source.",
source, source.toString()
deprecated query predicate problems(
DataFlow::Node sink, string message, DataFlow::Node source, string sourceMessage
) {
FlowToDataSerializerConstructor::flow(source, sink) and
message =
"Unsafe type is used in data contract serializer. Make sure $@ comes from the trusted source." and
sourceMessage = source.toString()
}

View File

@@ -10,8 +10,10 @@
*/
import csharp
import DataSetSerialization
deprecated import DataSetSerialization
from UnsafeXmlReadMethodCall mc
select mc,
"Making an XML deserialization call with a type derived from DataSet or DataTable types and may lead to a security problem. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details."
deprecated query predicate problems(UnsafeXmlReadMethodCall mc, string message) {
message =
"Making an XML deserialization call with a type derived from DataSet or DataTable types and may lead to a security problem. Please visit https://go.microsoft.com/fwlink/?linkid=2132227 for details." and
exists(mc)
}

View File

@@ -48,8 +48,8 @@ predicate isExternMethod(Method externMethod) {
SystemRuntimeInteropServicesComImportAttributeClass
}
from MethodCall mc
where
deprecated query predicate problems(MethodCall mc, string message) {
isExternMethod(mc.getTarget()) and
isDangerousMethod(mc.getTarget())
select mc, "Call to an external method '" + mc.getTarget().getName() + "'."
isDangerousMethod(mc.getTarget()) and
message = "Call to an external method '" + mc.getTarget().getName() + "'."
}

View File

@@ -174,13 +174,16 @@ predicate isPotentialTimeBomb(
)
}
from
Flow::PathNode source, Flow::PathNode sink, Call getLastWriteTimeMethodCall,
Call timeArithmeticCall, Call timeComparisonCall, SelectionStmt selStatement
where
deprecated query predicate problems(
SelectionStmt selStatement, Flow::PathNode source, Flow::PathNode sink, string message,
Call timeComparisonCall, string timeComparisonCallString, Call timeArithmeticCall, string offset,
Call getLastWriteTimeMethodCall, string lastWriteTimeMethodCallMessage
) {
isPotentialTimeBomb(source, sink, getLastWriteTimeMethodCall, timeArithmeticCall,
timeComparisonCall, selStatement)
select selStatement, source, sink,
"Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger.",
timeComparisonCall, timeComparisonCall.toString(), timeArithmeticCall, "offset",
getLastWriteTimeMethodCall, "last modification time of a file"
timeComparisonCall, selStatement) and
message =
"Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger." and
timeComparisonCallString = timeComparisonCall.toString() and
offset = "offset" and
lastWriteTimeMethodCallMessage = "last modification time of a file"
}

View File

@@ -42,8 +42,15 @@ predicate isSuspiciousPropertyName(PropertyRead pr) {
pr.getTarget().hasFullyQualifiedName("System.Diagnostics", "Process", "ProcessName")
}
from DataFlowFromMethodToHash::PathNode src, DataFlowFromMethodToHash::PathNode sink
where DataFlowFromMethodToHash::flow(src.getNode(), sink.getNode())
select src.getNode(), src, sink,
"The hash is calculated on $@, may be related to a backdoor. Please review the code for possible malicious intent.",
sink.getNode(), "this process name"
deprecated query predicate problems(
DataFlow::Node srcNode, DataFlowFromMethodToHash::PathNode src,
DataFlowFromMethodToHash::PathNode sink, string message, DataFlow::Node sinkNode,
string sinkMessage
) {
srcNode = src.getNode() and
sinkNode = sink.getNode() and
DataFlowFromMethodToHash::flow(srcNode, sinkNode) and
message =
"The hash is calculated on $@, may be related to a backdoor. Please review the code for possible malicious intent." and
sinkMessage = "this process name"
}

View File

@@ -1,6 +1,7 @@
/**
* Provides classes and predicates for detecting insecure cookies.
*/
deprecated module;
import csharp
import semmle.code.csharp.frameworks.microsoft.AspNetCore

View File

@@ -1,5 +1,5 @@
name: codeql/csharp-queries
version: 1.0.15
version: 1.0.16-dev
groups:
- csharp
- queries

View File

@@ -4,5 +4,5 @@ nodes
| RequestForgery.cs:12:52:12:54 | url : String | semmle.label | url : String |
| RequestForgery.cs:14:66:14:68 | access to parameter url | semmle.label | access to parameter url |
subpaths
#select
problems
| RequestForgery.cs:14:66:14:68 | access to parameter url | RequestForgery.cs:12:52:12:54 | url : String | RequestForgery.cs:14:66:14:68 | access to parameter url | The URL of this request depends on a $@. | RequestForgery.cs:12:52:12:54 | url | user-provided value |

View File

@@ -1,7 +1,3 @@
#select
| HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | HashWithoutSalt.cs:18:70:18:77 | access to parameter password : String | HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:18:70:18:77 | access to parameter password | The password |
| HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | HashWithoutSalt.cs:38:64:38:71 | access to parameter password : String | HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:38:64:38:71 | access to parameter password | The password |
| HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:70:64:70:71 | access to parameter password | The password |
edges
| HashWithoutSalt.cs:18:17:18:24 | access to local variable passBuff : IBuffer | HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | provenance | |
| HashWithoutSalt.cs:18:28:18:105 | call to method ConvertStringToBinary : IBuffer | HashWithoutSalt.cs:18:17:18:24 | access to local variable passBuff : IBuffer | provenance | |
@@ -27,4 +23,8 @@ nodes
| HashWithoutSalt.cs:70:28:70:72 | call to method GetBytes : Byte[] | semmle.label | call to method GetBytes : Byte[] |
| HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | semmle.label | access to parameter password : String |
| HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | semmle.label | access to local variable passBytes |
problems
| HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | HashWithoutSalt.cs:18:70:18:77 | access to parameter password : String | HashWithoutSalt.cs:20:49:20:56 | access to local variable passBuff | $@ is hashed without a salt. | HashWithoutSalt.cs:18:70:18:77 | access to parameter password | The password |
| HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | HashWithoutSalt.cs:38:64:38:71 | access to parameter password : String | HashWithoutSalt.cs:39:51:39:59 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:38:64:38:71 | access to parameter password | The password |
| HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | HashWithoutSalt.cs:70:64:70:71 | access to parameter password : String | HashWithoutSalt.cs:71:48:71:56 | access to local variable passBytes | $@ is hashed without a salt. | HashWithoutSalt.cs:70:64:70:71 | access to parameter password | The password |
subpaths

View File

@@ -17,7 +17,7 @@ edges
| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo | provenance | |
| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo : Int32 | provenance | |
| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:36:71:70 | call to method AddHours | provenance | |
#select
problems
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo : Int32 | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |
| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:76 | ... >= ... | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file |

View File

@@ -1,4 +1,4 @@
edges
nodes
subpaths
#select
problems

View File

@@ -20,12 +20,12 @@
Java,"Java 7 to 22 [5]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [6]_",``.java``
Kotlin,"Kotlin 1.5.0 to 2.1.0\ *x*","kotlinc",``.kt``
Kotlin,"Kotlin 1.5.0 to 2.1.2\ *x*","kotlinc",``.kt``
JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [7]_"
Python [8]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [9]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"
Swift [10]_,"Swift 5.4-5.10","Swift compiler","``.swift``"
TypeScript [11]_,"2.6-5.6",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
TypeScript [11]_,"2.6-5.7",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``"
.. container:: footnote-group

View File

@@ -138,5 +138,5 @@ sync,,,34,,,,,,,,,,,,,,,,,,,,,,,34,
syscall,5,2,8,5,,,,,,,,,,,,,,,,,,2,,,,8,
text/scanner,,,3,,,,,,,,,,,,,,,,,,,,,,,3,
text/tabwriter,,,1,,,,,,,,,,,,,,,,,,,,,,,1,
text/template,,,6,,,,,,,,,,,,,,,,,,,,,,,6,
text/template,,,4,,,,,,,,,,,,,,,,,,,,,,,4,
xorm.io/xorm,34,,,,,,,,,,,,,,34,,,,,,,,,,,,
1 package sink source summary sink:command-injection sink:credentials-key sink:jwt sink:log-injection sink:nosql-injection sink:path-injection sink:regex-use[0] sink:regex-use[1] sink:regex-use[c] sink:request-forgery sink:request-forgery[TCP Addr + Port] sink:sql-injection sink:url-redirection sink:url-redirection[0] sink:url-redirection[receiver] sink:xpath-injection source:commandargs source:database source:environment source:file source:remote source:stdin summary:taint summary:value
138 syscall 5 2 8 5 2 8
139 text/scanner 3 3
140 text/tabwriter 1 1
141 text/template 6 4 6 4
142 xorm.io/xorm 34 34

View File

@@ -26,7 +26,7 @@ Go framework & library support
`Macaron <https://gopkg.in/macaron.v1>`_,``gopkg.in/macaron*``,12,1,1
`Revel <http://revel.github.io/>`_,"``github.com/revel/revel*``, ``github.com/robfig/revel*``",46,20,4
`SendGrid <https://github.com/sendgrid/sendgrid-go>`_,``github.com/sendgrid/sendgrid-go*``,,1,
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",52,605,104
`Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",52,603,104
`XPath <https://github.com/antchfx/xpath>`_,``github.com/antchfx/xpath*``,,,4
`appleboy/gin-jwt <https://github.com/appleboy/gin-jwt>`_,``github.com/appleboy/gin-jwt*``,,,1
`beego <https://beego.me/>`_,"``github.com/astaxie/beego*``, ``github.com/beego/beego*``",102,63,213
@@ -61,5 +61,5 @@ Go framework & library support
`yaml <https://gopkg.in/yaml.v3>`_,``gopkg.in/yaml*``,,9,
`zap <https://go.uber.org/zap>`_,``go.uber.org/zap*``,,11,33
Others,"``github.com/Masterminds/squirrel``, ``github.com/caarlos0/env``, ``github.com/go-gorm/gorm``, ``github.com/go-xorm/xorm``, ``github.com/gobuffalo/envy``, ``github.com/gogf/gf/database/gdb``, ``github.com/hashicorp/go-envparse``, ``github.com/jinzhu/gorm``, ``github.com/jmoiron/sqlx``, ``github.com/joho/godotenv``, ``github.com/kelseyhightower/envconfig``, ``github.com/lann/squirrel``, ``github.com/raindog308/gorqlite``, ``github.com/rqlite/gorqlite``, ``github.com/uptrace/bun``, ``go.mongodb.org/mongo-driver/mongo``, ``gopkg.in/Masterminds/squirrel``, ``gorm.io/gorm``, ``xorm.io/xorm``",117,16,391
Totals,,459,943,1532
Totals,,459,941,1532

View File

@@ -1,5 +1,5 @@
name: codeql-go-consistency-queries
version: 1.0.15
version: 1.0.16-dev
groups:
- go
- queries

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Added the [rs cors](https://github.com/rs/cors) library to the CorsMisconfiguration.ql query

View File

@@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* By implementing `ImplicitFieldReadNode` it is now possible to declare a dataflow node that reads any content (fields, array members, map keys and values). For example, this is appropriate for modelling a serialization method that flattens a potentially deep data structure into a string or byte array.
* The `Template.Execute[Template]` methods of the `text/template` package now correctly convey taint from any nested fields to their result. This may produce more results from any taint-tracking query when the `text/template` package is in use.

View File

@@ -7,5 +7,5 @@ extensions:
- ["text/template", "", False, "HTMLEscapeString", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["text/template", "", False, "JSEscape", "", "", "Argument[1]", "Argument[0]", "taint", "manual"]
- ["text/template", "", False, "JSEscapeString", "", "", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["text/template", "Template", True, "Execute", "", "", "Argument[1]", "Argument[0]", "taint", "manual"]
- ["text/template", "Template", True, "ExecuteTemplate", "", "", "Argument[2]", "Argument[0]", "taint", "manual"]
# - ["text/template", "Template", True, "Execute", "", "", "Argument[1]", "Argument[0]", "taint", "manual"] # Implemented in QL to provide an arbitrary content read from the input.
# - ["text/template", "Template", True, "ExecuteTemplate", "", "", "Argument[2]", "Argument[0]", "taint", "manual"] # Implemented in QL to provide an arbitrary content read from the input.

View File

@@ -32,6 +32,7 @@ import semmle.go.frameworks.Afero
import semmle.go.frameworks.AwsLambda
import semmle.go.frameworks.Beego
import semmle.go.frameworks.BeegoOrm
import semmle.go.frameworks.RsCors
import semmle.go.frameworks.Couchbase
import semmle.go.frameworks.Echo
import semmle.go.frameworks.ElazarlGoproxy

View File

@@ -1,5 +1,5 @@
name: codeql/go-all
version: 3.0.2
version: 3.0.3-dev
groups: go
dbscheme: go.dbscheme
extractor: go

View File

@@ -143,26 +143,28 @@ predicate jumpStep(Node n1, Node n2) {
* Thus, `node2` references an object with a content `x` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, ContentSet c, Node node2) {
// a write `(*p).f = rhs` is modeled as two store steps: `rhs` is flows into field `f` of `(*p)`,
// which in turn flows into the pointer content of `p`
exists(Write w, Field f, DataFlow::Node base, DataFlow::Node rhs | w.writesField(base, f, rhs) |
node1 = rhs and
node2.(PostUpdateNode).getPreUpdateNode() = base and
c = any(DataFlow::FieldContent fc | fc.getField() = f)
predicate storeStep(Node node1, ContentSet cs, Node node2) {
exists(Content c | cs.asOneContent() = c |
// a write `(*p).f = rhs` is modeled as two store steps: `rhs` is flows into field `f` of `(*p)`,
// which in turn flows into the pointer content of `p`
exists(Write w, Field f, DataFlow::Node base, DataFlow::Node rhs | w.writesField(base, f, rhs) |
node1 = rhs and
node2.(PostUpdateNode).getPreUpdateNode() = base and
c = any(DataFlow::FieldContent fc | fc.getField() = f)
or
node1 = base and
node2.(PostUpdateNode).getPreUpdateNode() = node1.(PointerDereferenceNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node2.getType())
)
or
node1 = base and
node2.(PostUpdateNode).getPreUpdateNode() = node1.(PointerDereferenceNode).getOperand() and
node1 = node2.(AddressOperationNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node2.getType())
or
containerStoreStep(node1, node2, c)
)
or
node1 = node2.(AddressOperationNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node2.getType())
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), cs,
node2.(FlowSummaryNode).getSummaryNode())
or
containerStoreStep(node1, node2, c)
}
/**
@@ -170,20 +172,26 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
* Thus, `node1` references an object with a content `c` whose value ends up in
* `node2`.
*/
predicate readStep(Node node1, ContentSet c, Node node2) {
node1 = node2.(PointerDereferenceNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node1.getType())
or
exists(FieldReadNode read |
node2 = read and
node1 = read.getBase() and
c = any(DataFlow::FieldContent fc | fc.getField() = read.getField())
predicate readStep(Node node1, ContentSet cs, Node node2) {
exists(Content c | cs.asOneContent() = c |
node1 = node2.(PointerDereferenceNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node1.getType())
or
exists(FieldReadNode read |
node2 = read and
node1 = read.getBase() and
c = any(DataFlow::FieldContent fc | fc.getField() = read.getField())
)
or
containerReadStep(node1, node2, c)
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), cs,
node2.(FlowSummaryNode).getSummaryNode())
or
containerReadStep(node1, node2, c)
any(ImplicitFieldReadNode ifrn).shouldImplicitlyReadAllFields(node1) and
cs.isUniversalContent() and
node1 = node2
}
/**

View File

@@ -7,6 +7,7 @@ private import semmle.go.dataflow.FunctionInputsAndOutputs
private import semmle.go.dataflow.ExternalFlow
private import DataFlowPrivate
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.util.Unit
import DataFlowNodes::Public
/**
@@ -50,6 +51,18 @@ abstract class FunctionModel extends Function {
}
}
/**
* A unit class for adding nodes that should implicitly read from all nested content.
*
* For example, this might be appropriate for the argument to a method that serializes a struct.
*/
class ImplicitFieldReadNode extends Unit {
/**
* Holds if the node `n` should implicitly read from all nested content in a taint-tracking context.
*/
abstract predicate shouldImplicitlyReadAllFields(DataFlow::Node n);
}
/**
* Gets the `Node` corresponding to `insn`.
*/
@@ -169,6 +182,11 @@ class Content extends TContent {
) {
filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0
}
/**
* Gets the `ContentSet` contaning only this content.
*/
ContentSet asContentSet() { result.asOneContent() = this }
}
/** A reference through a field. */
@@ -236,21 +254,33 @@ class SyntheticFieldContent extends Content, TSyntheticFieldContent {
override string toString() { result = s.toString() }
}
private newtype TContentSet =
TOneContent(Content c) or
TAllContent()
/**
* 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 instanceof TContentSet {
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent() { result = this }
Content getAStoreContent() { this = TOneContent(result) }
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent() { result = this }
Content getAReadContent() {
this = TOneContent(result)
or
this = TAllContent() and exists(result)
}
/** Gets a textual representation of this content set. */
string toString() { result = super.toString() }
string toString() {
exists(Content c | this = TOneContent(c) | result = c.toString())
or
this = TAllContent() and result = "all content"
}
/**
* Holds if this element is at the specified location.
@@ -262,8 +292,27 @@ class ContentSet instanceof Content {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
exists(Content c | this = TOneContent(c) |
c.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
)
or
this = TAllContent() and
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
/**
* If this is a singleton content set, returns the content.
*/
Content asOneContent() { this = TOneContent(result) }
/**
* Holds if this is a universal content set.
*/
predicate isUniversalContent() { this = TAllContent() }
}
/**

View File

@@ -61,26 +61,28 @@ module Input implements InputSig<Location, DataFlowImplSpecific::GoDataFlow> {
}
string encodeContent(ContentSet cs, string arg) {
exists(Field f, string package, string className, string fieldName |
f = cs.(FieldContent).getField() and
f.hasQualifiedName(package, className, fieldName) and
result = "Field" and
arg = package + "." + className + "." + fieldName
exists(Content c | cs.asOneContent() = c |
exists(Field f, string package, string className, string fieldName |
f = c.(FieldContent).getField() and
f.hasQualifiedName(package, className, fieldName) and
result = "Field" and
arg = package + "." + className + "." + fieldName
)
or
exists(SyntheticField f |
f = c.(SyntheticFieldContent).getField() and result = "SyntheticField" and arg = f
)
or
c instanceof ArrayContent and result = "ArrayElement" and arg = ""
or
c instanceof CollectionContent and result = "Element" and arg = ""
or
c instanceof MapKeyContent and result = "MapKey" and arg = ""
or
c instanceof MapValueContent and result = "MapValue" and arg = ""
or
c instanceof PointerContent and result = "Dereference" and arg = ""
)
or
exists(SyntheticField f |
f = cs.(SyntheticFieldContent).getField() and result = "SyntheticField" and arg = f
)
or
cs instanceof ArrayContent and result = "ArrayElement" and arg = ""
or
cs instanceof CollectionContent and result = "Element" and arg = ""
or
cs instanceof MapKeyContent and result = "MapKey" and arg = ""
or
cs instanceof MapValueContent and result = "MapValue" and arg = ""
or
cs instanceof PointerContent and result = "Dereference" and arg = ""
}
bindingset[token]
@@ -523,7 +525,9 @@ module Private {
SummaryComponent qualifier() { result = argument(-1) }
/** Gets a summary component for field `f`. */
SummaryComponent field(Field f) { result = content(any(FieldContent c | c.getField() = f)) }
SummaryComponent field(Field f) {
result = content(any(FieldContent c | c.getField() = f).asContentSet())
}
/** Gets a summary component that represents the return value of a call. */
SummaryComponent return() { result = SC::return(_) }

View File

@@ -47,10 +47,11 @@ private Type getElementType(Type containerType) {
* of `c` at sinks and inputs to additional taint steps.
*/
bindingset[node]
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet c) {
exists(Type containerType |
predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::ContentSet cs) {
exists(Type containerType, DataFlow::Content c |
node instanceof DataFlow::ArgumentNode and
getElementType*(node.getType()) = containerType
getElementType*(node.getType()) = containerType and
cs.asOneContent() = c
|
containerType instanceof ArrayType and
c instanceof DataFlow::ArrayContent
@@ -142,7 +143,7 @@ predicate elementWriteStep(DataFlow::Node pred, DataFlow::Node succ) {
any(DataFlow::Write w).writesElement(succ.(DataFlow::PostUpdateNode).getPreUpdateNode(), _, pred)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(pred.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), any(DataFlow::Content c | c instanceof DataFlow::ArrayContent),
.getSummaryNode(), any(DataFlow::ArrayContent ac).asContentSet(),
succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode())
}

View File

@@ -21,7 +21,7 @@ module GinCors {
/**
* A write to the value of Access-Control-Allow-Credentials header
*/
class AllowCredentialsWrite extends DataFlow::ExprNode {
class AllowCredentialsWrite extends UniversalAllowCredentialsWrite {
DataFlow::Node base;
AllowCredentialsWrite() {
@@ -35,12 +35,12 @@ module GinCors {
/**
* Get config struct holding header values
*/
DataFlow::Node getBase() { result = base }
override DataFlow::Node getBase() { result = base }
/**
* Get config variable holding header values
*/
GinConfig getConfig() {
override GinConfig getConfig() {
exists(GinConfig gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
@@ -55,7 +55,7 @@ module GinCors {
/**
* A write to the value of Access-Control-Allow-Origins header
*/
class AllowOriginsWrite extends DataFlow::ExprNode {
class AllowOriginsWrite extends UniversalOriginWrite {
DataFlow::Node base;
AllowOriginsWrite() {
@@ -69,12 +69,12 @@ module GinCors {
/**
* Get config struct holding header values
*/
DataFlow::Node getBase() { result = base }
override DataFlow::Node getBase() { result = base }
/**
* Get config variable holding header values
*/
GinConfig getConfig() {
override GinConfig getConfig() {
exists(GinConfig gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
@@ -89,7 +89,7 @@ module GinCors {
/**
* A write to the value of Access-Control-Allow-Origins of value "*", overriding AllowOrigins
*/
class AllowAllOriginsWrite extends DataFlow::ExprNode {
class AllowAllOriginsWrite extends UniversalAllowAllOriginsWrite {
DataFlow::Node base;
AllowAllOriginsWrite() {
@@ -103,12 +103,12 @@ module GinCors {
/**
* Get config struct holding header values
*/
DataFlow::Node getBase() { result = base }
override DataFlow::Node getBase() { result = base }
/**
* Get config variable holding header values
*/
GinConfig getConfig() {
override GinConfig getConfig() {
exists(GinConfig gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =

View File

@@ -0,0 +1,184 @@
/**
* Provides classes for modeling the `github.com/rs/cors` package.
*/
import go
/**
* An abstract class for modeling the Go CORS handler model origin write.
*/
abstract class UniversalOriginWrite extends DataFlow::ExprNode {
/**
* Get config variable holding header values
*/
abstract DataFlow::Node getBase();
/**
* Get config variable holding header values
*/
abstract Variable getConfig();
}
/**
* An abstract class for modeling the Go CORS handler model allow all origins write.
*/
abstract class UniversalAllowAllOriginsWrite extends DataFlow::ExprNode {
/**
* Get config variable holding header values
*/
abstract DataFlow::Node getBase();
/**
* Get config variable holding header values
*/
abstract Variable getConfig();
}
/**
* An abstract class for modeling the Go CORS handler model allow credentials write.
*/
abstract class UniversalAllowCredentialsWrite extends DataFlow::ExprNode {
/**
* Get config struct holding header values
*/
abstract DataFlow::Node getBase();
/**
* Get config variable holding header values
*/
abstract Variable getConfig();
}
/**
* Provides classes for modeling the `github.com/rs/cors` package.
*/
module RsCors {
/** Gets the package name `github.com/gin-gonic/gin`. */
string packagePath() { result = package("github.com/rs/cors", "") }
/**
* A new function create a new rs Handler
*/
class New extends Function {
New() { exists(Function f | f.hasQualifiedName(packagePath(), "New") | this = f) }
}
/**
* A write to the value of Access-Control-Allow-Credentials header
*/
class AllowCredentialsWrite extends UniversalAllowCredentialsWrite {
DataFlow::Node base;
AllowCredentialsWrite() {
exists(Field f, Write w |
f.hasQualifiedName(packagePath(), "Options", "AllowCredentials") and
w.writesField(base, f, this) and
this.getType() instanceof BoolType
)
}
/**
* Get options struct holding header values
*/
override DataFlow::Node getBase() { result = base }
/**
* Get options variable holding header values
*/
override RsOptions getConfig() {
exists(RsOptions gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
base.asInstruction() or
gc.getV().getAUse() = base
) and
result = gc
)
}
}
/**
* A write to the value of Access-Control-Allow-Origins header
*/
class AllowOriginsWrite extends UniversalOriginWrite {
DataFlow::Node base;
AllowOriginsWrite() {
exists(Field f, Write w |
f.hasQualifiedName(packagePath(), "Options", "AllowedOrigins") and
w.writesField(base, f, this) and
this.asExpr() instanceof SliceLit
)
}
/**
* Get options struct holding header values
*/
override DataFlow::Node getBase() { result = base }
/**
* Get options variable holding header values
*/
override RsOptions getConfig() {
exists(RsOptions gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
base.asInstruction() or
gc.getV().getAUse() = base
) and
result = gc
)
}
}
/**
* A write to the value of Access-Control-Allow-Origins of value "*", overriding AllowOrigins
*/
class AllowAllOriginsWrite extends UniversalAllowAllOriginsWrite {
DataFlow::Node base;
AllowAllOriginsWrite() {
exists(Field f, Write w |
f.hasQualifiedName(packagePath(), "Options", "AllowAllOrigins") and
w.writesField(base, f, this) and
this.getType() instanceof BoolType
)
}
/**
* Get options struct holding header values
*/
override DataFlow::Node getBase() { result = base }
/**
* Get options variable holding header values
*/
override RsOptions getConfig() {
exists(RsOptions gc |
(
gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() =
base.asInstruction() or
gc.getV().getAUse() = base
) and
result = gc
)
}
}
/**
* A variable of type Options that holds the headers to be set.
*/
class RsOptions extends Variable {
SsaWithFields v;
RsOptions() {
this = v.getBaseVariable().getSourceVariable() and
exists(Type t | t.hasQualifiedName(packagePath(), "Options") | v.getType() = t)
}
/**
* Get variable declaration of Options
*/
SsaWithFields getV() { result = v }
}
}

View File

@@ -122,7 +122,7 @@ module NetHttp {
|
lastParamIndex = call.getCall().getCalleeType().getNumParameter() - 1 and
varArgsSliceArgument = SummaryComponentStack::argument(lastParamIndex) and
arrayContentSC = SummaryComponent::content(arrayContent) and
arrayContentSC = SummaryComponent::content(arrayContent.asContentSet()) and
stack = SummaryComponentStack::push(arrayContentSC, varArgsSliceArgument)
)
else stack = SummaryComponentStack::argument(n)

View File

@@ -67,4 +67,45 @@ module TextTemplate {
input = inp and output = outp
}
}
private class ExecuteTemplateMethod extends Method {
int inputArg;
ExecuteTemplateMethod() {
exists(string name |
this.hasQualifiedName("text/template", "Template", name) and
(
name = "Execute" and inputArg = 1
or
name = "ExecuteTemplate" and inputArg = 2
)
)
}
int getInputArgIdx() { result = inputArg }
}
private class ExecuteTemplateFieldReader extends DataFlow::ImplicitFieldReadNode {
override predicate shouldImplicitlyReadAllFields(DataFlow::Node n) {
exists(ExecuteTemplateMethod m, DataFlow::MethodCallNode cn |
cn.getTarget() = m and
n = cn.getArgument(m.getInputArgIdx())
)
}
}
private class ExecuteTemplateFunctionModels extends TaintTracking::FunctionModel,
ExecuteTemplateMethod
{
FunctionInput inp;
FunctionOutput outp;
ExecuteTemplateFunctionModels() {
inp.isParameter(this.getInputArgIdx()) and outp.isParameter(0)
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
}

View File

@@ -72,7 +72,7 @@ module UntrustedToAllowOriginHeaderConfig implements DataFlow::ConfigSig {
module UntrustedToAllowOriginConfigConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
additional predicate isSinkWrite(DataFlow::Node sink, GinCors::AllowOriginsWrite w) { sink = w }
additional predicate isSinkWrite(DataFlow::Node sink, UniversalOriginWrite w) { sink = w }
predicate isSink(DataFlow::Node sink) { isSinkWrite(sink, _) }
}
@@ -102,17 +102,17 @@ predicate allowCredentialsIsSetToTrue(DataFlow::ExprNode allowOriginHW) {
allowCredentialsHW.getResponseWriter()
)
or
exists(GinCors::AllowCredentialsWrite allowCredentialsGin |
exists(UniversalAllowCredentialsWrite allowCredentialsGin |
allowCredentialsGin.getExpr().getBoolValue() = true
|
allowCredentialsGin.getConfig() = allowOriginHW.(GinCors::AllowOriginsWrite).getConfig() and
not exists(GinCors::AllowAllOriginsWrite allowAllOrigins |
allowCredentialsGin.getConfig() = allowOriginHW.(UniversalOriginWrite).getConfig() and
not exists(UniversalAllowAllOriginsWrite allowAllOrigins |
allowAllOrigins.getExpr().getBoolValue() = true and
allowCredentialsGin.getConfig() = allowAllOrigins.getConfig()
)
or
allowCredentialsGin.getBase() = allowOriginHW.(GinCors::AllowOriginsWrite).getBase() and
not exists(GinCors::AllowAllOriginsWrite allowAllOrigins |
allowCredentialsGin.getBase() = allowOriginHW.(UniversalOriginWrite).getBase() and
not exists(UniversalAllowAllOriginsWrite allowAllOrigins |
allowAllOrigins.getExpr().getBoolValue() = true and
allowCredentialsGin.getBase() = allowAllOrigins.getBase()
)
@@ -150,7 +150,7 @@ predicate allowOriginIsNull(DataFlow::ExprNode allowOriginHW, string message) {
+ " is set to `true`"
or
allowOriginHW
.(GinCors::AllowOriginsWrite)
.(UniversalOriginWrite)
.asExpr()
.(SliceLit)
.getAnElement()

View File

@@ -1,5 +1,5 @@
name: codeql/go-queries
version: 1.1.6
version: 1.1.7-dev
groups:
- go
- queries

View File

@@ -5,3 +5,4 @@
| CorsMisconfiguration.go:53:4:53:44 | call to Set | access-control-allow-origin header is set to a user-defined value, and access-control-allow-credentials is set to `true` |
| CorsMisconfiguration.go:60:4:60:56 | call to Set | access-control-allow-origin header is set to a user-defined value, and access-control-allow-credentials is set to `true` |
| CorsMisconfiguration.go:67:5:67:57 | call to Set | access-control-allow-origin header is set to a user-defined value, and access-control-allow-credentials is set to `true` |
| RsCors.go:11:21:11:59 | slice literal | access-control-allow-origin header is set to `null`, and access-control-allow-credentials is set to `true` |

View File

@@ -0,0 +1,39 @@
package main
import (
"net/http"
"github.com/rs/cors"
)
func rs_vulnerable() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"null", "http://foo.com:8080"},
AllowCredentials: true,
// Enable Debugging for testing, consider disabling in production
Debug: true,
})
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
http.ListenAndServe(":8080", c.Handler(handler))
}
func rs_safe() {
c := cors.New(cors.Options{
AllowedOrigins: []string{"http://foo.com:8080"},
AllowCredentials: true,
// Enable Debugging for testing, consider disabling in production
Debug: true,
})
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
http.ListenAndServe(":8080", c.Handler(handler))
}

View File

@@ -5,6 +5,7 @@ go 1.21
require (
github.com/gin-contrib/cors v1.4.0
github.com/gin-gonic/gin v1.9.1
github.com/rs/cors v1.10.1
)
require (

View File

@@ -0,0 +1,53 @@
// Code generated by depstubber. DO NOT EDIT.
// This is a simple stub for github.com/rs/cors, strictly for use in testing.
// See the LICENSE file for information about the licensing of the original library.
// Source: github.com/rs/cors (exports: Options; functions: New)
// Package cors is a stub of github.com/rs/cors, generated by depstubber.
package cors
import (
http "net/http"
)
type Cors struct {
Log Logger
}
func (_ *Cors) Handler(_ http.Handler) http.Handler {
return nil
}
func (_ *Cors) HandlerFunc(_ http.ResponseWriter, _ *http.Request) {}
func (_ *Cors) OriginAllowed(_ *http.Request) bool {
return false
}
func (_ *Cors) ServeHTTP(_ http.ResponseWriter, _ *http.Request, _ http.HandlerFunc) {}
type Logger interface {
Printf(_ string, _ ...interface{})
}
func New(_ Options) *Cors {
return nil
}
type Options struct {
AllowedOrigins []string
AllowOriginFunc func(string) bool
AllowOriginRequestFunc func(*http.Request, string) bool
AllowOriginVaryRequestFunc func(*http.Request, string) (bool, []string)
AllowedMethods []string
AllowedHeaders []string
ExposedHeaders []string
MaxAge int
AllowCredentials bool
AllowPrivateNetwork bool
OptionsPassthrough bool
OptionsSuccessStatus int
Debug bool
Logger Logger
}

View File

@@ -4,6 +4,9 @@ github.com/gin-contrib/cors
# github.com/gin-gonic/gin v1.9.1
## explicit
github.com/gin-gonic/gin
# github.com/rs/cors v1.10.1
## explicit
github.com/rs/cors
# github.com/bytedance/sonic v1.9.1
## explicit
github.com/bytedance/sonic

View File

@@ -0,0 +1,9 @@
import go
import utils.test.InlineFlowTest
string getArgString(DataFlow::Node src, DataFlow::Node sink) {
exists(sink) and
result = src.(DataFlow::CallNode).getArgument(0).getExactValue()
}
import TaintFlowTestArgString<DefaultFlowConfig, getArgString/2>

View File

@@ -0,0 +1,60 @@
package xyz
import (
"bytes"
"text/template"
)
type Inner1 struct {
Data string
}
type Inner2 struct {
Data string
}
type Inner3 struct {
Data string
}
type HasInner3Slice struct {
Slice []Inner3
}
type Outer struct {
SliceField []Inner1
PtrField *Inner2
MapField map[string]Inner3
DeepField HasInner3Slice
}
func source(n int) string { return "dummy" }
func sink(arg any) {}
func test() {
source1 := source(1)
source2 := source(2)
source3 := source(3)
source4 := source(4)
toSerialize := Outer{[]Inner1{{source1}}, &Inner2{source2}, map[string]Inner3{"key": {source3}},
HasInner3Slice{[]Inner3{{source4}}}}
buff1 := new(bytes.Buffer)
buff2 := new(bytes.Buffer)
bytes1 := make([]byte, 10)
bytes2 := make([]byte, 10)
tmpl, _ := template.New("test").Parse("Template text goes here (irrelevant for test)")
tmpl.ExecuteTemplate(buff1, "test", toSerialize)
buff1.Read(bytes1)
sink(bytes1) // $ hasTaintFlow=1 hasTaintFlow=2 hasTaintFlow=3 hasTaintFlow=4
// Read `buff2` via an `any`-typed variable, to ensure the static type of the argument to tmpl.Execute makes no difference to the result
var toSerializeAsAny any
toSerializeAsAny = toSerialize
tmpl.Execute(buff2, toSerializeAsAny)
buff2.Read(bytes2)
sink(bytes2) // $ hasTaintFlow=1 hasTaintFlow=2 hasTaintFlow=3 hasTaintFlow=4
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Add databaseMetadata relation
compatibility: full
databaseMetadata.rel: delete

BIN
java/kotlin-extractor/deps/kotlin-compiler-2.1.20-Beta1.jar (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
java/kotlin-extractor/deps/kotlin-stdlib-2.1.20-Beta1.jar (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -25,7 +25,19 @@ import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyFunction
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.types.typeWithArguments
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrStarProjection
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
@@ -2293,7 +2305,7 @@ open class KotlinFileExtractor(
// synthesised and inherit the annotation from the delegate (which given it has
// @NotNull, is likely written in Java)
JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.takeUnless {
t.isNullable() ||
t.isNullableCodeQL() ||
primitiveTypeMapping.getPrimitiveInfo(t) != null ||
hasExistingAnnotation(it)
}
@@ -3975,7 +3987,7 @@ open class KotlinFileExtractor(
target.parent
} else {
val st = extensionReceiverParameter.type as? IrSimpleType
if (isNullable != null && st?.isNullable() != isNullable) {
if (isNullable != null && st?.isNullableCodeQL() != isNullable) {
verboseln("Nullablility of type didn't match")
return false
}
@@ -4621,9 +4633,9 @@ open class KotlinFileExtractor(
val isPrimitiveArrayCreation = !isBuiltinCallKotlin(c, "arrayOf")
val elementType =
if (isPrimitiveArrayCreation) {
c.type.getArrayElementType(pluginContext.irBuiltIns)
c.type.getArrayElementTypeCodeQL(pluginContext.irBuiltIns)
} else {
// TODO: is there any reason not to always use getArrayElementType?
// TODO: is there any reason not to always use getArrayElementTypeCodeQL?
if (c.typeArgumentsCount == 1) {
c.getTypeArgument(0).also {
if (it == null) {

View File

@@ -12,7 +12,24 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.addAnnotations
import org.jetbrains.kotlin.ir.types.classFqName
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.types.isNullableAny
import org.jetbrains.kotlin.ir.types.isPrimitiveType
import org.jetbrains.kotlin.ir.types.makeNullable
import org.jetbrains.kotlin.ir.types.typeOrNull
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.types.typeWithArguments
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrErrorType
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrStarProjection
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
@@ -679,7 +696,7 @@ open class KotlinUsesExtractor(
private fun getInvariantNullableArrayType(arrayType: IrSimpleType): IrSimpleType =
if (arrayType.isPrimitiveArray()) arrayType
else {
val componentType = arrayType.getArrayElementType(pluginContext.irBuiltIns)
val componentType = arrayType.getArrayElementTypeCodeQL(pluginContext.irBuiltIns)
val componentTypeBroadened =
when (componentType) {
is IrSimpleType ->
@@ -690,7 +707,7 @@ open class KotlinUsesExtractor(
val unchanged =
componentType == componentTypeBroadened &&
(arrayType.arguments[0] as? IrTypeProjection)?.variance == Variance.INVARIANT &&
componentType.isNullable()
componentType.isNullableCodeQL()
if (unchanged) arrayType
else
IrSimpleTypeImpl(
@@ -705,7 +722,7 @@ open class KotlinUsesExtractor(
Kotlin arrays can be broken down as:
isArray(t)
|- t.isBoxedArray
|- t.isBoxedArrayCodeQL
| |- t.isArray() e.g. Array<Boolean>, Array<Boolean?>
| |- t.isNullableArray() e.g. Array<Boolean>?, Array<Boolean?>?
|- t.isPrimitiveArray() e.g. BooleanArray
@@ -715,7 +732,7 @@ open class KotlinUsesExtractor(
Primitive arrays are represented as e.g. boolean[].
*/
private fun isArray(t: IrType) = t.isBoxedArray || t.isPrimitiveArray()
private fun isArray(t: IrType) = t.isBoxedArrayCodeQL || t.isPrimitiveArray()
data class ArrayInfo(
val elementTypeResults: TypeResults,
@@ -756,7 +773,7 @@ open class KotlinUsesExtractor(
) {
pluginContext.irBuiltIns.anyType
} else {
t.getArrayElementType(pluginContext.irBuiltIns)
t.getArrayElementTypeCodeQL(pluginContext.irBuiltIns)
}
val recInfo = useArrayType(elementType, t.isPrimitiveArray())
@@ -844,7 +861,7 @@ open class KotlinUsesExtractor(
if (
(context == TypeContext.RETURN ||
(context == TypeContext.OTHER && otherIsPrimitive)) &&
!s.isNullable() &&
!s.isNullableCodeQL() &&
getKotlinType(s)?.hasEnhancedNullability() != true &&
primitiveName != null
) {
@@ -860,7 +877,7 @@ open class KotlinUsesExtractor(
val kotlinClassId = useClassInstance(kotlinClass, listOf()).typeResult.id
val kotlinResult =
if (true) TypeResult(fakeKotlinType(), "TODO", "TODO")
else if (s.isNullable()) {
else if (s.isNullableCodeQL()) {
val kotlinSignature =
"$kotlinPackageName.$kotlinClassName?" // TODO: Is this right?
val kotlinLabel = "@\"kt_type;nullable;$kotlinPackageName.$kotlinClassName\""
@@ -902,21 +919,21 @@ open class KotlinUsesExtractor(
return extractErrorType()
}
}
(s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
(s.isBoxedArrayCodeQL && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
val arrayInfo = useArrayType(s, false)
return arrayInfo.componentTypeResults
}
owner is IrClass -> {
val args = if (s.codeQlIsRawType()) null else s.arguments
return useSimpleTypeClass(owner, args, s.isNullable())
return useSimpleTypeClass(owner, args, s.isNullableCodeQL())
}
owner is IrTypeParameter -> {
val javaResult = useTypeParameter(owner)
val aClassId = makeClass("kotlin", "TypeParam") // TODO: Wrong
val kotlinResult =
if (true) TypeResult(fakeKotlinType(), "TODO", "TODO")
else if (s.isNullable()) {
else if (s.isNullableCodeQL()) {
val kotlinSignature = "${javaResult.signature}?" // TODO: Wrong
val kotlinLabel = "@\"kt_type;nullable;type_param\"" // TODO: Wrong
val kotlinId: Label<DbKt_nullable_type> =
@@ -1200,7 +1217,7 @@ open class KotlinUsesExtractor(
}
private fun extendsAdditionAllowed(t: IrType) =
if (t.isBoxedArray) {
if (t.isBoxedArrayCodeQL) {
if (t is IrSimpleType) {
arrayExtendsAdditionAllowed(t)
} else {
@@ -1493,7 +1510,7 @@ open class KotlinUsesExtractor(
}
} else {
t.classOrNull?.let { tCls ->
if (t.isBoxedArray) {
if (t.isBoxedArrayCodeQL) {
(t.arguments.singleOrNull() as? IrTypeProjection)?.let { elementTypeArg
->
val elementType = elementTypeArg.type
@@ -1506,7 +1523,7 @@ open class KotlinUsesExtractor(
)
return tCls
.typeWithArguments(listOf(newArg))
.codeQlWithHasQuestionMark(t.isNullable())
.codeQlWithHasQuestionMark(t.isNullableCodeQL())
}
}
}
@@ -2086,12 +2103,12 @@ open class KotlinUsesExtractor(
}
if (owner is IrClass) {
if (t.isBoxedArray) {
val elementType = t.getArrayElementType(pluginContext.irBuiltIns)
if (t.isBoxedArrayCodeQL) {
val elementType = t.getArrayElementTypeCodeQL(pluginContext.irBuiltIns)
val erasedElementType = erase(elementType)
return owner
.typeWith(erasedElementType)
.codeQlWithHasQuestionMark(t.isNullable())
.codeQlWithHasQuestionMark(t.isNullableCodeQL())
}
return if (t.arguments.isNotEmpty())

View File

@@ -5,7 +5,7 @@ import com.github.codeql.utils.versions.*
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.fir.java.JavaBinarySourceElement
import org.jetbrains.kotlin.fir.java.VirtualFileBasedSourceElement
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
@@ -89,8 +89,8 @@ fun getIrClassVirtualFile(irClass: IrClass): VirtualFile? {
is BinaryJavaClass -> return element.virtualFile
}
}
is JavaBinarySourceElement -> {
return cSource.javaClass.virtualFile
is VirtualFileBasedSourceElement -> {
return cSource.virtualFile
}
is KotlinJvmBinarySourceElement -> {
val binaryClass = cSource.binaryClass

View File

@@ -5,6 +5,7 @@ import com.github.codeql.Logger
import com.github.codeql.getJavaEquivalentClassId
import com.github.codeql.utils.versions.codeQlWithHasQuestionMark
import com.github.codeql.utils.versions.createImplicitParameterDeclarationWithWrappedDescriptor
import com.github.codeql.utils.versions.*
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
@@ -18,15 +19,18 @@ import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.types.addAnnotations
import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrStarProjection
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeArgument
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.constructedClassType
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.kotlinFqName
import org.jetbrains.kotlin.ir.util.parents
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance
@@ -57,7 +61,7 @@ private fun IrSimpleType.substituteTypeArguments(
}
}
return IrSimpleTypeImpl(classifier, isNullable(), newArguments, annotations)
return IrSimpleTypeImpl(classifier, isNullableCodeQL(), newArguments, annotations)
}
/**
@@ -96,7 +100,7 @@ private fun subProjectedType(
else {
val newProjectedType =
substitutedTypeArg.type.let {
if (t.isNullable()) it.codeQlWithHasQuestionMark(true) else it
if (t.isNullableCodeQL()) it.codeQlWithHasQuestionMark(true) else it
}
val newVariance = combineVariance(outerVariance, substitutedTypeArg.variance)
makeTypeProjection(newProjectedType, newVariance)
@@ -113,7 +117,7 @@ private fun IrTypeArgument.upperBound(context: IrPluginContext) =
when (this.variance) {
Variance.INVARIANT -> this.type
Variance.IN_VARIANCE ->
if (this.type.isNullable()) context.irBuiltIns.anyNType
if (this.type.isNullableCodeQL()) context.irBuiltIns.anyNType
else context.irBuiltIns.anyType
Variance.OUT_VARIANCE -> this.type
}
@@ -128,7 +132,7 @@ private fun IrTypeArgument.lowerBound(context: IrPluginContext) =
Variance.INVARIANT -> this.type
Variance.IN_VARIANCE -> this.type
Variance.OUT_VARIANCE ->
if (this.type.isNullable()) context.irBuiltIns.nothingNType
if (this.type.isNullableCodeQL()) context.irBuiltIns.nothingNType
else context.irBuiltIns.nothingType
}
else -> context.irBuiltIns.nothingType
@@ -211,7 +215,7 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
this.type.let {
when (it) {
is IrSimpleType ->
if (it.isNullable() == b) this
if (it.isNullableCodeQL() == b) this
else makeTypeProjection(it.codeQlWithHasQuestionMark(b), this.variance)
else -> this
}

View File

@@ -0,0 +1,5 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
typealias IrBuiltIns = IrBuiltIns

View File

@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.fir.java
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
@@ -7,5 +8,6 @@ import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
We need this class to exist, but the compiler will never give us an
instance of it.
*/
abstract class JavaBinarySourceElement private constructor(val javaClass: BinaryJavaClass) :
SourceElement {}
abstract class VirtualFileBasedSourceElement private constructor(val javaClass: BinaryJavaClass) : SourceElement {
abstract val virtualFile: VirtualFile
}

View File

@@ -0,0 +1,11 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.types.*
fun IrType.isNullableCodeQL(): Boolean =
this.isNullable()
val IrType.isBoxedArrayCodeQL: Boolean by IrType::isBoxedArray
fun IrType.getArrayElementTypeCodeQL(irBuiltIns: IrBuiltIns): IrType =
this.getArrayElementType(irBuiltIns)

View File

@@ -0,0 +1,5 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.ir.IrBuiltIns
typealias IrBuiltIns = org.jetbrains.kotlin.ir.IrBuiltIns

View File

@@ -1,3 +0,0 @@
/*
The compiler provides this class, so we don't have to do anything.
*/

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