Compare commits

..

86 Commits

Author SHA1 Message Date
Napalys Klicius
d3d608fa33 Updated query description and added a sanitizer 2025-09-04 13:16:37 +00:00
Napalys Klicius
6c751ce934 Merged config classes 2025-09-04 12:31:24 +00:00
Napalys Klicius
4dac80a998 Replace complex wrapper classes with MaD 2025-09-04 12:19:22 +00:00
Napalys Klicius
021aa13ee2 Added change note 2025-07-31 12:45:34 +02:00
Napalys Klicius
791a7e242e Updated qhelp for cors permissive configuration 2025-07-31 11:31:10 +02:00
Napalys Klicius
2baca58b27 Removed deprecations from cors as it was moved out experimental 2025-07-31 11:08:22 +02:00
Napalys Klicius
fd4233e30e Moved apollo modeling to MaD 2025-07-31 10:58:38 +02:00
Napalys Klicius
84ffbbec33 Added missing doc strings 2025-07-30 10:51:38 +00:00
Napalys Klicius
95743d7109 Added inline test expectations for cors permissive config 2025-07-30 10:42:55 +00:00
Napalys Klicius
92daa7d42c Updated suite expectations 2025-07-30 10:32:11 +00:00
Napalys Klicius
358617f533 Move CORS misconfiguration query from experimental to Security 2025-07-30 10:22:59 +00:00
Idriss Riouak
6c00ceaec9 Merge pull request #20134 from github/idrissrio/java-dca-fix
Java: Move `extractorInformationSkipKey` predicate to library pack
2025-07-29 15:32:02 +01:00
idrissrio
ac52a1b123 Java: Move extractorInformationSkipKey predicate to library pack 2025-07-29 09:45:18 +02:00
Simon Friis Vindum
9d72fab287 Merge pull request #20119 from paldepind/rust/type-inference-assoc-type-tp
Rust: Type inference for impl trait types with type parameters
2025-07-28 11:38:17 +02:00
Simon Friis Vindum
92bce4e432 Rust: Split getFunctionReturnPos into two predicates 2025-07-28 10:45:59 +02:00
Simon Friis Vindum
9761580b7e Merge branch 'main' into rust/type-inference-assoc-type-tp 2025-07-28 10:39:00 +02:00
Anders Schack-Mulligen
37b508bf43 Merge pull request #20128 from aschackmull/ccr/del-formatting-instruction
Copilot: Remove the formatting instructions, as they're confusing CCR.
2025-07-28 10:24:30 +02:00
Simon Friis Vindum
13d9d8ad3f Merge pull request #20122 from paldepind/rust/type-inference-dyn-assoc
Rust: Fix type inference for trait objects for traits with associated types
2025-07-26 12:40:09 +02:00
Geoffrey White
4b947db0f8 Merge pull request #19804 from geoffw0/dotdot
Rust: Update DotDotCheck to use getCanonicalPath
2025-07-25 15:50:29 +01:00
Geoffrey White
2951ae9c7c Merge pull request #20124 from geoffw0/clone
Rust: Replace QL model for Clone with MaD
2025-07-25 15:46:44 +01:00
Simon Friis Vindum
b2ee625268 Rust: Expand doc and make predicate private 2025-07-25 15:22:10 +02:00
Geoffrey White
478f39a967 Rust: Accept (trivial) test changes. 2025-07-25 14:18:34 +01:00
Anders Schack-Mulligen
6511e21f81 Remove the formatting instructions, as they're confusing CCR. 2025-07-25 14:59:16 +02:00
Geoffrey White
2192ed04be Rust: Add clone MaD trait model. 2025-07-25 09:43:34 +01:00
Geoffrey White
4140579dd6 Rust: Remove QL model for clone. 2025-07-25 08:17:52 +01:00
Geoffrey White
7f659804e4 Rust: Fix the canonical path. 2025-07-24 17:24:29 +01:00
Geoffrey White
cfe25593ee Merge branch 'main' into dotdot 2025-07-24 16:32:36 +01:00
Simon Friis Vindum
466bf85a67 Rust: Fix type inference for trait objects for traits with associated types 2025-07-24 16:07:39 +02:00
Simon Friis Vindum
1b2f160b55 Rust: Add type inference tests for associated types 2025-07-24 16:07:37 +02:00
Joe Farebrother
b1ee795225 Merge pull request #20086 from joefarebrother/python-qual-raise-not-implemented
Python: Modernise raise-not-implemented query
2025-07-24 13:18:21 +01:00
Ian Lynagh
621b4833f3 Merge pull request #20114 from igfoo/igfoo/kotlin-2.2.20
Kotlin: Add Kotlin 2.2.20 support
2025-07-24 11:58:51 +01:00
Simon Friis Vindum
39f602c032 Rust: Create injective ids for impl trait type parameters 2025-07-24 12:07:11 +02:00
Simon Friis Vindum
bb56b0d45b Rust: Add type inference test with consistency issue 2025-07-24 11:55:23 +02:00
Simon Friis Vindum
9a0c5877ea Rust: Support impl trait types in return position with function type parameters 2025-07-24 11:00:01 +02:00
Joe Farebrother
97cf15affc Merge pull request #20052 from joefarebrother/python-qual-minor-doc-updates
Python: Minor documantation updates to several quality queries
2025-07-24 09:38:07 +01:00
Simon Friis Vindum
a20fed8ae5 Rust: Add type inference tests for impl trait types 2025-07-24 10:36:51 +02:00
Joe Farebrother
a8cc14493f Fix typo - add .
Co-authored-by: Napalys Klicius <napalys@github.com>
2025-07-24 09:35:05 +01:00
Simon Friis Vindum
82387461ee Merge pull request #20084 from paldepind/rust/type-inference-trait-object
Rust: Implement type inference for trait objects/`dyn` types
2025-07-24 10:17:23 +02:00
Simon Friis Vindum
b3dc6cba78 Rust: Use getATypeParam for consistency 2025-07-23 20:56:45 +02:00
Mathias Vorreiter Pedersen
5da7ae877b Merge pull request #20115 from MathiasVP/add-more-windows-memcpy-functions
C++: Add some more Windows specific memory copy models
2025-07-23 16:10:56 +01:00
Geoffrey White
199f2473e5 Merge pull request #20024 from geoffw0/moresensitive2
Shared: Improve sensitive data heuristics
2025-07-23 15:38:24 +01:00
Nora Dimitrijević
5f8c457295 Merge pull request #20081 from d10c/d10c/diff-informed-phase-3-rust
Rust: Diff-informed queries: phase 3 (non-trivial locations)
2025-07-23 16:31:23 +02:00
Mathias Vorreiter Pedersen
cbe5561eb6 C++: Accept test changes. 2025-07-23 14:05:42 +01:00
Nora Dimitrijević
83fe9e0d51 [DIFF-INFORMED] Rust: AccessInvalidPointer 2025-07-23 14:52:44 +02:00
Nora Dimitrijević
31a73d466b [DIFF-INFORMED] Rust: AccessAfterLifetime 2025-07-23 14:52:32 +02:00
Nora Dimitrijević
56ae8684e1 [DIFF-INFORMED] Rust: UncontrolledAllocationSize 2025-07-23 14:52:14 +02:00
Nora Dimitrijević
fcc3800756 [DIFF-INFORMED] Rust: CleartextLogging 2025-07-23 14:52:07 +02:00
Nora Dimitrijević
091163bf8e [DIFF-INFORMED] Rust: CleartextTransmission 2025-07-23 14:52:00 +02:00
Nora Dimitrijević
78c40e209b [DIFF-INFORMED] Rust: SqlInjection 2025-07-23 14:51:52 +02:00
Nora Dimitrijević
574bb871e0 [DIFF-INFORMED] Rust: TaintedPath 2025-07-23 14:51:45 +02:00
Nora Dimitrijević
329fd803e2 [DIFF-INFORMED] Rust: RegexInjection 2025-07-23 14:51:33 +02:00
Mathias Vorreiter Pedersen
9d736723fb C++: Add more Windows specific models for memcpy-like tings. 2025-07-23 13:45:20 +01:00
Mathias Vorreiter Pedersen
50785f7f21 C++: Add tests with missing flow. 2025-07-23 13:37:32 +01:00
Simon Friis Vindum
f5605c94c5 Rust: Add change note for type inference of trait objects 2025-07-23 14:08:22 +02:00
Simon Friis Vindum
12942667bf Rust: Add type inference for dyn types 2025-07-23 14:08:15 +02:00
Simon Friis Vindum
605c8e201e Rust: Add type inference tests for dyn types 2025-07-23 14:03:53 +02:00
Ian Lynagh
604af65b02 Kotlin: Opt in to DeprecatedForRemovalCompilerApi
We'll need a proper fix for this, but this will keep things working in
the meantime.
2025-07-23 12:51:12 +01:00
Ian Lynagh
709c111522 Kotlin: Add getJvmModuleNameForDeserializedDescriptor wrapper
It has been removed in 2.2.20.
2025-07-23 12:51:12 +01:00
Ian Lynagh
d1da041fcf Kotlin: Regenerate
Ran "../tools/bazel mod tidy"
2025-07-23 11:53:06 +01:00
Ian Lynagh
8432f6e42e Kotlin: Add 2.2.20-Beta1 version 2025-07-23 11:52:48 +01:00
Ian Lynagh
965f1fc547 Kotlin: Add 2.2.20 deps 2025-07-23 11:51:45 +01:00
Ian Lynagh
f148f434e1 Kotlin: Add a changenote for the addition of 2.2.2x support 2025-07-23 11:49:38 +01:00
Ian Lynagh
ad391df03f Kotlin: Support 2.2.20 2025-07-23 11:47:52 +01:00
Geoffrey White
68f0dfe046 Shared: Fix after merge. 2025-07-23 08:55:44 +01:00
Geoffrey White
4f6b698ca3 Merge branch 'main' into moresensitive2 2025-07-23 08:50:25 +01:00
Joe Farebrother
8ccb2ed059 Merge remote-tracking branch 'origin/python-qual-raise-not-implemented' into python-qual-raise-not-implemented 2025-07-18 10:05:40 +01:00
Joe Farebrother
6d33a7ec70 Update test output 2025-07-17 22:25:18 +01:00
Joe Farebrother
f2dd96ecf4 Update python/ql/src/Exceptions/NotImplementedIsNotAnException.qhelp
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-17 22:08:01 +01:00
Joe Farebrother
57f1d07b2b Undo module deprecation (used by another quality query) 2025-07-17 21:54:55 +01:00
Joe Farebrother
680e31dc48 Modernize raise-not-implemented 2025-07-17 10:02:00 +01:00
Joe Farebrother
0f5be2d096 Update python/ql/src/Expressions/DuplicateKeyInDictionaryLiteral.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-15 13:33:57 +01:00
Joe Farebrother
909f57261c Minor doc updates; updating python 2 references to python 3 and updating grammar 2025-07-15 13:26:46 +01:00
Joe Farebrother
7a7db0efe8 Update unsupported format character documentaion, fix outdated reference link 2025-07-15 10:42:25 +01:00
Joe Farebrother
df5f76872f Update docs for duplicate-key-in-dict-literal to relate. to python 3 2025-07-15 10:18:29 +01:00
Geoffrey White
918700ff6f Merge branch 'main' into moresensitive2 2025-07-14 11:58:08 +01:00
Geoffrey White
da0742f3ec Rust: Update path resolution consistency .expected. 2025-07-14 11:45:45 +01:00
Geoffrey White
30c6082b5d Sync identical files. 2025-07-14 11:45:34 +01:00
Geoffrey White
e121579a85 Rust: Adjust the test labels slightly. 2025-07-14 11:19:31 +01:00
Geoffrey White
9f59a3501c Rust: Revert ipaddr and fingerprint terms (too many FPs). 2025-07-14 11:17:09 +01:00
Geoffrey White
4778ef616a Rust: Add a test case for password_confirmation. 2025-07-11 15:43:31 +01:00
Geoffrey White
8f6f9f4359 Add change notes. 2025-07-11 11:54:59 +01:00
Geoffrey White
123458fd21 Sync identical files. 2025-07-10 18:10:24 +01:00
Geoffrey White
a6b4a18d51 Rust: Add negative patterns. 2025-07-10 13:56:14 +01:00
Geoffrey White
8f95e26ed6 Rust: Combine regexs where possible (likely better performance). 2025-07-10 13:56:12 +01:00
Geoffrey White
99e62d66e5 Rust: Add sensitive data patterns. 2025-07-10 13:56:11 +01:00
Geoffrey White
cd6975f7b7 Rust: Update DotDotCheck from getResolvedPath -> getCanonicalPath. 2025-06-17 17:07:39 +01:00
111 changed files with 4798 additions and 3959 deletions

View File

@@ -2,10 +2,3 @@ When reviewing code:
* do not review changes in files with `.expected` extension (they are automatically ensured to be correct).
* in `.ql` and `.qll` files, do not try to review the code itself as you don't understand the programming language
well enough to make comments in these languages. You can still check for typos or comment improvements.
When editing `.ql` and `.qll` files:
* All edited `.ql` and `.qll` files should be autoformatted afterwards using the CodeQL CLI.
* To install and use the CodeQL CLI autoformatter:
1. Download and extract CodeQL CLI: `cd /tmp && curl -L -o codeql-linux64.zip https://github.com/github/codeql-cli-binaries/releases/latest/download/codeql-linux64.zip && unzip -q codeql-linux64.zip`
2. Add to PATH: `export PATH="/tmp/codeql:$PATH"`
3. Run autoformatter: `codeql query format [file] --in-place`

View File

@@ -230,6 +230,7 @@ use_repo(
"kotlin-compiler-2.1.0-Beta1",
"kotlin-compiler-2.1.20-Beta1",
"kotlin-compiler-2.2.0-Beta1",
"kotlin-compiler-2.2.20-Beta1",
"kotlin-compiler-embeddable-1.6.0",
"kotlin-compiler-embeddable-1.6.20",
"kotlin-compiler-embeddable-1.7.0",
@@ -242,6 +243,7 @@ use_repo(
"kotlin-compiler-embeddable-2.1.0-Beta1",
"kotlin-compiler-embeddable-2.1.20-Beta1",
"kotlin-compiler-embeddable-2.2.0-Beta1",
"kotlin-compiler-embeddable-2.2.20-Beta1",
"kotlin-stdlib-1.6.0",
"kotlin-stdlib-1.6.20",
"kotlin-stdlib-1.7.0",
@@ -254,6 +256,7 @@ use_repo(
"kotlin-stdlib-2.1.0-Beta1",
"kotlin-stdlib-2.1.20-Beta1",
"kotlin-stdlib-2.2.0-Beta1",
"kotlin-stdlib-2.2.20-Beta1",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")

View File

@@ -36,4 +36,14 @@ extensions:
# processthreadsapi.h
- ["", "", False, "CreateThread", "", "", "Argument[@3]", "Argument[2].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThread", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
- ["", "", False, "CreateRemoteThreadEx", "", "", "Argument[@4]", "Argument[3].Parameter[@0]", "value", "manual"]
# wdm.h
- ["", "", False, "RtlCopyVolatileMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyDeviceMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyMemoryNonTemporal", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlCopyUnicodeString", "", "", "Argument[*1].Field[*Buffer]", "Argument[*0].Field[*Buffer]", "value", "manual"]
- ["", "", False, "RtlMoveMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
- ["", "", False, "RtlMoveVolatileMemory", "", "", "Argument[*@1]", "Argument[*@0]", "value", "manual"]
# winternl.h
- ["", "", False, "RtlInitUnicodeString", "", "", "Argument[*1]", "Argument[*0].Field[*Buffer]", "value", "manual"]

View File

@@ -21,14 +21,22 @@ models
| 20 | Summary: ; ; false; CreateRemoteThreadEx; ; ; Argument[@4]; Argument[3].Parameter[@0]; value; manual |
| 21 | Summary: ; ; false; CreateThread; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 22 | Summary: ; ; false; ReadFileEx; ; ; Argument[*3].Field[@hEvent]; Argument[4].Parameter[*2].Field[@hEvent]; value; manual |
| 23 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
| 24 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 25 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 26 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 27 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 28 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
| 23 | Summary: ; ; false; RtlCopyDeviceMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 24 | Summary: ; ; false; RtlCopyMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 25 | Summary: ; ; false; RtlCopyMemoryNonTemporal; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 26 | Summary: ; ; false; RtlCopyUnicodeString; ; ; Argument[*1].Field[*Buffer]; Argument[*0].Field[*Buffer]; value; manual |
| 27 | Summary: ; ; false; RtlCopyVolatileMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 28 | Summary: ; ; false; RtlInitUnicodeString; ; ; Argument[*1]; Argument[*0].Field[*Buffer]; value; manual |
| 29 | Summary: ; ; false; RtlMoveMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 30 | Summary: ; ; false; RtlMoveVolatileMemory; ; ; Argument[*@1]; Argument[*@0]; value; manual |
| 31 | Summary: ; ; false; callWithArgument; ; ; Argument[1]; Argument[0].Parameter[0]; value; manual |
| 32 | Summary: ; ; false; pthread_create; ; ; Argument[@3]; Argument[2].Parameter[@0]; value; manual |
| 33 | Summary: ; ; false; ymlStepGenerated; ; ; Argument[0]; ReturnValue; taint; df-generated |
| 34 | Summary: ; ; false; ymlStepManual; ; ; Argument[0]; ReturnValue; taint; manual |
| 35 | Summary: ; ; false; ymlStepManual_with_body; ; ; Argument[0]; ReturnValue; taint; manual |
| 36 | Summary: boost::asio; ; false; buffer; ; ; Argument[*0]; ReturnValue; taint; manual |
edges
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:28 |
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:36 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:17 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:17 Sink:MaD:2 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
@@ -37,10 +45,10 @@ edges
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:2 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:28 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:26 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:25 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:27 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:36 |
| test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | provenance | MaD:34 |
| test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | test.cpp:5:5:5:20 | [summary] to write: ReturnValue in ymlStepGenerated | provenance | MaD:33 |
| test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | provenance | MaD:35 |
| test.cpp:7:47:7:52 | value2 | test.cpp:7:64:7:69 | value2 | provenance | |
| test.cpp:7:64:7:69 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | provenance | |
| test.cpp:10:10:10:18 | call to ymlSource | test.cpp:10:10:10:18 | call to ymlSource | provenance | Src:MaD:16 |
@@ -52,15 +60,15 @@ edges
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | |
| test.cpp:17:10:17:22 | call to ymlStepManual | test.cpp:18:10:18:10 | y | provenance | Sink:MaD:1 |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | provenance | |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:26 |
| test.cpp:17:24:17:24 | x | test.cpp:17:10:17:22 | call to ymlStepManual | provenance | MaD:34 |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | |
| test.cpp:21:10:21:25 | call to ymlStepGenerated | test.cpp:22:10:22:10 | z | provenance | Sink:MaD:1 |
| test.cpp:21:27:21:27 | x | test.cpp:5:5:5:20 | [summary param] 0 in ymlStepGenerated | provenance | |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:25 |
| test.cpp:21:27:21:27 | x | test.cpp:21:10:21:25 | call to ymlStepGenerated | provenance | MaD:33 |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | |
| test.cpp:25:11:25:33 | call to ymlStepManual_with_body | test.cpp:26:10:26:11 | y2 | provenance | Sink:MaD:1 |
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | provenance | |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:27 |
| test.cpp:25:35:25:35 | x | test.cpp:25:11:25:33 | call to ymlStepManual_with_body | provenance | MaD:35 |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | provenance | |
| test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body | test.cpp:33:10:33:11 | z2 | provenance | Sink:MaD:1 |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | provenance | |
@@ -68,16 +76,16 @@ edges
| test.cpp:46:30:46:32 | *arg [x] | test.cpp:47:12:47:19 | *arg [x] | provenance | |
| test.cpp:47:12:47:19 | *arg [x] | test.cpp:48:13:48:13 | *s [x] | provenance | |
| test.cpp:48:13:48:13 | *s [x] | test.cpp:48:16:48:16 | x | provenance | Sink:MaD:1 |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:24 |
| test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | provenance | MaD:32 |
| test.cpp:52:5:52:18 | [summary] to write: Argument[2].Parameter[*0] in pthread_create [x] | test.cpp:46:30:46:32 | *arg [x] | provenance | |
| test.cpp:56:2:56:2 | *s [post update] [x] | test.cpp:59:55:59:64 | *& ... [x] | provenance | |
| test.cpp:56:2:56:18 | ... = ... | test.cpp:56:2:56:2 | *s [post update] [x] | provenance | |
| test.cpp:56:8:56:16 | call to ymlSource | test.cpp:56:2:56:18 | ... = ... | provenance | Src:MaD:16 |
| test.cpp:59:55:59:64 | *& ... [x] | test.cpp:52:5:52:18 | [summary param] *3 in pthread_create [x] | provenance | |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:23 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:31 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:31 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:31 |
| test.cpp:63:6:63:21 | [summary param] 1 in callWithArgument | test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | provenance | MaD:31 |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:68:22:68:22 | y | provenance | |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:74:22:74:22 | y | provenance | |
| test.cpp:63:6:63:21 | [summary] to write: Argument[0].Parameter[0] in callWithArgument | test.cpp:82:22:82:22 | y | provenance | |
@@ -180,6 +188,59 @@ edges
| windows.cpp:439:7:439:8 | *& ... [x] | windows.cpp:349:8:349:19 | [summary param] *3 in CreateThread [x] | provenance | |
| windows.cpp:451:7:451:8 | *& ... [x] | windows.cpp:357:8:357:25 | [summary param] *4 in CreateRemoteThread [x] | provenance | |
| windows.cpp:464:7:464:8 | *& ... [x] | windows.cpp:387:8:387:27 | [summary param] *4 in CreateRemoteThreadEx [x] | provenance | |
| windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | provenance | MaD:27 |
| windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | provenance | MaD:23 |
| windows.cpp:485:6:485:18 | [summary param] *1 in RtlCopyMemory | windows.cpp:485:6:485:18 | [summary param] *0 in RtlCopyMemory [Return] | provenance | MaD:24 |
| windows.cpp:493:6:493:29 | [summary param] *1 in RtlCopyMemoryNonTemporal | windows.cpp:493:6:493:29 | [summary param] *0 in RtlCopyMemoryNonTemporal [Return] | provenance | MaD:25 |
| windows.cpp:510:6:510:25 | [summary param] *1 in RtlCopyUnicodeString [*Buffer] | windows.cpp:510:6:510:25 | [summary] read: Argument[*1].Field[*Buffer] in RtlCopyUnicodeString | provenance | |
| windows.cpp:510:6:510:25 | [summary] read: Argument[*1].Field[*Buffer] in RtlCopyUnicodeString | windows.cpp:510:6:510:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlCopyUnicodeString | provenance | MaD:26 |
| windows.cpp:510:6:510:25 | [summary] to write: Argument[*0] in RtlCopyUnicodeString [*Buffer] | windows.cpp:510:6:510:25 | [summary param] *0 in RtlCopyUnicodeString [Return] [*Buffer] | provenance | |
| windows.cpp:510:6:510:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlCopyUnicodeString | windows.cpp:510:6:510:25 | [summary] to write: Argument[*0] in RtlCopyUnicodeString [*Buffer] | provenance | |
| windows.cpp:515:6:515:18 | [summary param] *1 in RtlMoveMemory | windows.cpp:515:6:515:18 | [summary param] *0 in RtlMoveMemory [Return] | provenance | MaD:29 |
| windows.cpp:521:17:521:37 | [summary param] *1 in RtlMoveVolatileMemory | windows.cpp:521:17:521:37 | [summary param] *0 in RtlMoveVolatileMemory [Return] | provenance | MaD:30 |
| windows.cpp:527:6:527:25 | [summary param] *1 in RtlInitUnicodeString | windows.cpp:527:6:527:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlInitUnicodeString | provenance | MaD:28 |
| windows.cpp:527:6:527:25 | [summary] to write: Argument[*0] in RtlInitUnicodeString [*Buffer] | windows.cpp:527:6:527:25 | [summary param] *0 in RtlInitUnicodeString [Return] [*Buffer] | provenance | |
| windows.cpp:527:6:527:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlInitUnicodeString | windows.cpp:527:6:527:25 | [summary] to write: Argument[*0] in RtlInitUnicodeString [*Buffer] | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:533:11:533:16 | call to source | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:537:40:537:41 | *& ... | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:542:38:542:39 | *& ... | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:547:32:547:33 | *& ... | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:552:43:552:44 | *& ... | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:568:32:568:33 | *& ... | provenance | |
| windows.cpp:533:11:533:16 | call to source | windows.cpp:573:40:573:41 | *& ... | provenance | |
| windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | windows.cpp:538:10:538:23 | access to array | provenance | |
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | provenance | |
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | provenance | MaD:27 |
| windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | windows.cpp:543:10:543:23 | access to array | provenance | |
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | provenance | |
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | provenance | MaD:23 |
| windows.cpp:547:19:547:29 | RtlCopyMemory output argument | windows.cpp:548:10:548:23 | access to array | provenance | |
| windows.cpp:547:32:547:33 | *& ... | windows.cpp:485:6:485:18 | [summary param] *1 in RtlCopyMemory | provenance | |
| windows.cpp:547:32:547:33 | *& ... | windows.cpp:547:19:547:29 | RtlCopyMemory output argument | provenance | MaD:24 |
| windows.cpp:552:30:552:40 | RtlCopyMemoryNonTemporal output argument | windows.cpp:553:10:553:23 | access to array | provenance | |
| windows.cpp:552:43:552:44 | *& ... | windows.cpp:493:6:493:29 | [summary param] *1 in RtlCopyMemoryNonTemporal | provenance | |
| windows.cpp:552:43:552:44 | *& ... | windows.cpp:552:30:552:40 | RtlCopyMemoryNonTemporal output argument | provenance | MaD:25 |
| windows.cpp:559:5:559:24 | ... = ... | windows.cpp:561:39:561:44 | *buffer | provenance | |
| windows.cpp:559:17:559:24 | call to source | windows.cpp:559:5:559:24 | ... = ... | provenance | |
| windows.cpp:561:26:561:36 | RtlInitUnicodeString output argument [*Buffer] | windows.cpp:562:10:562:19 | *src_string [*Buffer] | provenance | |
| windows.cpp:561:26:561:36 | RtlInitUnicodeString output argument [*Buffer] | windows.cpp:563:40:563:50 | *& ... [*Buffer] | provenance | |
| windows.cpp:561:39:561:44 | *buffer | windows.cpp:527:6:527:25 | [summary param] *1 in RtlInitUnicodeString | provenance | |
| windows.cpp:561:39:561:44 | *buffer | windows.cpp:561:26:561:36 | RtlInitUnicodeString output argument [*Buffer] | provenance | MaD:28 |
| windows.cpp:562:10:562:19 | *src_string [*Buffer] | windows.cpp:562:10:562:29 | access to array | provenance | |
| windows.cpp:562:10:562:19 | *src_string [*Buffer] | windows.cpp:562:21:562:26 | *Buffer | provenance | |
| windows.cpp:562:21:562:26 | *Buffer | windows.cpp:562:10:562:29 | access to array | provenance | |
| windows.cpp:563:26:563:37 | RtlCopyUnicodeString output argument [*Buffer] | windows.cpp:564:10:564:20 | *dest_string [*Buffer] | provenance | |
| windows.cpp:563:40:563:50 | *& ... [*Buffer] | windows.cpp:510:6:510:25 | [summary param] *1 in RtlCopyUnicodeString [*Buffer] | provenance | |
| windows.cpp:563:40:563:50 | *& ... [*Buffer] | windows.cpp:563:26:563:37 | RtlCopyUnicodeString output argument [*Buffer] | provenance | MaD:26 |
| windows.cpp:564:10:564:20 | *dest_string [*Buffer] | windows.cpp:564:10:564:30 | access to array | provenance | |
| windows.cpp:564:10:564:20 | *dest_string [*Buffer] | windows.cpp:564:22:564:27 | *Buffer | provenance | |
| windows.cpp:564:22:564:27 | *Buffer | windows.cpp:564:10:564:30 | access to array | provenance | |
| windows.cpp:568:19:568:29 | RtlMoveMemory output argument | windows.cpp:569:10:569:23 | access to array | provenance | |
| windows.cpp:568:32:568:33 | *& ... | windows.cpp:515:6:515:18 | [summary param] *1 in RtlMoveMemory | provenance | |
| windows.cpp:568:32:568:33 | *& ... | windows.cpp:568:19:568:29 | RtlMoveMemory output argument | provenance | MaD:29 |
| windows.cpp:573:27:573:37 | RtlMoveVolatileMemory output argument | windows.cpp:574:10:574:23 | access to array | provenance | |
| windows.cpp:573:40:573:41 | *& ... | windows.cpp:521:17:521:37 | [summary param] *1 in RtlMoveVolatileMemory | provenance | |
| windows.cpp:573:40:573:41 | *& ... | windows.cpp:573:27:573:37 | RtlMoveVolatileMemory output argument | provenance | MaD:30 |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
@@ -352,6 +413,59 @@ nodes
| windows.cpp:439:7:439:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:451:7:451:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:464:7:464:8 | *& ... [x] | semmle.label | *& ... [x] |
| windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | semmle.label | [summary param] *0 in RtlCopyVolatileMemory [Return] |
| windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | semmle.label | [summary param] *1 in RtlCopyVolatileMemory |
| windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | semmle.label | [summary param] *0 in RtlCopyDeviceMemory [Return] |
| windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | semmle.label | [summary param] *1 in RtlCopyDeviceMemory |
| windows.cpp:485:6:485:18 | [summary param] *0 in RtlCopyMemory [Return] | semmle.label | [summary param] *0 in RtlCopyMemory [Return] |
| windows.cpp:485:6:485:18 | [summary param] *1 in RtlCopyMemory | semmle.label | [summary param] *1 in RtlCopyMemory |
| windows.cpp:493:6:493:29 | [summary param] *0 in RtlCopyMemoryNonTemporal [Return] | semmle.label | [summary param] *0 in RtlCopyMemoryNonTemporal [Return] |
| windows.cpp:493:6:493:29 | [summary param] *1 in RtlCopyMemoryNonTemporal | semmle.label | [summary param] *1 in RtlCopyMemoryNonTemporal |
| windows.cpp:510:6:510:25 | [summary param] *0 in RtlCopyUnicodeString [Return] [*Buffer] | semmle.label | [summary param] *0 in RtlCopyUnicodeString [Return] [*Buffer] |
| windows.cpp:510:6:510:25 | [summary param] *1 in RtlCopyUnicodeString [*Buffer] | semmle.label | [summary param] *1 in RtlCopyUnicodeString [*Buffer] |
| windows.cpp:510:6:510:25 | [summary] read: Argument[*1].Field[*Buffer] in RtlCopyUnicodeString | semmle.label | [summary] read: Argument[*1].Field[*Buffer] in RtlCopyUnicodeString |
| windows.cpp:510:6:510:25 | [summary] to write: Argument[*0] in RtlCopyUnicodeString [*Buffer] | semmle.label | [summary] to write: Argument[*0] in RtlCopyUnicodeString [*Buffer] |
| windows.cpp:510:6:510:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlCopyUnicodeString | semmle.label | [summary] to write: Argument[*0].Field[*Buffer] in RtlCopyUnicodeString |
| windows.cpp:515:6:515:18 | [summary param] *0 in RtlMoveMemory [Return] | semmle.label | [summary param] *0 in RtlMoveMemory [Return] |
| windows.cpp:515:6:515:18 | [summary param] *1 in RtlMoveMemory | semmle.label | [summary param] *1 in RtlMoveMemory |
| windows.cpp:521:17:521:37 | [summary param] *0 in RtlMoveVolatileMemory [Return] | semmle.label | [summary param] *0 in RtlMoveVolatileMemory [Return] |
| windows.cpp:521:17:521:37 | [summary param] *1 in RtlMoveVolatileMemory | semmle.label | [summary param] *1 in RtlMoveVolatileMemory |
| windows.cpp:527:6:527:25 | [summary param] *0 in RtlInitUnicodeString [Return] [*Buffer] | semmle.label | [summary param] *0 in RtlInitUnicodeString [Return] [*Buffer] |
| windows.cpp:527:6:527:25 | [summary param] *1 in RtlInitUnicodeString | semmle.label | [summary param] *1 in RtlInitUnicodeString |
| windows.cpp:527:6:527:25 | [summary] to write: Argument[*0] in RtlInitUnicodeString [*Buffer] | semmle.label | [summary] to write: Argument[*0] in RtlInitUnicodeString [*Buffer] |
| windows.cpp:527:6:527:25 | [summary] to write: Argument[*0].Field[*Buffer] in RtlInitUnicodeString | semmle.label | [summary] to write: Argument[*0].Field[*Buffer] in RtlInitUnicodeString |
| windows.cpp:533:11:533:16 | call to source | semmle.label | call to source |
| windows.cpp:533:11:533:16 | call to source | semmle.label | call to source |
| windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument | semmle.label | RtlCopyVolatileMemory output argument |
| windows.cpp:537:40:537:41 | *& ... | semmle.label | *& ... |
| windows.cpp:538:10:538:23 | access to array | semmle.label | access to array |
| windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument | semmle.label | RtlCopyDeviceMemory output argument |
| windows.cpp:542:38:542:39 | *& ... | semmle.label | *& ... |
| windows.cpp:543:10:543:23 | access to array | semmle.label | access to array |
| windows.cpp:547:19:547:29 | RtlCopyMemory output argument | semmle.label | RtlCopyMemory output argument |
| windows.cpp:547:32:547:33 | *& ... | semmle.label | *& ... |
| windows.cpp:548:10:548:23 | access to array | semmle.label | access to array |
| windows.cpp:552:30:552:40 | RtlCopyMemoryNonTemporal output argument | semmle.label | RtlCopyMemoryNonTemporal output argument |
| windows.cpp:552:43:552:44 | *& ... | semmle.label | *& ... |
| windows.cpp:553:10:553:23 | access to array | semmle.label | access to array |
| windows.cpp:559:5:559:24 | ... = ... | semmle.label | ... = ... |
| windows.cpp:559:17:559:24 | call to source | semmle.label | call to source |
| windows.cpp:561:26:561:36 | RtlInitUnicodeString output argument [*Buffer] | semmle.label | RtlInitUnicodeString output argument [*Buffer] |
| windows.cpp:561:39:561:44 | *buffer | semmle.label | *buffer |
| windows.cpp:562:10:562:19 | *src_string [*Buffer] | semmle.label | *src_string [*Buffer] |
| windows.cpp:562:10:562:29 | access to array | semmle.label | access to array |
| windows.cpp:562:21:562:26 | *Buffer | semmle.label | *Buffer |
| windows.cpp:563:26:563:37 | RtlCopyUnicodeString output argument [*Buffer] | semmle.label | RtlCopyUnicodeString output argument [*Buffer] |
| windows.cpp:563:40:563:50 | *& ... [*Buffer] | semmle.label | *& ... [*Buffer] |
| windows.cpp:564:10:564:20 | *dest_string [*Buffer] | semmle.label | *dest_string [*Buffer] |
| windows.cpp:564:10:564:30 | access to array | semmle.label | access to array |
| windows.cpp:564:22:564:27 | *Buffer | semmle.label | *Buffer |
| windows.cpp:568:19:568:29 | RtlMoveMemory output argument | semmle.label | RtlMoveMemory output argument |
| windows.cpp:568:32:568:33 | *& ... | semmle.label | *& ... |
| windows.cpp:569:10:569:23 | access to array | semmle.label | access to array |
| windows.cpp:573:27:573:37 | RtlMoveVolatileMemory output argument | semmle.label | RtlMoveVolatileMemory output argument |
| windows.cpp:573:40:573:41 | *& ... | semmle.label | *& ... |
| windows.cpp:574:10:574:23 | access to array | semmle.label | access to array |
subpaths
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:17:24:17:24 | x | test.cpp:4:5:4:17 | [summary param] 0 in ymlStepManual | test.cpp:4:5:4:17 | [summary] to write: ReturnValue in ymlStepManual | test.cpp:17:10:17:22 | call to ymlStepManual |
@@ -359,4 +473,12 @@ subpaths
| test.cpp:25:35:25:35 | x | test.cpp:6:5:6:27 | [summary param] 0 in ymlStepManual_with_body | test.cpp:6:5:6:27 | [summary] to write: ReturnValue in ymlStepManual_with_body | test.cpp:25:11:25:33 | call to ymlStepManual_with_body |
| test.cpp:32:41:32:41 | x | test.cpp:7:47:7:52 | value2 | test.cpp:7:5:7:30 | *ymlStepGenerated_with_body | test.cpp:32:11:32:36 | call to ymlStepGenerated_with_body |
| windows.cpp:27:36:27:38 | *cmd | windows.cpp:17:8:17:25 | [summary param] *0 in CommandLineToArgvA | windows.cpp:17:8:17:25 | [summary] to write: ReturnValue[**] in CommandLineToArgvA | windows.cpp:27:17:27:34 | **call to CommandLineToArgvA |
| windows.cpp:537:40:537:41 | *& ... | windows.cpp:473:17:473:37 | [summary param] *1 in RtlCopyVolatileMemory | windows.cpp:473:17:473:37 | [summary param] *0 in RtlCopyVolatileMemory [Return] | windows.cpp:537:27:537:37 | RtlCopyVolatileMemory output argument |
| windows.cpp:542:38:542:39 | *& ... | windows.cpp:479:17:479:35 | [summary param] *1 in RtlCopyDeviceMemory | windows.cpp:479:17:479:35 | [summary param] *0 in RtlCopyDeviceMemory [Return] | windows.cpp:542:25:542:35 | RtlCopyDeviceMemory output argument |
| windows.cpp:547:32:547:33 | *& ... | windows.cpp:485:6:485:18 | [summary param] *1 in RtlCopyMemory | windows.cpp:485:6:485:18 | [summary param] *0 in RtlCopyMemory [Return] | windows.cpp:547:19:547:29 | RtlCopyMemory output argument |
| windows.cpp:552:43:552:44 | *& ... | windows.cpp:493:6:493:29 | [summary param] *1 in RtlCopyMemoryNonTemporal | windows.cpp:493:6:493:29 | [summary param] *0 in RtlCopyMemoryNonTemporal [Return] | windows.cpp:552:30:552:40 | RtlCopyMemoryNonTemporal output argument |
| windows.cpp:561:39:561:44 | *buffer | windows.cpp:527:6:527:25 | [summary param] *1 in RtlInitUnicodeString | windows.cpp:527:6:527:25 | [summary param] *0 in RtlInitUnicodeString [Return] [*Buffer] | windows.cpp:561:26:561:36 | RtlInitUnicodeString output argument [*Buffer] |
| windows.cpp:563:40:563:50 | *& ... [*Buffer] | windows.cpp:510:6:510:25 | [summary param] *1 in RtlCopyUnicodeString [*Buffer] | windows.cpp:510:6:510:25 | [summary param] *0 in RtlCopyUnicodeString [Return] [*Buffer] | windows.cpp:563:26:563:37 | RtlCopyUnicodeString output argument [*Buffer] |
| windows.cpp:568:32:568:33 | *& ... | windows.cpp:515:6:515:18 | [summary param] *1 in RtlMoveMemory | windows.cpp:515:6:515:18 | [summary param] *0 in RtlMoveMemory [Return] | windows.cpp:568:19:568:29 | RtlMoveMemory output argument |
| windows.cpp:573:40:573:41 | *& ... | windows.cpp:521:17:521:37 | [summary param] *1 in RtlMoveVolatileMemory | windows.cpp:521:17:521:37 | [summary param] *0 in RtlMoveVolatileMemory [Return] | windows.cpp:573:27:573:37 | RtlMoveVolatileMemory output argument |
testFailures

View File

@@ -5556,12 +5556,24 @@
| Dubious signature "(z_streamp,int *)" in summary model. |
| Dubious signature "(z_streamp,unsigned int *,int *)" in summary model. |
| Dubious signature "(z_streamp,unsigned int)" in summary model. |
| Unrecognized input specification "Argument[***0]" in summary model. |
| Unrecognized input specification "Argument[***1]" in summary model. |
| Unrecognized input specification "Argument[***3]" in summary model. |
| Unrecognized input specification "Argument[***4]" in summary model. |
| Unrecognized input specification "Argument[****0]" in summary model. |
| Unrecognized input specification "Argument[****1]" in summary model. |
| Unrecognized input specification "Argument[****3]" in summary model. |
| Unrecognized input specification "Argument[****4]" in summary model. |
| Unrecognized input specification "Argument[*****0]" in summary model. |
| Unrecognized input specification "Argument[*****1]" in summary model. |
| Unrecognized input specification "Field[****hEvent]" in summary model. |
| Unrecognized input specification "Field[***hEvent]" in summary model. |
| Unrecognized output specification "Argument[***0]" in summary model. |
| Unrecognized output specification "Argument[***1]" in summary model. |
| Unrecognized output specification "Argument[****0]" in summary model. |
| Unrecognized output specification "Argument[****1]" in summary model. |
| Unrecognized output specification "Argument[*****0]" in summary model. |
| Unrecognized output specification "Argument[*****1]" in summary model. |
| Unrecognized output specification "Field[****hEvent]" in summary model. |
| Unrecognized output specification "Field[***hEvent]" in summary model. |
| Unrecognized output specification "Parameter[***0]" in summary model. |

View File

@@ -466,4 +466,111 @@ void test_create_thread()
&attrList,
&threadId);
}
}
using size_t = decltype(sizeof(0));
volatile void * RtlCopyVolatileMemory(
volatile void *Destination,
volatile const void *Source,
size_t Length
);
volatile void * RtlCopyDeviceMemory(
volatile void *Destination,
volatile const void *Source,
size_t Length
);
void RtlCopyMemory(
void* Destination,
const void* Source,
size_t Length
);
using VOID = void;
VOID RtlCopyMemoryNonTemporal(
VOID *Destination,
const VOID *Source,
SIZE_T Length
);
using USHORT = unsigned short;
using PWSTR = wchar_t*;
using PCWSTR = const wchar_t*;
using PCUNICODE_STRING = const struct _UNICODE_STRING*;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
VOID RtlCopyUnicodeString(
PUNICODE_STRING DestinationString,
PCUNICODE_STRING SourceString
);
void RtlMoveMemory(
void* Destination,
const void* Source,
size_t Length
);
volatile void * RtlMoveVolatileMemory(
volatile void *Destination,
volatile const void *Source,
size_t Length
);
void RtlInitUnicodeString(
PUNICODE_STRING DestinationString,
PCWSTR SourceString
);
void test_copy_and_move_memory() {
int x = source();
{
char dest_buffer[1024];
RtlCopyVolatileMemory(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
{
char dest_buffer[1024];
RtlCopyDeviceMemory(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
{
char dest_buffer[1024];
RtlCopyMemory(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
{
char dest_buffer[1024];
RtlCopyMemoryNonTemporal(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
{
UNICODE_STRING dest_string;
UNICODE_STRING src_string;
wchar_t buffer[1024];
buffer[0] = source();
RtlInitUnicodeString(&src_string, buffer);
sink(src_string.Buffer[0]); // $ ir
RtlCopyUnicodeString(&dest_string, &src_string);
sink(dest_string.Buffer[0]); // $ ir
}
{
char dest_buffer[1024];
RtlMoveMemory(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
{
volatile char dest_buffer[1024];
RtlMoveVolatileMemory(dest_buffer, &x, sizeof(x));
sink(dest_buffer[0]); // $ ir
}
}

View File

@@ -21,7 +21,7 @@
Java,"Java 7 to 24 [6]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [7]_",``.java``
Kotlin,"Kotlin 1.6.0 to 2.2.0\ *x*","kotlinc",``.kt``
Kotlin,"Kotlin 1.6.0 to 2.2.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`` [8]_"
Python [9]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11, 3.12, 3.13",Not applicable,``.py``
Ruby [10]_,"up to 3.3",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``"

View File

@@ -83,7 +83,7 @@ kt_javac_options(
"kotlin.RequiresOptIn",
"org.jetbrains.kotlin.ir.symbols.%s" %
("IrSymbolInternals" if version_less(v, "2.0.0") else "UnsafeDuringIrConstructionAPI"),
],
] + ([] if version_less(v, "2.2.20") else ["org.jetbrains.kotlin.DeprecatedForRemovalCompilerApi"]),
x_suppress_version_warnings = True,
),
# * extractor.name is different for each version, so we need to put it in different output dirs

BIN
java/kotlin-extractor/deps/kotlin-compiler-2.2.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.2.20-Beta1.jar (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -37,7 +37,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
import org.jetbrains.kotlin.load.kotlin.getJvmModuleNameForDeserializedDescriptor
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.name.SpecialNames

View File

@@ -0,0 +1,9 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.load.kotlin.getJvmModuleNameForDeserializedDescriptor
fun getJvmModuleNameForDeserializedDescriptor(descriptor: CallableMemberDescriptor): String? {
return org.jetbrains.kotlin.load.kotlin.getJvmModuleNameForDeserializedDescriptor(descriptor)
}

View File

@@ -0,0 +1,32 @@
package com.github.codeql.utils.versions
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.metadata.jvm.deserialization.*
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
fun getJvmModuleNameForDeserializedDescriptor(descriptor: CallableMemberDescriptor): String? {
val parent = getParentOfType(descriptor, ClassOrPackageFragmentDescriptor::class.java, false)
when {
parent is DeserializedClassDescriptor -> {
val classProto = parent.classProto
val nameResolver = parent.c.nameResolver
return classProto.getExtensionOrNull(JvmProtoBuf.classModuleName)
?.let(nameResolver::getString)
?: JvmProtoBufUtil.DEFAULT_MODULE_NAME
}
descriptor is DeserializedMemberDescriptor -> {
val source = descriptor.containerSource
if (source is JvmPackagePartSource) {
return source.moduleName
}
}
}
return null
}

View File

@@ -12,6 +12,7 @@ VERSIONS = [
"2.1.0-Beta1",
"2.1.20-Beta1",
"2.2.0-Beta1",
"2.2.20-Beta1",
]
def _version_to_tuple(v):

View File

@@ -1,5 +1,5 @@
{
"markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.2.10.",
"markdownMessage": "The Kotlin version installed (`999.999.999`) is too recent for this version of CodeQL. Install a version lower than 2.2.30.",
"severity": "error",
"source": {
"extractorName": "java",

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/java-queries
pack: codeql/java-all
extensible: extractorInformationSkipKey
data:
# These will have unstable values, as they are dependent on the

View File

@@ -1,6 +1,6 @@
extensions:
- addsTo:
pack: codeql/java-queries
pack: codeql/java-all
extensible: extractorInformationSkipKey
data:
# These will have unstable values, as they are dependent on the

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Kotlin versions up to 2.2.2\ *x* are now supported.

View File

@@ -61,3 +61,9 @@ class Diagnostic extends @diagnostic {
/** Gets a textual representation of this diagnostic. */
string toString() { result = this.getMessage() }
}
/**
* Holds for extraction information keys that should be skipped from telemetry reports.
* This predicate can be extended by other packs to filter out specific telemetry keys.
*/
extensible predicate extractorInformationSkipKey(string key);

View File

@@ -10,7 +10,7 @@
* of the field in case the field is not amenable to a non-trivial SSA
* representation.
*/
overlay[local]
overlay[local?]
module;
import java

View File

@@ -6,7 +6,6 @@ module;
private import semmle.code.Location
private import codeql.dataflow.DataFlow
private import semmle.code.java.Overlay
module Private {
import DataFlowPrivate
@@ -30,6 +29,4 @@ module JavaDataFlow implements InputSig<Location> {
predicate mayBenefitFromCallContext = Private::mayBenefitFromCallContext/1;
predicate viableImplInCallContext = Private::viableImplInCallContext/2;
predicate isEvaluatingInOverlay = isOverlay/0;
}

View File

@@ -83,7 +83,6 @@ overlay[caller?]
pragma[inline]
predicate localFlow(Node node1, Node node2) { node1 = node2 or localFlowStepPlus(node1, node2) }
overlay[caller?]
private predicate localFlowStepPlus(Node node1, Node node2) = fastTC(localFlowStep/2)(node1, node2)
/**

View File

@@ -1,4 +1,4 @@
overlay[local]
overlay[local?]
module;
import java
@@ -157,20 +157,15 @@ private predicate hasEntryDef(TrackedVar v, BasicBlock b) {
}
/** Holds if `n` might update the locally tracked variable `v`. */
overlay[global]
pragma[nomagic]
private predicate uncertainVariableUpdateImpl(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
private predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) {
exists(Call c | c = n.asCall() | updatesNamedField(c, v, _)) and
b.getNode(i) = n and
hasDominanceInformation(b)
or
uncertainVariableUpdateImpl(v.getQualifier(), n, b, i)
uncertainVariableUpdate(v.getQualifier(), n, b, i)
}
/** Holds if `n` might update the locally tracked variable `v`. */
predicate uncertainVariableUpdate(TrackedVar v, ControlFlowNode n, BasicBlock b, int i) =
forceLocal(uncertainVariableUpdateImpl/4)(v, n, b, i)
private module SsaInput implements SsaImplCommon::InputSig<Location> {
private import java as J
@@ -350,7 +345,6 @@ private module Cached {
* Constructor --(intraInstanceCallEdge)-->+ Method(setter of this.f)
* ```
*/
overlay[global]
private predicate intraInstanceCallEdge(Callable c1, Method m2) {
exists(MethodCall ma, RefType t1 |
ma.getCaller() = c1 and
@@ -371,7 +365,6 @@ private module Cached {
)
}
overlay[global]
private Callable tgt(Call c) {
result = viableImpl_v2(c)
or
@@ -381,13 +374,11 @@ private module Cached {
}
/** Holds if `(c1,c2)` is an edge in the call graph. */
overlay[global]
private predicate callEdge(Callable c1, Callable c2) {
exists(Call c | c.getCaller() = c1 and c2 = tgt(c))
}
/** Holds if `(c1,c2)` is an edge in the call graph excluding `intraInstanceCallEdge`. */
overlay[global]
private predicate crossInstanceCallEdge(Callable c1, Callable c2) {
callEdge(c1, c2) and not intraInstanceCallEdge(c1, c2)
}
@@ -401,7 +392,6 @@ private module Cached {
relevantFieldUpdate(_, f.getField(), _)
}
overlay[global]
private predicate source(Call call, TrackedField f, Field field, Callable c, boolean fresh) {
relevantCall(call, f) and
field = f.getField() and
@@ -415,11 +405,9 @@ private module Cached {
* `fresh` indicates whether the instance `this` in `c` has been freshly
* allocated along the call-chain.
*/
overlay[global]
private newtype TCallableNode =
MkCallableNode(Callable c, boolean fresh) { source(_, _, _, c, fresh) or edge(_, c, fresh) }
overlay[global]
private predicate edge(TCallableNode n, Callable c2, boolean f2) {
exists(Callable c1, boolean f1 | n = MkCallableNode(c1, f1) |
intraInstanceCallEdge(c1, c2) and f2 = f1
@@ -429,7 +417,6 @@ private module Cached {
)
}
overlay[global]
private predicate edge(TCallableNode n1, TCallableNode n2) {
exists(Callable c2, boolean f2 |
edge(n1, c2, f2) and
@@ -437,7 +424,6 @@ private module Cached {
)
}
overlay[global]
pragma[noinline]
private predicate source(Call call, TrackedField f, Field field, TCallableNode n) {
exists(Callable c, boolean fresh |
@@ -446,28 +432,24 @@ private module Cached {
)
}
overlay[global]
private predicate sink(Callable c, Field f, TCallableNode n) {
setsOwnField(c, f) and n = MkCallableNode(c, false)
or
setsOtherField(c, f) and n = MkCallableNode(c, _)
}
overlay[global]
private predicate prunedNode(TCallableNode n) {
sink(_, _, n)
or
exists(TCallableNode mid | edge(n, mid) and prunedNode(mid))
}
overlay[global]
private predicate prunedEdge(TCallableNode n1, TCallableNode n2) {
prunedNode(n1) and
prunedNode(n2) and
edge(n1, n2)
}
overlay[global]
private predicate edgePlus(TCallableNode c1, TCallableNode c2) = fastTC(prunedEdge/2)(c1, c2)
/**
@@ -475,7 +457,6 @@ private module Cached {
* where `f` and `call` share the same enclosing callable in which a
* `FieldRead` of `f` is reachable from `call`.
*/
overlay[global]
pragma[noopt]
private predicate updatesNamedFieldImpl(Call call, TrackedField f, Callable setter) {
exists(TCallableNode src, TCallableNode sink, Field field |
@@ -486,23 +467,17 @@ private module Cached {
}
bindingset[call, f]
overlay[global]
pragma[inline_late]
private predicate updatesNamedField0(Call call, TrackedField f, Callable setter) {
updatesNamedField(call, f, setter)
}
overlay[global]
cached
predicate defUpdatesNamedFieldImpl(SsaImplicitUpdate def, TrackedField f, Callable setter) {
predicate defUpdatesNamedField(SsaImplicitUpdate def, TrackedField f, Callable setter) {
f = def.getSourceVariable() and
updatesNamedField0(def.getCfgNode().asCall(), f, setter)
}
cached
predicate defUpdatesNamedField(SsaImplicitUpdate def, TrackedField f, Callable setter) =
forceLocal(defUpdatesNamedFieldImpl/3)(def, f, setter)
cached
predicate ssaUncertainImplicitUpdate(SsaImplicitUpdate def) {
exists(SsaSourceVariable v, BasicBlock bb, int i |
@@ -570,7 +545,6 @@ private module Cached {
}
cached
overlay[global]
module DataFlowIntegration {
import DataFlowIntegrationImpl

View File

@@ -2,6 +2,7 @@
* Provides predicates for reasoning about runtime call targets through virtual
* dispatch.
*/
overlay[local?]
module;
import java

View File

@@ -170,15 +170,12 @@ private module RegexFlow = DataFlow::Global<RegexFlowConfig>;
* As an optimisation, only regexes containing an infinite repitition quatifier (`+`, `*`, or `{x,}`)
* and therefore may be relevant for ReDoS queries are considered.
*/
predicate usedAsRegexG(StringLiteral regex, string mode, boolean match_full_string) {
predicate usedAsRegex(StringLiteral regex, string mode, boolean match_full_string) {
RegexFlow::flow(DataFlow::exprNode(regex), _) and
mode = "None" and // TODO: proper mode detection
mode = "None" and // TODO: proper mode detection
(if matchesFullString(regex) then match_full_string = true else match_full_string = false)
}
overlay[local]
predicate usedAsRegex(StringLiteral regex, string mode, boolean match_full_string) = forceLocal(usedAsRegexG/3)(regex, mode, match_full_string)
/**
* Holds if `regex` is used as a regular expression that is matched against a full string,
* as though it was implicitly surrounded by ^ and $.

View File

@@ -1,5 +1,5 @@
/** Provides a class hierarchy corresponding to a parse tree of regular expressions. */
overlay[local]
overlay[local?]
module;
private import semmle.code.java.regex.regex as RE // importing under a namescape to avoid naming conflict for `Top`.

View File

@@ -936,7 +936,6 @@ abstract class RegexString extends StringLiteral {
}
/** A string literal used as a regular expression */
overlay[local]
class Regex extends RegexString {
boolean matches_full_string;

View File

@@ -10,8 +10,6 @@ import java
import semmle.code.java.Diagnostics
import DatabaseQuality
extensible predicate extractorInformationSkipKey(string key);
predicate compilationInfo(string key, int value) {
exists(Compilation c, string infoKey |
key = infoKey + ": " + c.getInfo(infoKey) and

View File

@@ -1,5 +1,5 @@
extensions:
- addsTo:
pack: codeql/java-queries
pack: codeql/java-all
extensible: extractorInformationSkipKey
data: []

View File

@@ -83,5 +83,6 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql
ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql
ql/javascript/ql/src/Summary/LinesOfCode.ql
ql/javascript/ql/src/Summary/LinesOfUserCode.ql

View File

@@ -184,6 +184,7 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
ql/javascript/ql/src/Security/CWE-918/ClientSideRequestForgery.ql
ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql
ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql
ql/javascript/ql/src/Statements/DanglingElse.ql
ql/javascript/ql/src/Statements/IgnoreArrayResult.ql
ql/javascript/ql/src/Statements/InconsistentLoopOrientation.ql

View File

@@ -99,5 +99,6 @@ ql/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
ql/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.ql
ql/javascript/ql/src/Security/CWE-918/ClientSideRequestForgery.ql
ql/javascript/ql/src/Security/CWE-918/RequestForgery.ql
ql/javascript/ql/src/Security/CWE-942/CorsPermissiveConfiguration.ql
ql/javascript/ql/src/Summary/LinesOfCode.ql
ql/javascript/ql/src/Summary/LinesOfUserCode.ql

View File

@@ -75,7 +75,6 @@ ql/javascript/ql/src/experimental/Security/CWE-347/decodeJwtWithoutVerificationL
ql/javascript/ql/src/experimental/Security/CWE-444/InsecureHttpParser.ql
ql/javascript/ql/src/experimental/Security/CWE-522-DecompressionBombs/DecompressionBombs.ql
ql/javascript/ql/src/experimental/Security/CWE-918/SSRF.ql
ql/javascript/ql/src/experimental/Security/CWE-942/CorsPermissiveConfiguration.ql
ql/javascript/ql/src/experimental/StandardLibrary/MultipleArgumentsToSetConstructor.ql
ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-020/UntrustedDataToExternalAPI.ql
ql/javascript/ql/src/experimental/heuristics/ql/src/Security/CWE-078/CommandInjection.ql

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The regular expressions in `SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.

View File

@@ -5,6 +5,13 @@ extensions:
data:
- ["@apollo/server", "Member[ApolloServer,ApolloServerBase].Argument[0].AnyMember.AnyMember.AnyMember.Parameter[1]", "remote"]
- addsTo:
pack: codeql/javascript-all
extensible: sinkModel
data:
- ["@apollo/server", "Member[gql].Argument[0]", "sql-injection"]
- ["@apollo/server", "Member[ApolloServer,ApolloServerBase].Argument[0].Member[cors].Member[origin]", "cors-misconfiguration"]
- addsTo:
pack: codeql/javascript-all
extensible: typeModel
@@ -13,3 +20,9 @@ extensions:
- ["@apollo/server", "apollo-server-express", ""]
- ["@apollo/server", "apollo-server-core", ""]
- ["@apollo/server", "apollo-server", ""]
- ["@apollo/server", "@apollo/apollo-server-express", ""]
- ["@apollo/server", "apollo-server-express", ""]
- ["@apollo/server", "@apollo/server", ""]
- ["@apollo/server", "@apollo/apollo-server-core", ""]
- ["ApolloServer", "@apollo/server", "Member[ApolloServer]"]
- ["GraphQLApollo", "@apollo/server", "Member[gql]"]

View File

@@ -0,0 +1,6 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: sinkModel
data:
- ["cors", "Argument[0].Member[origin]", "cors-misconfiguration"]

View File

@@ -0,0 +1,85 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* overly permissive CORS configurations, as well as
* extension points for adding your own.
*/
import javascript
/** Module containing sources, sinks, and sanitizers for overly permissive CORS configurations. */
module CorsPermissiveConfiguration {
private newtype TFlowState =
TTaint() or
TPermissive()
/** A flow state to associate with a tracked value. */
class FlowState extends TFlowState {
/** Gets a string representation of this flow state. */
string toString() {
this = TTaint() and result = "taint"
or
this = TPermissive() and result = "permissive"
}
}
/** Predicates for working with flow states. */
module FlowState {
/** A tainted value. */
FlowState taint() { result = TTaint() }
/** A permissive value (true, null, or "*"). */
FlowState permissive() { result = TPermissive() }
}
/**
* A data flow source for permissive CORS configuration.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for permissive CORS configuration.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for permissive CORS configuration.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source instanceof ActiveThreatModelSource {
ActiveThreatModelSourceAsSource() { not this instanceof ClientSideRemoteFlowSource }
}
/** An overly permissive value for `origin` configuration. */
class PermissiveValue extends Source {
PermissiveValue() {
this.mayHaveBooleanValue(true) or
this.asExpr() instanceof NullLiteral or
this.mayHaveStringValue("*")
}
}
/**
* The value of cors origin when initializing the application.
*/
class CorsOriginSink extends Sink, DataFlow::ValueNode {
CorsOriginSink() { this = ModelOutput::getASinkNode("cors-misconfiguration").asSink() }
}
/**
* A sanitizer for CORS configurations where credentials are explicitly disabled.
* When credentials are false, using "*" for origin is a legitimate pattern.
*/
private class CredentialsDisabledSanitizer extends Sanitizer {
CredentialsDisabledSanitizer() {
exists(DataFlow::SourceNode config, DataFlow::CallNode call |
call.getArgument(0).getALocalSource() = config and
this = config.getAPropertyWrite("origin").getRhs() and
config.getAPropertyWrite("credentials").getRhs().mayHaveBooleanValue(false)
)
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* Provides a dataflow taint tracking configuration for reasoning
* about overly permissive CORS configurations.
*
* Note, for performance reasons: only import this file if
* `CorsPermissiveConfiguration::Configuration` is needed,
* otherwise `CorsPermissiveConfigurationCustomizations` should
* be imported instead.
*/
import javascript
import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration
private import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration as CorsPermissiveConfiguration
/**
* A data flow configuration for overly permissive CORS configuration.
*/
module CorsPermissiveConfigurationConfig implements DataFlow::StateConfigSig {
class FlowState = CorsPermissiveConfiguration::FlowState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof PermissiveValue and state = FlowState::permissive()
or
source instanceof RemoteFlowSource and state = FlowState::taint()
}
predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof CorsOriginSink and
state = [FlowState::taint(), FlowState::permissive()]
}
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
module CorsPermissiveConfigurationFlow =
TaintTracking::GlobalWithState<CorsPermissiveConfigurationConfig>;

View File

@@ -0,0 +1,73 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
A server can use CORS (Cross-Origin Resource Sharing) to relax the
restrictions imposed by the Same-Origin Policy, allowing controlled, secure
cross-origin requests when necessary.
</p>
<p>
A server with an overly permissive CORS configuration may inadvertently
expose sensitive data or enable CSRF attacks, which allow attackers to trick
users into performing unwanted operations on websites they're authenticated to.
</p>
</overview>
<recommendation>
<p>
When the <code>origin</code> is set to <code>true</code>, the server
accepts requests from any origin, potentially exposing the system to
CSRF attacks. Use <code>false</code> as the origin value or implement a whitelist
of allowed origins instead.
</p>
<p>
When the <code>origin</code> is set to <code>null</code>, it can be
exploited by an attacker who can deceive a user into making
requests from a <code>null</code> origin, often hosted within a sandboxed iframe.
</p>
<p>
If the <code>origin</code> value is user-controlled, ensure that the data
is properly sanitized and validated against a whitelist of allowed origins.
</p>
</recommendation>
<example>
<p>
In the following example, <code>server_1</code> accepts requests from any origin
because the value of <code>origin</code> is set to <code>true</code>.
<code>server_2</code> uses user-controlled data for the origin without validation.
</p>
<sample src="examples/CorsPermissiveConfigurationBad.js"/>
<p>
To fix these issues, <code>server_1</code> uses a restrictive CORS configuration
that is not vulnerable to CSRF attacks. <code>server_2</code> properly validates
user-controlled data against a whitelist before using it.
</p>
<sample src="examples/CorsPermissiveConfigurationGood.js"/>
</example>
<references>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">CORS, Access-Control-Allow-Origin</a>.</li>
<li>W3C: <a href="https://w3c.github.io/webappsec-cors-for-developers/#resources">CORS for developers, Advice for Resource Owners</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,22 @@
/**
* @name Permissive CORS configuration
* @description Cross-origin resource sharing (CORS) policy allows overly broad access.
* @kind path-problem
* @problem.severity warning
* @security-severity 6.0
* @precision high
* @id js/cors-permissive-configuration
* @tags security
* external/cwe/cwe-942
*/
import javascript
import semmle.javascript.security.CorsPermissiveConfigurationQuery as CorsQuery
import CorsQuery::CorsPermissiveConfigurationFlow::PathGraph
from
CorsQuery::CorsPermissiveConfigurationFlow::PathNode source,
CorsQuery::CorsPermissiveConfigurationFlow::PathNode sink
where CorsQuery::CorsPermissiveConfigurationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "CORS Origin allows broad access due to $@.", source.getNode(),
"permissive or user controlled value"

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The query "CORS misconfiguration" (`js/cors-misconfiguration`) has been promoted from experimental and is now part of the default security suite.

View File

@@ -1,36 +0,0 @@
/**
* Provides classes for working with Apollo GraphQL connectors.
*/
import javascript
/** Provides classes modeling the apollo packages [@apollo/server](https://npmjs.com/package/@apollo/server`) */
module Apollo {
/** Get a reference to the `ApolloServer` class. */
private API::Node apollo() {
result =
API::moduleImport([
"@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core",
"apollo-server", "apollo-server-express"
]).getMember("ApolloServer")
}
/** Gets a reference to the `gql` function that parses GraphQL strings. */
private API::Node gql() {
result =
API::moduleImport([
"@apollo/server", "@apollo/apollo-server-express", "@apollo/apollo-server-core",
"apollo-server", "apollo-server-express"
]).getMember("gql")
}
/** An instantiation of an `ApolloServer`. */
class ApolloServer extends API::NewNode {
ApolloServer() { this = apollo().getAnInstantiation() }
}
/** A string that is interpreted as a GraphQL query by a `apollo` package. */
private class ApolloGraphQLString extends GraphQL::GraphQLString {
ApolloGraphQLString() { this = gql().getACall().getArgument(0) }
}
}

View File

@@ -1,24 +0,0 @@
/**
* Provides classes for working with Cors connectors.
*/
import javascript
/** Provides classes modeling the [cors](https://npmjs.com/package/cors) library. */
module Cors {
/**
* An expression that creates a new CORS configuration.
*/
class Cors extends DataFlow::CallNode {
Cors() { this = DataFlow::moduleImport("cors").getAnInvocation() }
/** Get the options used to configure Cors */
DataFlow::Node getOptionsArgument() { result = this.getArgument(0) }
/** Holds if cors is using default configuration */
predicate isDefault() { this.getNumArgument() = 0 }
/** Gets the value of the `origin` option used to configure this Cors instance. */
DataFlow::Node getOrigin() { result = this.getOptionArgument(0, "origin") }
}
}

View File

@@ -1,71 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
A server can use <code>CORS</code> (Cross-Origin Resource Sharing) to relax the
restrictions imposed by the <code>SOP</code> (Same-Origin Policy), allowing controlled, secure
cross-origin requests when necessary.
A server with an overly permissive <code>CORS</code> configuration may inadvertently
expose sensitive data or lead to <code>CSRF</code> which is an attack that allows attackers to trick
users into performing unwanted operations in websites they're authenticated to.
</p>
</overview>
<recommendation>
<p>
When the <code>origin</code> is set to <code>true</code>, it signifies that the server
is accepting requests from <code>any</code> origin, potentially exposing the system to
CSRF attacks. This can be fixed using <code>false</code> as origin value or using a whitelist.
</p>
<p>
On the other hand, if the <code>origin</code> is
set to <code>null</code>, it can be exploited by an attacker to deceive a user into making
requests from a <code>null</code> origin form, often hosted within a sandboxed iframe.
</p>
<p>
If the <code>origin</code> value is user controlled, make sure that the data
is properly sanitized.
</p>
</recommendation>
<example>
<p>
In the example below, the <code>server_1</code> accepts requests from any origin
since the value of <code>origin</code> is set to <code>true</code>.
And <code>server_2</code>'s origin is user-controlled.
</p>
<sample src="examples/CorsPermissiveConfigurationBad.js"/>
<p>
In the example below, the <code>server_1</code> CORS is restrictive so it's not
vulnerable to CSRF attacks. And <code>server_2</code>'s is using properly sanitized
user-controlled data.
</p>
<sample src="examples/CorsPermissiveConfigurationGood.js"/>
</example>
<references>
<li>Mozilla Developer Network: <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin">CORS, Access-Control-Allow-Origin</a>.</li>
<li>W3C: <a href="https://w3c.github.io/webappsec-cors-for-developers/#resources">CORS for developers, Advice for Resource Owners</a></li>
</references>
</qhelp>

View File

@@ -1,21 +0,0 @@
/**
* @name overly CORS configuration
* @description Misconfiguration of CORS HTTP headers allows CSRF attacks.
* @kind path-problem
* @problem.severity error
* @security-severity 7.5
* @precision high
* @id js/cors-misconfiguration
* @tags security
* external/cwe/cwe-942
*/
import javascript
import CorsPermissiveConfigurationQuery
import CorsPermissiveConfigurationFlow::PathGraph
from
CorsPermissiveConfigurationFlow::PathNode source, CorsPermissiveConfigurationFlow::PathNode sink
where CorsPermissiveConfigurationFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "CORS Origin misconfiguration due to a $@.", source.getNode(),
"too permissive or user controlled value"

View File

@@ -1,141 +0,0 @@
/**
* Provides default sources, sinks and sanitizers for reasoning about
* overly permissive CORS configurations, as well as
* extension points for adding your own.
*/
import javascript
import Cors::Cors
import Apollo::Apollo
/** Module containing sources, sinks, and sanitizers for overly permissive CORS configurations. */
module CorsPermissiveConfiguration {
private newtype TFlowState =
TTaint() or
TTrueOrNull() or
TWildcard()
/** A flow state to asociate with a tracked value. */
class FlowState extends TFlowState {
/** Gets a string representation of this flow state. */
string toString() {
this = TTaint() and result = "taint"
or
this = TTrueOrNull() and result = "true-or-null"
or
this = TWildcard() and result = "wildcard"
}
deprecated DataFlow::FlowLabel toFlowLabel() {
this = TTaint() and result.isTaint()
or
this = TTrueOrNull() and result instanceof TrueAndNull
or
this = TWildcard() and result instanceof Wildcard
}
}
/** Predicates for working with flow states. */
module FlowState {
deprecated FlowState fromFlowLabel(DataFlow::FlowLabel label) { result.toFlowLabel() = label }
/** A tainted value. */
FlowState taint() { result = TTaint() }
/** A `true` or `null` value. */
FlowState trueOrNull() { result = TTrueOrNull() }
/** A `"*"` value. */
FlowState wildcard() { result = TWildcard() }
}
/**
* A data flow source for permissive CORS configuration.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for permissive CORS configuration.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A sanitizer for permissive CORS configuration.
*/
abstract class Sanitizer extends DataFlow::Node { }
/**
* DEPRECATED: Use `ActiveThreatModelSource` from Concepts instead!
*/
deprecated class RemoteFlowSourceAsSource = ActiveThreatModelSourceAsSource;
/**
* An active threat-model source, considered as a flow source.
*/
private class ActiveThreatModelSourceAsSource extends Source instanceof ActiveThreatModelSource {
ActiveThreatModelSourceAsSource() { not this instanceof ClientSideRemoteFlowSource }
}
/** A flow label representing `true` and `null` values. */
abstract deprecated class TrueAndNull extends DataFlow::FlowLabel {
TrueAndNull() { this = "TrueAndNull" }
}
deprecated TrueAndNull truenullLabel() { any() }
/** A flow label representing `*` value. */
abstract deprecated class Wildcard extends DataFlow::FlowLabel {
Wildcard() { this = "Wildcard" }
}
deprecated Wildcard wildcardLabel() { any() }
/** An overly permissive value for `origin` (Apollo) */
class TrueNullValue extends Source {
TrueNullValue() { this.mayHaveBooleanValue(true) or this.asExpr() instanceof NullLiteral }
}
/** An overly permissive value for `origin` (Express) */
class WildcardValue extends Source {
WildcardValue() { this.mayHaveStringValue("*") }
}
/**
* The value of cors origin when initializing the application.
*/
class CorsApolloServer extends Sink, DataFlow::ValueNode {
CorsApolloServer() {
exists(ApolloServer agql |
this =
agql.getOptionArgument(0, "cors").getALocalSource().getAPropertyWrite("origin").getRhs()
)
}
}
/**
* The value of cors origin when initializing the application.
*/
class ExpressCors extends Sink, DataFlow::ValueNode {
ExpressCors() {
exists(CorsConfiguration config | this = config.getCorsConfiguration().getOrigin())
}
}
/**
* An express route setup configured with the `cors` package.
*/
class CorsConfiguration extends DataFlow::MethodCallNode {
Cors corsConfig;
CorsConfiguration() {
exists(Express::RouteSetup setup | this = setup |
if setup.isUseCall()
then corsConfig = setup.getArgument(0)
else corsConfig = setup.getArgument(any(int i | i > 0))
)
}
/** Gets the expression that configures `cors` on this route setup. */
Cors getCorsConfiguration() { result = corsConfig }
}
}

View File

@@ -1,69 +0,0 @@
/**
* Provides a dataflow taint tracking configuration for reasoning
* about overly permissive CORS configurations.
*
* Note, for performance reasons: only import this file if
* `CorsPermissiveConfiguration::Configuration` is needed,
* otherwise `CorsPermissiveConfigurationCustomizations` should
* be imported instead.
*/
import javascript
import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration
private import CorsPermissiveConfigurationCustomizations::CorsPermissiveConfiguration as CorsPermissiveConfiguration
/**
* A data flow configuration for overly permissive CORS configuration.
*/
module CorsPermissiveConfigurationConfig implements DataFlow::StateConfigSig {
class FlowState = CorsPermissiveConfiguration::FlowState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof TrueNullValue and state = FlowState::trueOrNull()
or
source instanceof WildcardValue and state = FlowState::wildcard()
or
source instanceof RemoteFlowSource and state = FlowState::taint()
}
predicate isSink(DataFlow::Node sink, FlowState state) {
sink instanceof CorsApolloServer and state = [FlowState::taint(), FlowState::trueOrNull()]
or
sink instanceof ExpressCors and state = [FlowState::taint(), FlowState::wildcard()]
}
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
}
module CorsPermissiveConfigurationFlow =
TaintTracking::GlobalWithState<CorsPermissiveConfigurationConfig>;
/**
* DEPRECATED. Use the `CorsPermissiveConfigurationFlow` module instead.
*/
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CorsPermissiveConfiguration" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowLabel label) {
CorsPermissiveConfigurationConfig::isSource(source, FlowState::fromFlowLabel(label))
}
override predicate isSink(DataFlow::Node sink, DataFlow::FlowLabel label) {
CorsPermissiveConfigurationConfig::isSink(sink, FlowState::fromFlowLabel(label))
}
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
CorsPermissiveConfigurationConfig::isBarrier(node)
}
}
deprecated private class WildcardActivated extends DataFlow::FlowLabel, Wildcard {
WildcardActivated() { this = this }
}
deprecated private class TrueAndNullActivated extends DataFlow::FlowLabel, TrueAndNull {
TrueAndNullActivated() { this = this }
}

View File

@@ -1 +0,0 @@
./experimental/Security/CWE-942/CorsPermissiveConfiguration.ql

View File

@@ -1,3 +1,12 @@
#select
| apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | CORS Origin allows broad access due to $@. | apollo-test.js:11:25:11:28 | true | permissive or user controlled value |
| apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | CORS Origin allows broad access due to $@. | apollo-test.js:21:25:21:28 | null | permissive or user controlled value |
| apollo-test.js:26:25:26:35 | user_origin | apollo-test.js:8:33:8:39 | req.url | apollo-test.js:26:25:26:35 | user_origin | CORS Origin allows broad access due to $@. | apollo-test.js:8:33:8:39 | req.url | permissive or user controlled value |
| apollo-test.js:26:25:26:35 | user_origin | apollo-test.js:8:42:8:45 | true | apollo-test.js:26:25:26:35 | user_origin | CORS Origin allows broad access due to $@. | apollo-test.js:8:42:8:45 | true | permissive or user controlled value |
| express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | CORS Origin allows broad access due to $@. | express-test.js:26:17:26:19 | '*' | permissive or user controlled value |
| express-test.js:33:17:33:27 | user_origin | express-test.js:10:33:10:39 | req.url | express-test.js:33:17:33:27 | user_origin | CORS Origin allows broad access due to $@. | express-test.js:10:33:10:39 | req.url | permissive or user controlled value |
| express-test.js:33:17:33:27 | user_origin | express-test.js:10:42:10:45 | true | express-test.js:33:17:33:27 | user_origin | CORS Origin allows broad access due to $@. | express-test.js:10:42:10:45 | true | permissive or user controlled value |
| express-test.js:48:17:48:19 | '*' | express-test.js:48:17:48:19 | '*' | express-test.js:48:17:48:19 | '*' | CORS Origin allows broad access due to $@. | express-test.js:48:17:48:19 | '*' | permissive or user controlled value |
edges
| apollo-test.js:8:9:8:59 | user_origin | apollo-test.js:26:25:26:35 | user_origin | provenance | |
| apollo-test.js:8:9:8:59 | user_origin | apollo-test.js:26:25:26:35 | user_origin | provenance | |
@@ -6,8 +15,11 @@ edges
| apollo-test.js:8:33:8:39 | req.url | apollo-test.js:8:23:8:46 | url.par ... , true) | provenance | |
| apollo-test.js:8:42:8:45 | true | apollo-test.js:8:23:8:46 | url.par ... , true) | provenance | |
| express-test.js:10:9:10:59 | user_origin | express-test.js:33:17:33:27 | user_origin | provenance | |
| express-test.js:10:9:10:59 | user_origin | express-test.js:33:17:33:27 | user_origin | provenance | |
| express-test.js:10:23:10:46 | url.par ... , true) | express-test.js:10:9:10:59 | user_origin | provenance | |
| express-test.js:10:23:10:46 | url.par ... , true) | express-test.js:10:9:10:59 | user_origin | provenance | |
| express-test.js:10:33:10:39 | req.url | express-test.js:10:23:10:46 | url.par ... , true) | provenance | |
| express-test.js:10:42:10:45 | true | express-test.js:10:23:10:46 | url.par ... , true) | provenance | |
nodes
| apollo-test.js:8:9:8:59 | user_origin | semmle.label | user_origin |
| apollo-test.js:8:9:8:59 | user_origin | semmle.label | user_origin |
@@ -20,15 +32,13 @@ nodes
| apollo-test.js:26:25:26:35 | user_origin | semmle.label | user_origin |
| apollo-test.js:26:25:26:35 | user_origin | semmle.label | user_origin |
| express-test.js:10:9:10:59 | user_origin | semmle.label | user_origin |
| express-test.js:10:9:10:59 | user_origin | semmle.label | user_origin |
| express-test.js:10:23:10:46 | url.par ... , true) | semmle.label | url.par ... , true) |
| express-test.js:10:23:10:46 | url.par ... , true) | semmle.label | url.par ... , true) |
| express-test.js:10:33:10:39 | req.url | semmle.label | req.url |
| express-test.js:10:42:10:45 | true | semmle.label | true |
| express-test.js:26:17:26:19 | '*' | semmle.label | '*' |
| express-test.js:33:17:33:27 | user_origin | semmle.label | user_origin |
| express-test.js:33:17:33:27 | user_origin | semmle.label | user_origin |
| express-test.js:48:17:48:19 | '*' | semmle.label | '*' |
subpaths
#select
| apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | apollo-test.js:11:25:11:28 | true | CORS Origin misconfiguration due to a $@. | apollo-test.js:11:25:11:28 | true | too permissive or user controlled value |
| apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | apollo-test.js:21:25:21:28 | null | CORS Origin misconfiguration due to a $@. | apollo-test.js:21:25:21:28 | null | too permissive or user controlled value |
| apollo-test.js:26:25:26:35 | user_origin | apollo-test.js:8:33:8:39 | req.url | apollo-test.js:26:25:26:35 | user_origin | CORS Origin misconfiguration due to a $@. | apollo-test.js:8:33:8:39 | req.url | too permissive or user controlled value |
| apollo-test.js:26:25:26:35 | user_origin | apollo-test.js:8:42:8:45 | true | apollo-test.js:26:25:26:35 | user_origin | CORS Origin misconfiguration due to a $@. | apollo-test.js:8:42:8:45 | true | too permissive or user controlled value |
| express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | express-test.js:26:17:26:19 | '*' | CORS Origin misconfiguration due to a $@. | express-test.js:26:17:26:19 | '*' | too permissive or user controlled value |
| express-test.js:33:17:33:27 | user_origin | express-test.js:10:33:10:39 | req.url | express-test.js:33:17:33:27 | user_origin | CORS Origin misconfiguration due to a $@. | express-test.js:10:33:10:39 | req.url | too permissive or user controlled value |

View File

@@ -0,0 +1,2 @@
query: Security/CWE-942/CorsPermissiveConfiguration.ql
postprocess: utils/test/InlineExpectationsTestQuery.ql

View File

@@ -5,10 +5,10 @@ var https = require('https'),
var server = https.createServer(function () { });
server.on('request', function (req, res) {
let user_origin = url.parse(req.url, true).query.origin;
let user_origin = url.parse(req.url, true).query.origin; // $ Source
// BAD: CORS too permissive
const server_1 = new ApolloServer({
cors: { origin: true }
cors: { origin: true } // $ Alert
});
// GOOD: restrictive CORS
@@ -18,11 +18,11 @@ server.on('request', function (req, res) {
// BAD: CORS too permissive
const server_3 = new ApolloServer({
cors: { origin: null }
cors: { origin: null } // $ Alert
});
// BAD: CORS is controlled by user
const server_4 = new ApolloServer({
cors: { origin: user_origin }
cors: { origin: user_origin } // $ Alert
});
});

View File

@@ -7,7 +7,7 @@ var https = require('https'),
var server = https.createServer(function () { });
server.on('request', function (req, res) {
let user_origin = url.parse(req.url, true).query.origin;
let user_origin = url.parse(req.url, true).query.origin; // $ Source
// BAD: CORS too permissive, default value is *
var app1 = express();
@@ -23,14 +23,30 @@ server.on('request', function (req, res) {
// BAD: CORS too permissive
var app3 = express();
var corsOption3 = {
origin: '*'
origin: '*' // $ Alert
};
app3.use(cors(corsOption3));
// BAD: CORS is controlled by user
var app4 = express();
var corsOption4 = {
origin: user_origin
origin: user_origin // $ Alert
};
app4.use(cors(corsOption4));
// GOOD: CORS allows any origin but credentials are disabled (safe pattern)
var app5 = express();
var corsOption5 = {
origin: '*',
credentials: false
};
app5.use(cors(corsOption5));
// BAD: CORS allows any origin with credentials enabled
var app6 = express();
var corsOption6 = {
origin: '*', // $ Alert
credentials: true
};
app6.use(cors(corsOption6));
});

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The regular expressions in `SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.

View File

@@ -45,10 +45,10 @@ leaving <code>KeyboardInterrupt</code> to propagate.
</example>
<references>
<li>Python Language Reference: <a href="http://docs.python.org/2.7/reference/compound_stmts.html#try">The try statement</a>,
<a href="http://docs.python.org/2.7/reference/executionmodel.html#exceptions">Exceptions</a>.</li>
<li>Python Language Reference: <a href="http://docs.python.org/3/reference/compound_stmts.html#try">The try statement</a>,
<a href="http://docs.python.org/3/reference/executionmodel.html#exceptions">Exceptions</a>.</li>
<li>M. Lutz, Learning Python, Section 35.3: Exception Design Tips and Gotchas, O'Reilly Media, 2013.</li>
<li>Python Tutorial: <a href="https://docs.python.org/2/tutorial/errors.html">Errors and Exceptions</a>.</li>
<li>Python Tutorial: <a href="https://docs.python.org/3/tutorial/errors.html">Errors and Exceptions</a>.</li>
</references>

View File

@@ -7,7 +7,7 @@
The loss of information can lead to hard to debug errors and incomplete log files.
It is even possible that ignoring an exception can cause a security vulnerability.
An empty <code>except</code> block may be an indication that the programmer intended to
handle the exception but never wrote the code to do so.</p>
handle the exception, but never wrote the code to do so.</p>
</overview>
<recommendation>
@@ -15,7 +15,7 @@ handle the exception but never wrote the code to do so.</p>
</recommendation>
<example>
<p>In this example the program keeps running with the same privileges if it fails to drop to lower
<p>In this example, the program keeps running with the same privileges if it fails to drop to lower
privileges.</p>
<sample src="EmptyExcept.py" />

View File

@@ -4,25 +4,25 @@
<qhelp>
<overview>
<p><code>NotImplemented</code> is not an Exception, but is often mistakenly used in place of <code>NotImplementedError</code>.
Executing <code>raise NotImplemented</code> or <code>raise NotImplemented()</code> will raise a <code>TypeError</code>.
When <code>raise NotImplemented</code> is used to mark code that is genuinely never called, this mistake is benign.
However, should it be called, then a <code>TypeError</code> will be raised rather than the expected <code>NotImplemented</code>,
which might make debugging the issue difficult.
<p>
The constant <code>NotImplemented</code> is not an <code>Exception</code>, but is often confused for <code>NotImplementedError</code>.
If it is used as an exception, such as in <code>raise NotImplemented</code> or <code>raise NotImplemented("message")</code>,
a <code>TypeError</code> will be raised rather than the expected <code>NotImplemented</code>. This may make debugging more difficult.
</p>
<p>The correct use of <code>NotImplemented</code> is to implement binary operators.
<p><code>NotImplemented</code> should only be used as a special return value for implementing special methods such as <code>__lt__</code>.
Code that is not intended to be called should raise <code>NotImplementedError</code>.</p>
</overview>
<recommendation>
<p>Replace uses of <code>NotImplemented</code> with <code>NotImplementedError</code>.</p>
<p>If a <code>NotImplementedError</code> is intended to be raised, replace the use of <code>NotImplemented</code>
with that. If <code>NotImplemented</code> is intended to be returned rather than raised, replace the <code>raise</code> with <code>return NotImplemented</code>.
</p>
</recommendation>
<example>
<p>
In the example below, the method <code>wrong</code> will incorrectly raise a <code>TypeError</code> when called.
In the following example, the method <code>wrong</code> will incorrectly raise a <code>TypeError</code> when called.
The method <code>right</code> will raise a <code>NotImplementedError</code>.
</p>
@@ -34,6 +34,7 @@ The method <code>right</code> will raise a <code>NotImplementedError</code>.
<references>
<li>Python Language Reference: <a href="https://docs.python.org/library/exceptions.html#NotImplementedError">The NotImplementedError exception</a>.</li>
<li>Python Language Reference: <a href="https://docs.python.org/3/library/constants.html#NotImplemented">The NotImplemented constant</a>.</li>
<li>Python Language Reference: <a href="https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types">Emulating numeric types</a>.</li>
</references>

View File

@@ -1,6 +1,6 @@
/**
* @name NotImplemented is not an Exception
* @description Using 'NotImplemented' as an exception will result in a type error.
* @name Raising `NotImplemented`
* @description Using `NotImplemented` as an exception will result in a type error.
* @kind problem
* @problem.severity warning
* @sub-severity high
@@ -12,8 +12,17 @@
*/
import python
import Exceptions.NotImplemented
import semmle.python.ApiGraphs
predicate raiseNotImplemented(Raise raise, Expr notImpl) {
exists(API::Node n | n = API::builtin("NotImplemented") |
notImpl = n.getACall().asExpr()
or
n.asSource().flowsTo(DataFlow::exprNode(notImpl))
) and
notImpl = raise.getException()
}
from Expr notimpl
where use_of_not_implemented_in_raise(_, notimpl)
where raiseNotImplemented(_, notimpl)
select notimpl, "NotImplemented is not an Exception. Did you mean NotImplementedError?"

View File

@@ -24,7 +24,7 @@ However, this may result in incorrect object initialization if the enclosing cla
</recommendation>
<example>
<p>
In this example the call to <code>super(Vehicle, self)</code> in <code>Car.__init__</code> is incorrect as it
In this example, the call to <code>super(Vehicle, self)</code> in <code>Car.__init__</code> is incorrect, as it
passes <code>Vehicle</code> rather than <code>Car</code> as the first argument to <code>super</code>.
As a result, <code>super(SportsCar, self).__init__()</code> in the <code>SportsCar.__init__</code> method will not call
all <code>__init__()</code> methods because the call to <code>super(Vehicle, self).__init__()</code>
@@ -37,7 +37,7 @@ skips <code>StatusSymbol.__init__()</code>.
</example>
<references>
<li>Python Standard Library: <a href="https://docs.python.org/2/library/functions.html#super">super</a>.</li>
<li>Python Standard Library: <a href="https://docs.python.org/3/library/functions.html#super">super</a>.</li>
<li>Artima Developer: <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=236275">Things to Know About Python Super</a>.</li>

View File

@@ -1,2 +1,2 @@
dictionary = {1:"a", 2:"b", 2:"c"}
print dictionary[2]
dictionary = {1:"a", 2:"b", 2:"c"} # BAD: The `2` key is duplicated.
print(dictionary[2])

View File

@@ -4,8 +4,8 @@
<qhelp>
<overview>
<p>Dictionary literals are constructed in the order given in the source.
This means that if a key is duplicated the second key-value pair will overwrite
the first as a dictionary can only have one value per key.
This means that if a key is duplicated, the second key-value pair will overwrite
the first; as a dictionary can only have one value per key.
</p>
</overview>
@@ -15,14 +15,14 @@ If they are then decide which value is wanted and delete the other one.</p>
</recommendation>
<example>
<p>This example will output "c" because the mapping between 2 and "b" is overwritten by the
mapping from 2 to "c". The programmer may have meant to map 3 to "c" instead.</p>
<p>The following example will output <code>"c"</code>, because the mapping between 2 and <code>"b"</code> is overwritten by the
mapping from 2 to <code>"c"</code>. The programmer may have meant to map 3 to <code>"c"</code> instead.</p>
<sample src="DuplicateKeyInDictionaryLiteral.py" />
</example>
<references>
<li>Python: <a href="http://docs.python.org/2/reference/expressions.html#dictionary-displays">Dictionary literals</a>.</li>
<li>Python: <a href="http://docs.python.org/3/reference/expressions.html#dictionary-displays">Dictionary literals</a>.</li>
</references>
</qhelp>

View File

@@ -17,7 +17,7 @@ wrap the use of the object in a <code>with</code> statement.
</recommendation>
<example>
<p>In the first example, rather than close the zip file in a conventional manner the programmer has called <code>__del__</code>.
<p>In the first example, rather than close the zip file in a conventional manner, the programmer has called <code>__del__</code>.
A safer alternative is shown in the second example.
</p>

View File

@@ -37,7 +37,7 @@ either of the alternatives below.
</example>
<references>
<li>Python Standard Library: <a href="http://docs.python.org/2/library/stdtypes.html#comparisons">Comparisons</a>.</li>
<li>Python Standard Library: <a href="http://docs.python.org/3/library/stdtypes.html#comparisons">Comparisons</a>.</li>
</references>
</qhelp>

View File

@@ -1,6 +1,6 @@
/**
* @name Comparison using is when operands support `__eq__`
* @description Comparison using 'is' when equivalence is not the same as identity
* @description Comparison using `is` when equivalence is not the same as identity
* @kind problem
* @tags quality
* reliability

View File

@@ -3,18 +3,19 @@
"qhelp.dtd">
<qhelp>
<overview>
<p>A format string, that is the string on the left hand side of an expression like <code>fmt % arguments</code>, must consist of legal conversion specifiers.
<p>A printf-style format string (i.e. a string that is used as the left hand side of the <code>%</code> operator, such as <code>fmt % arguments</code>)
must consist of valid conversion specifiers, such as <code>%s</code>, <code>%d</code>, etc.
Otherwise, a <code>ValueError</code> will be raised.
</p>
</overview>
<recommendation>
<p>Choose a legal conversion specifier.</p>
<p>Ensure a valid conversion specifier is used.</p>
</recommendation>
<example>
<p>In <code>format_as_tuple_incorrect</code>, "t" is not a legal conversion specifier.
<p>In the following example, <code>format_as_tuple_incorrect</code>, <code>%t</code> is not a valid conversion specifier.
</p>
<sample src="UnsupportedFormatCharacter.py" />
@@ -22,7 +23,7 @@ Otherwise, a <code>ValueError</code> will be raised.
</example>
<references>
<li>Python Library Reference: <a href="http://docs.python.org/library/stdtypes.html#string-formatting">String Formatting.</a> </li>
<li>Python Library Reference: <a href="https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting">printf-style String Formatting.</a> </li>
</references>
</qhelp>

View File

@@ -6,7 +6,7 @@
<overview>
<p>When a function contains both explicit returns (<code>return value</code>) and implicit returns
(where code falls off the end of a function) this often indicates that a return
(where code falls off the end of a function), this often indicates that a return
statement has been forgotten. It is best to return an explicit return value even when returning
<code>None</code> because this makes it easier for other developers to read your code.
</p>
@@ -29,7 +29,7 @@ return value of <code>None</code> as this equates to <code>False</code>. However
</example>
<references>
<li>Python Language Reference: <a href="http://docs.python.org/2/reference/compound_stmts.html#function">Function definitions</a>.
<li>Python Language Reference: <a href="http://docs.python.org/3/reference/compound_stmts.html#function">Function definitions</a>.
</li>

View File

@@ -1,6 +1,6 @@
/**
* @name Explicit returns mixed with implicit (fall through) returns
* @description Mixing implicit and explicit returns indicates a likely error as implicit returns always return 'None'.
* @description Mixing implicit and explicit returns indicates a likely error as implicit returns always return `None`.
* @kind problem
* @tags quality
* reliability
@@ -31,4 +31,4 @@ predicate has_implicit_return(Function func) {
from Function func
where explicitly_returns_non_none(func) and has_implicit_return(func)
select func,
"Mixing implicit and explicit returns may indicate an error as implicit returns always return None."
"Mixing implicit and explicit returns may indicate an error, as implicit returns always return None."

View File

@@ -22,7 +22,7 @@ not logical in the context of an initializer.</p>
</example>
<references>
<li>Python: <a href="http://docs.python.org/2.7/reference/datamodel.html#object.__init__">The __init__ method</a>.</li>
<li>Python: <a href="http://docs.python.org/3/reference/datamodel.html#object.__init__">The __init__ method</a>.</li>
</references>
</qhelp>

View File

@@ -37,7 +37,7 @@ function with a default of <code>default=None</code>, check if the parameter is
<references>
<li>Effbot: <a href="https://web.archive.org/web/20201112004749/http://effbot.org/zone/default-values.htm">Default Parameter Values in Python</a>.</li>
<li>Python Language Reference: <a href="http://docs.python.org/2/reference/compound_stmts.html#function-definitions">Function definitions</a>.</li>
<li>Python Language Reference: <a href="http://docs.python.org/3/reference/compound_stmts.html#function-definitions">Function definitions</a>.</li>
</references>

View File

@@ -1,2 +1,2 @@
| exceptions_test.py:170:11:170:24 | NotImplemented | NotImplemented is not an Exception. Did you mean NotImplementedError? |
| exceptions_test.py:173:11:173:24 | NotImplemented | NotImplemented is not an Exception. Did you mean NotImplementedError? |
| exceptions_test.py:173:11:173:26 | NotImplemented() | NotImplemented is not an Exception. Did you mean NotImplementedError? |

View File

@@ -1,4 +1,4 @@
| functions_test.py:18:1:18:11 | Function cr1 | Mixing implicit and explicit returns may indicate an error as implicit returns always return None. |
| functions_test.py:22:1:22:11 | Function cr2 | Mixing implicit and explicit returns may indicate an error as implicit returns always return None. |
| functions_test.py:336:1:336:16 | Function ok_match | Mixing implicit and explicit returns may indicate an error as implicit returns always return None. |
| functions_test.py:344:1:344:17 | Function ok_match2 | Mixing implicit and explicit returns may indicate an error as implicit returns always return None. |
| functions_test.py:18:1:18:11 | Function cr1 | Mixing implicit and explicit returns may indicate an error, as implicit returns always return None. |
| functions_test.py:22:1:22:11 | Function cr2 | Mixing implicit and explicit returns may indicate an error, as implicit returns always return None. |
| functions_test.py:336:1:336:16 | Function ok_match | Mixing implicit and explicit returns may indicate an error, as implicit returns always return None. |
| functions_test.py:344:1:344:17 | Function ok_match2 | Mixing implicit and explicit returns may indicate an error, as implicit returns always return None. |

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The regular expressions in `SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.

View File

@@ -256,7 +256,6 @@ lib/codeql/rust/elements/internal/ConstParamImpl.qll c6995be58f84d1df65897c80f7e
lib/codeql/rust/elements/internal/ContinueExprConstructor.qll cd93f1b35ccdb031d7e8deba92f6a76187f6009c454f3ea07e89ba459de57ca6 6f658e7d580c4c9068b01d6dd6f72888b8800860668a6653f8c3b27dc9996935
lib/codeql/rust/elements/internal/CrateConstructor.qll 2a3710ed6ff4ffdbc773ac16e2cf176415be8908e1d59fd0702bdeddbae096f4 f75a069b0ef71e54089001eb3a34b8a9e4ce8e4f65ffa71b669b38cf86e0af40
lib/codeql/rust/elements/internal/DynTraitTypeReprConstructor.qll 6964e6c80fb7f5e283c1d15562cef18ed097452b7fcbc04eff780c7646675c7a f03c4830bf1b958fdfb6563136fa21c911b2e41ce1d1caee14ec572c7232866d
lib/codeql/rust/elements/internal/DynTraitTypeReprImpl.qll 635b491538a2ede0b2cf8ecaa1cea21e115a707dec4e023fcdbc1f7197615e8c 7a0dc718656631e08c4becc53174af42fbaaa639e252fb087d4317f5add840dc
lib/codeql/rust/elements/internal/EnumConstructor.qll eca1a13937faacb1db50e4cf69d175f992f2204a5aaed9144bb6f3cb63814ac5 1bafba78b2729fdb052a25a1ba3f4f70871564aa4df632b4a1d467858a437924
lib/codeql/rust/elements/internal/ExprImpl.qll ab20ee174e2e786f34af6e5dedf3ec071bb89fc266b3e91df6377f72aa38d3f2 f68192700f449bf1c229cfbaabd5353c7c559941c915d5a0c88752cf9844194b
lib/codeql/rust/elements/internal/ExprStmtConstructor.qll dd6bb06a7d48c12f630aafd611621cc50ce0f3e7d9abba5484a695f90879264b dc8b6ec8acc314e041ae71868803630c5d4cab488c72c1ea929bb756e1847c52
@@ -289,7 +288,6 @@ lib/codeql/rust/elements/internal/IdentPatConstructor.qll 09792f5a070996b65f095d
lib/codeql/rust/elements/internal/IfExprConstructor.qll 03088b54c8fa623f93a5b5a7eb896f680e8b0e9025488157a02c48aaebc6ad56 906f916c3690d0721a31dd31b302dcdcec4233bb507683007d82cf10793a648f
lib/codeql/rust/elements/internal/ImplConstructor.qll 24edccca59f70d812d1458b412a45310ddc096d095332f6e3258903c54c1bb44 7eb673b3ab33a0873ee5ce189105425066b376821cce0fc9eb8ace22995f0bc7
lib/codeql/rust/elements/internal/ImplTraitTypeReprConstructor.qll 1ed355e5e56f432b24b6f4778e4dc45c6e65095190cacb7a5015529e0c9d01f8 c8505185a042da4eb20a0cc32323194a0290c4bf821c7e0fce7351b194b10f31
lib/codeql/rust/elements/internal/ImplTraitTypeReprImpl.qll 26259dfa599f48fb00ff7e5e17e9a8b40c29360f02cf11abc4ccbb573996f5bb 5b4c0e29e9c20c3121e3f37f1f1cba3f181d56023e9912c6dc5c481cb8ee3e4d
lib/codeql/rust/elements/internal/IndexExprConstructor.qll 99bdc3d793c4dbd993860da60abe2b7c604345d645e86916462bc55a6939a5d1 3fe9d7da725956903707806aadbecac8d5b3874e8bed63c9bab54fff630e75dd
lib/codeql/rust/elements/internal/InferTypeReprConstructor.qll bc5f16853401617fc9c5af8a1287a23c5921df1b615cfbe2d7c7a70145ecfcbd da93bd28ea2daade2cbb0a729be3fbf05f72bc02009565c7bb062e4f68fdb9e7
lib/codeql/rust/elements/internal/ItemImpl.qll e3fb78d572ce1c3cc857d2671bd71ff4d7850321acfddc5f15533ff87accda79 fbabc2081e4b2773b04938d57bb51af908c80b7bc53c3127c74ab5d4fb9837bc

2
rust/ql/.gitattributes generated vendored
View File

@@ -258,7 +258,6 @@
/lib/codeql/rust/elements/internal/ContinueExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/CrateConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/DynTraitTypeReprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/DynTraitTypeReprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/EnumConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ExprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/ExprStmtConstructor.qll linguist-generated
@@ -291,7 +290,6 @@
/lib/codeql/rust/elements/internal/IfExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ImplConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ImplTraitTypeReprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ImplTraitTypeReprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/IndexExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/InferTypeReprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/ItemImpl.qll linguist-generated

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The regular expressions in `SensitiveDataHeuristics.qll` have been extended to find more instances of sensitive data such as secrets used in authentication, finance and health information, and device data. The heuristics have also been refined to find fewer false positive matches. This will improve results for queries related to sensitive information.

View File

@@ -5,5 +5,4 @@
private import codeql.rust.frameworks.rustcrypto.RustCrypto
private import codeql.rust.frameworks.Poem
private import codeql.rust.frameworks.Sqlx
private import codeql.rust.frameworks.stdlib.Clone
private import codeql.rust.frameworks.stdlib.Stdlib

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `DynTraitTypeRepr`.
*
@@ -12,6 +11,10 @@ private import codeql.rust.elements.internal.generated.DynTraitTypeRepr
* be referenced directly.
*/
module Impl {
private import rust
private import codeql.rust.internal.PathResolution as PathResolution
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A dynamic trait object type.
*
@@ -21,5 +24,16 @@ module Impl {
* // ^^^^^^^^^
* ```
*/
class DynTraitTypeRepr extends Generated::DynTraitTypeRepr { }
class DynTraitTypeRepr extends Generated::DynTraitTypeRepr {
/** Gets the trait that this trait object refers to. */
pragma[nomagic]
Trait getTrait() {
result =
PathResolution::resolvePath(this.getTypeBoundList()
.getBound(0)
.getTypeRepr()
.(PathTypeRepr)
.getPath())
}
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `ImplTraitTypeRepr`.
*
@@ -6,12 +5,14 @@
*/
private import codeql.rust.elements.internal.generated.ImplTraitTypeRepr
private import rust
/**
* INTERNAL: This module contains the customizable definition of `ImplTraitTypeRepr` and should not
* be referenced directly.
*/
module Impl {
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* An `impl Trait` type.
*
@@ -21,5 +22,15 @@ module Impl {
* // ^^^^^^^^^^^^^^^^^^^^^^^^^^
* ```
*/
class ImplTraitTypeRepr extends Generated::ImplTraitTypeRepr { }
class ImplTraitTypeRepr extends Generated::ImplTraitTypeRepr {
/** Gets the function for which this impl trait type occurs, if any. */
Function getFunction() {
this.getParentNode*() = [result.getRetType().getTypeRepr(), result.getAParam().getTypeRepr()]
}
/** Holds if this impl trait type occurs in the return type of a function. */
predicate isInReturnPos() {
this.getParentNode*() = this.getFunction().getRetType().getTypeRepr()
}
}
}

View File

@@ -1,22 +0,0 @@
/** A model for `clone` on the `Clone` trait. */
private import rust
private import codeql.rust.dataflow.FlowSummary
/** A `clone` method. */
final class CloneCallable extends SummarizedCallable::Range {
CloneCallable() {
this.getParamList().hasSelfParam() and
this.getParamList().getNumberOfParams() = 0 and
this.getName().getText() = "clone"
}
final override predicate propagatesFlow(
string input, string output, boolean preservesValue, string model
) {
input = "Argument[self].Reference" and
output = "ReturnValue" and
preservesValue = true and
model = "generated"
}
}

View File

@@ -3,6 +3,8 @@ extensions:
pack: codeql/rust-all
extensible: summaryModel
data:
# Clone
- ["<_ as core::clone::Clone>::clone", "Argument[self].Reference", "ReturnValue", "value", "manual"]
# Conversions
- ["<core::alloc::layout::Layout>::align_to", "Argument[self].Element", "ReturnValue.Field[0,1,2].Reference.Element", "taint", "manual"]
- ["<_ as core::convert::Into>::into", "Argument[self].Element", "ReturnValue.Element", "taint", "manual"]

View File

@@ -7,6 +7,27 @@ private import codeql.rust.internal.CachedStages
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
/**
* Holds if a dyn trait type should have a type parameter associated with `n`. A
* dyn trait type inherits the type parameters of the trait it implements. That
* includes the type parameters corresponding to associated types.
*
* For instance in
* ```rust
* trait SomeTrait<A> {
* type AssociatedType;
* }
* ```
* this predicate holds for the nodes `A` and `type AssociatedType`.
*/
private predicate dynTraitTypeParameter(Trait trait, AstNode n) {
trait = any(DynTraitTypeRepr dt).getTrait() and
(
n = trait.getGenericParamList().getATypeParam() or
n = trait.(TraitItemNode).getAnAssocItem().(TypeAlias)
)
}
cached
newtype TType =
TTuple(int arity) {
@@ -24,15 +45,28 @@ newtype TType =
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(ImplTraitTypeRepr impl) or
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
TSliceType() or
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
TArrayTypeParameter() or
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) {
implTraitTypeParam(implTrait, _, tp)
} or
TRefTypeParameter() or
TSelfTypeParameter(Trait t) or
TSliceTypeParameter()
predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
implTrait.isInReturnPos() and
tp = implTrait.getFunction().getGenericParamList().getTypeParam(i) and
// Only include type parameters of the function that occur inside the impl
// trait type.
exists(Path path | path.getParentNode*() = implTrait and resolvePath(path) = tp)
}
/**
* A type without type arguments.
*
@@ -240,13 +274,38 @@ class ImplTraitType extends Type, TImplTraitType {
override TupleField getTupleField(int i) { none() }
override TypeParameter getTypeParameter(int i) { none() }
override TypeParameter getTypeParameter(int i) {
exists(TypeParam tp |
implTraitTypeParam(impl, i, tp) and
result = TImplTraitTypeParameter(impl, tp)
)
}
override string toString() { result = impl.toString() }
override Location getLocation() { result = impl.getLocation() }
}
class DynTraitType extends Type, TDynTraitType {
Trait trait;
DynTraitType() { this = TDynTraitType(trait) }
override StructField getStructField(string name) { none() }
override TupleField getTupleField(int i) { none() }
override DynTraitTypeParameter getTypeParameter(int i) {
result = TDynTraitTypeParameter(trait.getGenericParamList().getTypeParam(i))
}
Trait getTrait() { result = trait }
override string toString() { result = "dyn " + trait.getName().toString() }
override Location getLocation() { result = trait.getLocation() }
}
/**
* An [impl Trait in return position][1] type, for example:
*
@@ -259,7 +318,7 @@ class ImplTraitType extends Type, TImplTraitType {
class ImplTraitReturnType extends ImplTraitType {
private Function function;
ImplTraitReturnType() { impl = function.getRetType().getTypeRepr() }
ImplTraitReturnType() { impl.isInReturnPos() and function = impl.getFunction() }
override Function getFunction() { result = function }
}
@@ -381,6 +440,53 @@ class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
override Location getLocation() { result instanceof EmptyLocation }
}
class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
private AstNode n;
DynTraitTypeParameter() { this = TDynTraitTypeParameter(n) }
Trait getTrait() { dynTraitTypeParameter(result, n) }
/** Gets the dyn trait type that this type parameter belongs to. */
DynTraitType getDynTraitType() { result.getTrait() = this.getTrait() }
/** Gets the `TypeParam` of this dyn trait type parameter, if any. */
TypeParam getTypeParam() { result = n }
/** Gets the `TypeAlias` of this dyn trait type parameter, if any. */
TypeAlias getTypeAlias() { result = n }
/** Gets the trait type parameter that this dyn trait type parameter corresponds to. */
TypeParameter getTraitTypeParameter() {
result.(TypeParamTypeParameter).getTypeParam() = n
or
result.(AssociatedTypeTypeParameter).getTypeAlias() = n
}
private string toStringInner() {
result = [this.getTypeParam().toString(), this.getTypeAlias().getName().toString()]
}
override string toString() { result = "dyn(" + this.toStringInner() + ")" }
override Location getLocation() { result = n.getLocation() }
}
class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
private TypeParam typeParam;
private ImplTraitTypeRepr implTrait;
ImplTraitTypeParameter() { this = TImplTraitTypeParameter(implTrait, typeParam) }
TypeParam getTypeParam() { result = typeParam }
ImplTraitTypeRepr getImplTraitTypeRepr() { result = implTrait }
override string toString() { result = "impl(" + typeParam.toString() + ")" }
override Location getLocation() { result = typeParam.getLocation() }
}
/** An implicit reference type parameter. */
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
override string toString() { result = "&T" }
@@ -465,6 +571,12 @@ final class ImplTypeAbstraction extends TypeAbstraction, Impl {
}
}
final class DynTypeAbstraction extends TypeAbstraction, DynTraitTypeRepr {
override TypeParameter getATypeParameter() {
result = any(DynTraitTypeParameter tp | tp.getTrait() = this.getTrait()).getTraitTypeParameter()
}
}
final class TraitTypeAbstraction extends TypeAbstraction, Trait {
override TypeParameter getATypeParameter() {
result.(TypeParamTypeParameter).getTypeParam() = this.getGenericParamList().getATypeParam()
@@ -488,5 +600,7 @@ final class SelfTypeBoundTypeAbstraction extends TypeAbstraction, Name {
}
final class ImplTraitTypeReprAbstraction extends TypeAbstraction, ImplTraitTypeRepr {
override TypeParameter getATypeParameter() { none() }
override TypeParameter getATypeParameter() {
implTraitTypeParam(this, _, result.(TypeParamTypeParameter).getTypeParam())
}
}

View File

@@ -83,35 +83,48 @@ private module Input1 implements InputSig1<Location> {
int getTypeParameterId(TypeParameter tp) {
tp =
rank[result](TypeParameter tp0, int kind, int id |
rank[result](TypeParameter tp0, int kind, int id1, int id2 |
tp0 instanceof ArrayTypeParameter and
kind = 0 and
id = 0
id1 = 0 and
id2 = 0
or
tp0 instanceof RefTypeParameter and
kind = 0 and
id = 1
id1 = 0 and
id2 = 1
or
tp0 instanceof SliceTypeParameter and
kind = 0 and
id = 2
id1 = 0 and
id2 = 2
or
kind = 1 and
exists(AstNode node | id = idOfTypeParameterAstNode(node) |
id1 = 0 and
id2 =
idOfTypeParameterAstNode([
tp0.(DynTraitTypeParameter).getTypeParam().(AstNode),
tp0.(DynTraitTypeParameter).getTypeAlias()
])
or
kind = 2 and
id1 = idOfTypeParameterAstNode(tp0.(ImplTraitTypeParameter).getImplTraitTypeRepr()) and
id2 = idOfTypeParameterAstNode(tp0.(ImplTraitTypeParameter).getTypeParam())
or
kind = 3 and
id1 = 0 and
exists(AstNode node | id2 = idOfTypeParameterAstNode(node) |
node = tp0.(TypeParamTypeParameter).getTypeParam() or
node = tp0.(AssociatedTypeTypeParameter).getTypeAlias() or
node = tp0.(SelfTypeParameter).getTrait() or
node = tp0.(ImplTraitTypeTypeParameter).getImplTraitTypeRepr()
)
or
exists(TupleTypeParameter ttp, int maxArity |
maxArity = max(int i | i = any(TupleType tt).getArity()) and
tp0 = ttp and
kind = 2 and
id = ttp.getTupleType().getArity() * maxArity + ttp.getIndex()
)
kind = 4 and
id1 = tp0.(TupleTypeParameter).getTupleType().getArity() and
id2 = tp0.(TupleTypeParameter).getIndex()
|
tp0 order by kind, id
tp0 order by kind, id1, id2
)
}
}
@@ -189,6 +202,14 @@ private module Input2 implements InputSig2 {
condition = impl and
constraint = impl.getTypeBoundList().getABound().getTypeRepr()
)
or
// a `dyn Trait` type implements `Trait`. See the comment on
// `DynTypeBoundListMention` for further details.
exists(DynTraitTypeRepr object |
abs = object and
condition = object.getTypeBoundList() and
constraint = object.getTrait()
)
}
}
@@ -1715,10 +1736,16 @@ private Function getMethodFromImpl(MethodCall mc) {
bindingset[trait, name]
pragma[inline_late]
private Function getTraitMethod(ImplTraitReturnType trait, string name) {
private Function getImplTraitMethod(ImplTraitReturnType trait, string name) {
result = getMethodSuccessor(trait.getImplTraitTypeRepr(), name)
}
bindingset[traitObject, name]
pragma[inline_late]
private Function getDynTraitMethod(DynTraitType traitObject, string name) {
result = getMethodSuccessor(traitObject.getTrait(), name)
}
pragma[nomagic]
private Function resolveMethodCallTarget(MethodCall mc) {
// The method comes from an `impl` block targeting the type of the receiver.
@@ -1729,7 +1756,10 @@ private Function resolveMethodCallTarget(MethodCall mc) {
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
or
// The type of the receiver is an `impl Trait` type.
result = getTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
result = getImplTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
or
// The type of the receiver is a trait object `dyn Trait` type.
result = getDynTraitMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())
}
pragma[nomagic]
@@ -2073,6 +2103,13 @@ private module Debug {
result = resolveCallTarget(c)
}
predicate debugConditionSatisfiesConstraint(
TypeAbstraction abs, TypeMention condition, TypeMention constraint
) {
abs = getRelevantLocatable() and
Input2::conditionSatisfiesConstraint(abs, condition, constraint)
}
predicate debugInferImplicitSelfType(SelfParam self, TypePath path, Type t) {
self = getRelevantLocatable() and
t = inferImplicitSelfType(self, path)

View File

@@ -258,6 +258,12 @@ class ImplTraitTypeReprMention extends TypeMention instanceof ImplTraitTypeRepr
override Type resolveTypeAt(TypePath typePath) {
typePath.isEmpty() and
result.(ImplTraitType).getImplTraitTypeRepr() = this
or
exists(ImplTraitTypeParameter tp |
this = tp.getImplTraitTypeRepr() and
typePath = TypePath::singleton(tp) and
result = TTypeParamTypeParameter(tp.getTypeParam())
)
}
}
@@ -309,3 +315,64 @@ class SelfTypeParameterMention extends TypeMention instanceof Name {
result = TSelfTypeParameter(trait)
}
}
class DynTraitTypeReprMention extends TypeMention instanceof DynTraitTypeRepr {
private DynTraitType dynType;
DynTraitTypeReprMention() {
// This excludes `DynTraitTypeRepr` elements where `getTrait` is not
// defined, i.e., where path resolution can't find a trait.
dynType.getTrait() = super.getTrait()
}
override Type resolveTypeAt(TypePath path) {
path.isEmpty() and
result = dynType
or
exists(DynTraitTypeParameter tp, TypePath path0, TypePath suffix |
dynType = tp.getDynTraitType() and
path = TypePath::cons(tp, suffix) and
result = super.getTypeBoundList().getBound(0).getTypeRepr().(TypeMention).resolveTypeAt(path0) and
path0.isCons(tp.getTraitTypeParameter(), suffix)
)
}
}
// We want a type of the form `dyn Trait` to implement `Trait`. If `Trait` has
// type parameters then `dyn Trait` has equivalent type parameters and the
// implementation should be abstracted over them.
//
// Intuitively we want something to the effect of:
// ```
// impl<A, B, ..> Trait<A, B, ..> for (dyn Trait)<A, B, ..>
// ```
// To achieve this:
// - `DynTypeAbstraction` is an abstraction over type parameters of the trait.
// - `DynTypeBoundListMention` (this class) is a type mention which has `dyn
// Trait` at the root and which for every type parameter of `dyn Trait` has the
// corresponding type parameter of the trait.
// - `TraitMention` (which is used for other things as well) is a type mention
// for the trait applied to its own type parameters.
//
// We arbitrarily use the `TypeBoundList` inside `DynTraitTypeRepr` to encode
// this type mention, since it doesn't syntactically appear in the AST. This
// works because there is a one-to-one correspondence between a trait object and
// its list of type bounds.
class DynTypeBoundListMention extends TypeMention instanceof TypeBoundList {
private Trait trait;
DynTypeBoundListMention() {
exists(DynTraitTypeRepr dyn | this = dyn.getTypeBoundList() and trait = dyn.getTrait())
}
override Type resolveTypeAt(TypePath path) {
path.isEmpty() and
result.(DynTraitType).getTrait() = trait
or
exists(DynTraitTypeParameter tp |
trait = tp.getTrait() and
path = TypePath::singleton(tp) and
result = tp.getTraitTypeParameter()
)
}
}

View File

@@ -69,7 +69,8 @@ module SanitizerGuard {
*/
private class DotDotCheck extends SanitizerGuard::Range, CfgNodes::MethodCallExprCfgNode {
DotDotCheck() {
this.getAstNode().(Resolvable).getResolvedPath() = "<str>::contains" and
this.getAstNode().(CallExprBase).getStaticTarget().(Addressable).getCanonicalPath() =
["<alloc::string::String>::contains", "<core::str>::contains"] and
this.getArgument(0).getAstNode().(LiteralExpr).getTextValue() =
["\"..\"", "\"../\"", "\"..\\\""]
}

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Type inference now supports trait objects, i.e., `dyn Trait` types.

View File

@@ -34,6 +34,8 @@ module RegexInjectionConfig implements DataFlow::ConfigSig {
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
any(AdditionalFlowStep s).step(nodeFrom, nodeTo)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -79,6 +79,8 @@ module TaintedPathConfig implements DataFlow::StateConfigSig {
stateFrom instanceof NotNormalized and
stateTo instanceof NormalizedUnchecked
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module TaintedPathFlow = TaintTracking::GlobalWithState<TaintedPathConfig>;

View File

@@ -26,6 +26,8 @@ module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
}
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;

View File

@@ -37,6 +37,8 @@ module CleartextTransmissionConfig implements DataFlow::ConfigSig {
// make sources barriers so that we only report the closest instance
isSource(node)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module CleartextTransmissionFlow = TaintTracking::Global<CleartextTransmissionConfig>;

View File

@@ -45,6 +45,8 @@ module CleartextLoggingConfig implements DataFlow::ConfigSig {
isSink(node) and
c.getAReadContent() instanceof DataFlow::TuplePositionContent
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;

View File

@@ -32,6 +32,8 @@ module UncontrolledAllocationConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
}
module UncontrolledAllocationFlow = TaintTracking::Global<UncontrolledAllocationConfig>;

View File

@@ -28,10 +28,33 @@ module AccessAfterLifetimeConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node node) { node instanceof AccessAfterLifetime::Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof AccessAfterLifetime::Barrier }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) {
exists(Variable target, DataFlow::Node sink | result = target.getLocation() |
isSink(sink) and
narrowDereferenceAfterLifetime(source, sink, target)
)
}
}
module AccessAfterLifetimeFlow = TaintTracking::Global<AccessAfterLifetimeConfig>;
pragma[inline]
predicate narrowDereferenceAfterLifetime(DataFlow::Node source, DataFlow::Node sink, Variable target) {
// check that the dereference is outside the lifetime of the target
AccessAfterLifetime::dereferenceAfterLifetime(source, sink, target) and
// include only results inside `unsafe` blocks, as other results tend to be false positives
(
sink.asExpr().getExpr().getEnclosingBlock*().isUnsafe() or
sink.asExpr().getExpr().getEnclosingCallable().(Function).isUnsafe()
) and
// exclude cases with sources / sinks in macros, since these results are difficult to interpret
not source.asExpr().getExpr().isFromMacroExpansion() and
not sink.asExpr().getExpr().isFromMacroExpansion()
}
from
AccessAfterLifetimeFlow::PathNode sourceNode, AccessAfterLifetimeFlow::PathNode sinkNode,
Variable target
@@ -39,14 +62,6 @@ where
// flow from a pointer or reference to the dereference
AccessAfterLifetimeFlow::flowPath(sourceNode, sinkNode) and
// check that the dereference is outside the lifetime of the target
AccessAfterLifetime::dereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target) and
// include only results inside `unsafe` blocks, as other results tend to be false positives
(
sinkNode.getNode().asExpr().getExpr().getEnclosingBlock*().isUnsafe() or
sinkNode.getNode().asExpr().getExpr().getEnclosingCallable().(Function).isUnsafe()
) and
// exclude cases with sources / sinks in macros, since these results are difficult to interpret
not sourceNode.getNode().asExpr().getExpr().isFromMacroExpansion() and
not sinkNode.getNode().asExpr().getExpr().isFromMacroExpansion()
narrowDereferenceAfterLifetime(sourceNode.getNode(), sinkNode.getNode(), target)
select sinkNode.getNode(), sourceNode, sinkNode,
"Access of a pointer to $@ after its lifetime has ended.", target, target.toString()

View File

@@ -32,6 +32,8 @@ module AccessInvalidPointerConfig implements DataFlow::ConfigSig {
// make sinks barriers so that we only report the closest instance
isSink(node)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
module AccessInvalidPointerFlow = TaintTracking::Global<AccessInvalidPointerConfig>;

View File

@@ -1,41 +1,42 @@
models
| 1 | Summary: <alloc::boxed::Box>::into_pin; Argument[0]; ReturnValue; value |
| 2 | Summary: <alloc::boxed::Box>::new; Argument[0]; ReturnValue.Reference; value |
| 3 | Summary: <alloc::boxed::Box>::pin; Argument[0]; ReturnValue.Reference; value |
| 4 | Summary: <core::i64 as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
| 5 | Summary: <core::option::Option>::unwrap; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
| 6 | Summary: <core::option::Option>::zip; Argument[0].Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Field[1]; value |
| 7 | Summary: <core::pin::Pin>::into_inner; Argument[0].Field[core::pin::Pin::__pointer]; ReturnValue; value |
| 8 | Summary: <core::pin::Pin>::into_inner; Argument[0]; ReturnValue; value |
| 9 | Summary: <core::pin::Pin>::into_inner_unchecked; Argument[0]; ReturnValue; value |
| 10 | Summary: <core::pin::Pin>::new; Argument[0].Reference; ReturnValue; value |
| 11 | Summary: <core::pin::Pin>::new; Argument[0]; ReturnValue.Field[core::pin::Pin::__pointer]; value |
| 12 | Summary: <core::pin::Pin>::new; Argument[0]; ReturnValue; value |
| 13 | Summary: <core::pin::Pin>::new_unchecked; Argument[0].Reference; ReturnValue; value |
| 14 | Summary: <core::result::Result>::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
| 15 | Summary: core::ptr::read; Argument[0].Reference; ReturnValue; value |
| 16 | Summary: core::ptr::write; Argument[1]; Argument[0].Reference; value |
| 1 | Summary: <_ as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
| 2 | Summary: <alloc::boxed::Box>::into_pin; Argument[0]; ReturnValue; value |
| 3 | Summary: <alloc::boxed::Box>::new; Argument[0]; ReturnValue.Reference; value |
| 4 | Summary: <alloc::boxed::Box>::pin; Argument[0]; ReturnValue.Reference; value |
| 5 | Summary: <core::i64 as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
| 6 | Summary: <core::option::Option>::unwrap; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
| 7 | Summary: <core::option::Option>::zip; Argument[0].Field[core::option::Option::Some(0)]; ReturnValue.Field[core::option::Option::Some(0)].Field[1]; value |
| 8 | Summary: <core::pin::Pin>::into_inner; Argument[0].Field[core::pin::Pin::__pointer]; ReturnValue; value |
| 9 | Summary: <core::pin::Pin>::into_inner; Argument[0]; ReturnValue; value |
| 10 | Summary: <core::pin::Pin>::into_inner_unchecked; Argument[0]; ReturnValue; value |
| 11 | Summary: <core::pin::Pin>::new; Argument[0].Reference; ReturnValue; value |
| 12 | Summary: <core::pin::Pin>::new; Argument[0]; ReturnValue.Field[core::pin::Pin::__pointer]; value |
| 13 | Summary: <core::pin::Pin>::new; Argument[0]; ReturnValue; value |
| 14 | Summary: <core::pin::Pin>::new_unchecked; Argument[0].Reference; ReturnValue; value |
| 15 | Summary: <core::result::Result>::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
| 16 | Summary: core::ptr::read; Argument[0].Reference; ReturnValue; value |
| 17 | Summary: core::ptr::write; Argument[1]; Argument[0].Reference; value |
edges
| main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:5 |
| main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:6 |
| main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | |
| main.rs:12:13:12:28 | Some(...) [Some] | main.rs:12:9:12:9 | a [Some] | provenance | |
| main.rs:12:18:12:27 | source(...) | main.rs:12:13:12:28 | Some(...) [Some] | provenance | |
| main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:5 |
| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated |
| main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:6 |
| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | MaD:1 |
| main.rs:14:13:14:21 | a.clone() [Some] | main.rs:14:9:14:9 | b [Some] | provenance | |
| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:14 |
| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:15 |
| main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | |
| main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | |
| main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | |
| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:14 |
| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated |
| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:15 |
| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | MaD:1 |
| main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | |
| main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | |
| main.rs:26:9:26:9 | a | main.rs:28:13:28:13 | a | provenance | |
| main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | a | provenance | |
| main.rs:28:9:28:9 | b | main.rs:29:10:29:10 | b | provenance | |
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | MaD:4 |
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | generated |
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | MaD:1 |
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | MaD:5 |
| main.rs:28:13:28:21 | a.clone() | main.rs:28:9:28:9 | b | provenance | |
| main.rs:43:18:43:22 | SelfParam [Wrapper] | main.rs:44:26:44:29 | self [Wrapper] | provenance | |
| main.rs:44:13:44:33 | Wrapper {...} [Wrapper] | main.rs:43:33:45:9 | { ... } [Wrapper] | provenance | |
@@ -46,12 +47,10 @@ edges
| main.rs:49:30:49:39 | source(...) | main.rs:49:17:49:41 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:50:15:50:15 | w [Wrapper] | main.rs:43:18:43:22 | SelfParam [Wrapper] | provenance | |
| main.rs:50:15:50:15 | w [Wrapper] | main.rs:51:13:51:28 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:50:15:50:15 | w [Wrapper] | main.rs:53:17:53:17 | w [Wrapper] | provenance | |
| main.rs:50:15:50:15 | w [Wrapper] | main.rs:53:17:53:25 | w.clone() [Wrapper] | provenance | |
| main.rs:51:13:51:28 | Wrapper {...} [Wrapper] | main.rs:51:26:51:26 | n | provenance | |
| main.rs:51:26:51:26 | n | main.rs:51:38:51:38 | n | provenance | |
| main.rs:53:13:53:13 | u [Wrapper] | main.rs:54:15:54:15 | u [Wrapper] | provenance | |
| main.rs:53:17:53:17 | w [Wrapper] | main.rs:53:17:53:25 | w.clone() [Wrapper] | provenance | generated |
| main.rs:53:17:53:25 | w.clone() [Wrapper] | main.rs:53:13:53:13 | u [Wrapper] | provenance | |
| main.rs:54:15:54:15 | u [Wrapper] | main.rs:55:13:55:28 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:55:13:55:28 | Wrapper {...} [Wrapper] | main.rs:55:26:55:26 | n | provenance | |
@@ -61,14 +60,14 @@ edges
| main.rs:66:22:66:31 | source(...) | main.rs:66:17:66:32 | Some(...) [Some] | provenance | |
| main.rs:67:13:67:13 | z [Some, tuple.1] | main.rs:68:15:68:15 | z [Some, tuple.1] | provenance | |
| main.rs:67:17:67:24 | a.zip(...) [Some, tuple.1] | main.rs:67:13:67:13 | z [Some, tuple.1] | provenance | |
| main.rs:67:23:67:23 | b [Some] | main.rs:67:17:67:24 | a.zip(...) [Some, tuple.1] | provenance | MaD:6 |
| main.rs:67:23:67:23 | b [Some] | main.rs:67:17:67:24 | a.zip(...) [Some, tuple.1] | provenance | MaD:7 |
| main.rs:68:15:68:15 | z [Some, tuple.1] | main.rs:69:13:69:24 | Some(...) [Some, tuple.1] | provenance | |
| main.rs:69:13:69:24 | Some(...) [Some, tuple.1] | main.rs:69:18:69:23 | TuplePat [tuple.1] | provenance | |
| main.rs:69:18:69:23 | TuplePat [tuple.1] | main.rs:69:22:69:22 | m | provenance | |
| main.rs:69:22:69:22 | m | main.rs:71:22:71:22 | m | provenance | |
| main.rs:92:29:92:29 | [post] y [&ref] | main.rs:93:33:93:33 | y [&ref] | provenance | |
| main.rs:92:32:92:41 | source(...) | main.rs:92:29:92:29 | [post] y [&ref] | provenance | MaD:16 |
| main.rs:93:33:93:33 | y [&ref] | main.rs:93:18:93:34 | ...::read(...) | provenance | MaD:15 |
| main.rs:92:32:92:41 | source(...) | main.rs:92:29:92:29 | [post] y [&ref] | provenance | MaD:17 |
| main.rs:93:33:93:33 | y [&ref] | main.rs:93:18:93:34 | ...::read(...) | provenance | MaD:16 |
| main.rs:108:13:108:17 | mut i | main.rs:109:34:109:34 | i | provenance | |
| main.rs:108:13:108:17 | mut i | main.rs:110:33:110:33 | i | provenance | |
| main.rs:108:13:108:17 | mut i | main.rs:111:47:111:47 | i | provenance | |
@@ -79,20 +78,20 @@ edges
| main.rs:109:13:109:20 | mut pin1 [Pin, &ref] | main.rs:115:31:115:34 | pin1 [Pin, &ref] | provenance | |
| main.rs:109:24:109:35 | ...::new(...) [&ref] | main.rs:109:13:109:20 | mut pin1 [&ref] | provenance | |
| main.rs:109:24:109:35 | ...::new(...) [Pin, &ref] | main.rs:109:13:109:20 | mut pin1 [Pin, &ref] | provenance | |
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [&ref] | provenance | MaD:12 |
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [Pin, &ref] | provenance | MaD:11 |
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [&ref] | provenance | MaD:13 |
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [Pin, &ref] | provenance | MaD:12 |
| main.rs:109:34:109:34 | i | main.rs:109:33:109:34 | &i [&ref] | provenance | |
| main.rs:110:13:110:20 | mut pin2 [&ref] | main.rs:116:15:116:18 | pin2 [&ref] | provenance | |
| main.rs:110:24:110:34 | ...::pin(...) [&ref] | main.rs:110:13:110:20 | mut pin2 [&ref] | provenance | |
| main.rs:110:33:110:33 | i | main.rs:110:24:110:34 | ...::pin(...) [&ref] | provenance | MaD:3 |
| main.rs:110:33:110:33 | i | main.rs:110:24:110:34 | ...::pin(...) [&ref] | provenance | MaD:4 |
| main.rs:111:13:111:20 | mut pin3 [&ref] | main.rs:117:15:117:18 | pin3 [&ref] | provenance | |
| main.rs:111:24:111:49 | ...::into_pin(...) [&ref] | main.rs:111:13:111:20 | mut pin3 [&ref] | provenance | |
| main.rs:111:38:111:48 | ...::new(...) [&ref] | main.rs:111:24:111:49 | ...::into_pin(...) [&ref] | provenance | MaD:1 |
| main.rs:111:47:111:47 | i | main.rs:111:38:111:48 | ...::new(...) [&ref] | provenance | MaD:2 |
| main.rs:111:38:111:48 | ...::new(...) [&ref] | main.rs:111:24:111:49 | ...::into_pin(...) [&ref] | provenance | MaD:2 |
| main.rs:111:47:111:47 | i | main.rs:111:38:111:48 | ...::new(...) [&ref] | provenance | MaD:3 |
| main.rs:114:15:114:18 | pin1 [&ref] | main.rs:114:14:114:18 | * ... | provenance | |
| main.rs:115:15:115:35 | ...::into_inner(...) [&ref] | main.rs:115:14:115:35 | * ... | provenance | |
| main.rs:115:31:115:34 | pin1 [&ref] | main.rs:115:15:115:35 | ...::into_inner(...) [&ref] | provenance | MaD:8 |
| main.rs:115:31:115:34 | pin1 [Pin, &ref] | main.rs:115:15:115:35 | ...::into_inner(...) [&ref] | provenance | MaD:7 |
| main.rs:115:31:115:34 | pin1 [&ref] | main.rs:115:15:115:35 | ...::into_inner(...) [&ref] | provenance | MaD:9 |
| main.rs:115:31:115:34 | pin1 [Pin, &ref] | main.rs:115:15:115:35 | ...::into_inner(...) [&ref] | provenance | MaD:8 |
| main.rs:116:15:116:18 | pin2 [&ref] | main.rs:116:14:116:18 | * ... | provenance | |
| main.rs:117:15:117:18 | pin3 [&ref] | main.rs:117:14:117:18 | * ... | provenance | |
| main.rs:122:13:122:18 | mut ms [MyStruct] | main.rs:123:34:123:35 | ms [MyStruct] | provenance | |
@@ -101,20 +100,20 @@ edges
| main.rs:122:38:122:47 | source(...) | main.rs:122:22:122:49 | MyStruct {...} [MyStruct] | provenance | |
| main.rs:123:13:123:20 | mut pin1 [MyStruct] | main.rs:129:30:129:33 | pin1 [MyStruct] | provenance | |
| main.rs:123:24:123:36 | ...::new(...) [MyStruct] | main.rs:123:13:123:20 | mut pin1 [MyStruct] | provenance | |
| main.rs:123:33:123:35 | &ms [&ref, MyStruct] | main.rs:123:24:123:36 | ...::new(...) [MyStruct] | provenance | MaD:10 |
| main.rs:123:33:123:35 | &ms [&ref, MyStruct] | main.rs:123:24:123:36 | ...::new(...) [MyStruct] | provenance | MaD:11 |
| main.rs:123:34:123:35 | ms [MyStruct] | main.rs:123:33:123:35 | &ms [&ref, MyStruct] | provenance | |
| main.rs:127:14:127:15 | ms [MyStruct] | main.rs:127:14:127:19 | ms.val | provenance | |
| main.rs:129:14:129:34 | ...::into_inner(...) [MyStruct] | main.rs:129:14:129:38 | ... .val | provenance | |
| main.rs:129:30:129:33 | pin1 [MyStruct] | main.rs:129:14:129:34 | ...::into_inner(...) [MyStruct] | provenance | MaD:8 |
| main.rs:129:30:129:33 | pin1 [MyStruct] | main.rs:129:14:129:34 | ...::into_inner(...) [MyStruct] | provenance | MaD:9 |
| main.rs:136:13:136:18 | mut ms [MyStruct] | main.rs:137:44:137:45 | ms [MyStruct] | provenance | |
| main.rs:136:22:136:49 | MyStruct {...} [MyStruct] | main.rs:136:13:136:18 | mut ms [MyStruct] | provenance | |
| main.rs:136:38:136:47 | source(...) | main.rs:136:22:136:49 | MyStruct {...} [MyStruct] | provenance | |
| main.rs:137:13:137:20 | mut pin5 [MyStruct] | main.rs:139:40:139:43 | pin5 [MyStruct] | provenance | |
| main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | main.rs:137:13:137:20 | mut pin5 [MyStruct] | provenance | |
| main.rs:137:43:137:45 | &ms [&ref, MyStruct] | main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | provenance | MaD:13 |
| main.rs:137:43:137:45 | &ms [&ref, MyStruct] | main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | provenance | MaD:14 |
| main.rs:137:44:137:45 | ms [MyStruct] | main.rs:137:43:137:45 | &ms [&ref, MyStruct] | provenance | |
| main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | main.rs:139:14:139:48 | ... .val | provenance | |
| main.rs:139:40:139:43 | pin5 [MyStruct] | main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | provenance | MaD:9 |
| main.rs:139:40:139:43 | pin5 [MyStruct] | main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | provenance | MaD:10 |
nodes
| main.rs:12:9:12:9 | a [Some] | semmle.label | a [Some] |
| main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] |
@@ -152,7 +151,6 @@ nodes
| main.rs:51:26:51:26 | n | semmle.label | n |
| main.rs:51:38:51:38 | n | semmle.label | n |
| main.rs:53:13:53:13 | u [Wrapper] | semmle.label | u [Wrapper] |
| main.rs:53:17:53:17 | w [Wrapper] | semmle.label | w [Wrapper] |
| main.rs:53:17:53:25 | w.clone() [Wrapper] | semmle.label | w.clone() [Wrapper] |
| main.rs:54:15:54:15 | u [Wrapper] | semmle.label | u [Wrapper] |
| main.rs:55:13:55:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] |

View File

@@ -1,29 +1,29 @@
multipleCallTargets
| test.rs:55:7:55:26 | ... .as_str() |
| test.rs:56:7:56:21 | ... .as_str() |
| test.rs:72:7:72:26 | ... .as_str() |
| test.rs:73:7:73:36 | ... .as_str() |
| test.rs:74:7:74:34 | ... .as_str() |
| test.rs:75:7:75:27 | ... .as_str() |
| test.rs:258:7:258:36 | ... .as_str() |
| test.rs:260:7:260:33 | ... .as_str() |
| test.rs:261:7:261:36 | ... .as_str() |
| test.rs:262:7:262:26 | ... .as_str() |
| test.rs:266:7:266:28 | ... .as_str() |
| test.rs:267:7:267:37 | ... .as_str() |
| test.rs:268:7:268:36 | ... .as_str() |
| test.rs:271:7:271:32 | ... .as_str() |
| test.rs:281:7:281:34 | ... .as_str() |
| test.rs:284:7:284:36 | ... .as_str() |
| test.rs:288:7:288:39 | ... .as_str() |
| test.rs:295:7:295:53 | ... .as_str() |
| test.rs:296:7:296:45 | ... .as_str() |
| test.rs:298:7:298:39 | ... .as_str() |
| test.rs:299:7:299:34 | ... .as_str() |
| test.rs:300:7:300:42 | ... .as_str() |
| test.rs:302:7:302:48 | ... .as_str() |
| test.rs:303:7:303:35 | ... .as_str() |
| test.rs:304:7:304:35 | ... .as_str() |
| test.rs:313:8:313:19 | num.as_str() |
| test.rs:324:8:324:19 | num.as_str() |
| test.rs:343:7:343:39 | ... .as_str() |
| test.rs:56:7:56:26 | ... .as_str() |
| test.rs:57:7:57:21 | ... .as_str() |
| test.rs:73:7:73:26 | ... .as_str() |
| test.rs:74:7:74:36 | ... .as_str() |
| test.rs:75:7:75:34 | ... .as_str() |
| test.rs:76:7:76:27 | ... .as_str() |
| test.rs:262:7:262:36 | ... .as_str() |
| test.rs:264:7:264:33 | ... .as_str() |
| test.rs:265:7:265:36 | ... .as_str() |
| test.rs:266:7:266:26 | ... .as_str() |
| test.rs:270:7:270:28 | ... .as_str() |
| test.rs:271:7:271:37 | ... .as_str() |
| test.rs:272:7:272:36 | ... .as_str() |
| test.rs:275:7:275:32 | ... .as_str() |
| test.rs:285:7:285:34 | ... .as_str() |
| test.rs:288:7:288:36 | ... .as_str() |
| test.rs:292:7:292:39 | ... .as_str() |
| test.rs:299:7:299:53 | ... .as_str() |
| test.rs:300:7:300:45 | ... .as_str() |
| test.rs:302:7:302:39 | ... .as_str() |
| test.rs:303:7:303:34 | ... .as_str() |
| test.rs:304:7:304:42 | ... .as_str() |
| test.rs:306:7:306:48 | ... .as_str() |
| test.rs:307:7:307:35 | ... .as_str() |
| test.rs:308:7:308:35 | ... .as_str() |
| test.rs:317:8:317:19 | num.as_str() |
| test.rs:328:8:328:19 | num.as_str() |
| test.rs:347:7:347:39 | ... .as_str() |

View File

@@ -23,7 +23,7 @@ impl MyStruct {
fn get_password() -> String { get_string() }
fn test_passwords(
password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str,
password: &str, pass_word: &str, passwd: &str, my_password: &str, password_str: &str, password_confirmation: &str,
pass_phrase: &str, passphrase: &str, passPhrase: &str, backup_code: &str,
auth_key: &str, authkey: &str, authKey: &str, authentication_key: &str, authenticationkey: &str, authenticationKey: &str, oauth: &str,
one_time_code: &str,
@@ -37,6 +37,7 @@ fn test_passwords(
sink(passwd); // $ sensitive=password
sink(my_password); // $ sensitive=password
sink(password_str); // $ sensitive=password
sink(password_confirmation); // $ sensitive=password
sink(pass_phrase); // $ sensitive=password
sink(passphrase); // $ sensitive=password
sink(passPhrase); // $ sensitive=password
@@ -48,12 +49,12 @@ fn test_passwords(
sink(authentication_key); // $ sensitive=password
sink(authenticationkey); // $ sensitive=password
sink(authenticationKey); // $ sensitive=password
sink(oauth); // $ MISSING: sensitive=password
sink(oauth); // $ sensitive=password
sink(one_time_code); // $ MISSING: sensitive=password
sink(ms); // $ MISSING: sensitive=password
sink(ms.password.as_str()); // $ sensitive=password
sink(ms.mfa.as_str()); // $ MISSING: sensitive=password
sink(ms.mfa.as_str()); // $ sensitive=password
sink(get_password()); // $ sensitive=password
let password2 = get_string();
@@ -67,10 +68,10 @@ fn test_passwords(
sink(harmless);
sink(encrypted_password);
sink(password_hash);
sink(passwordFile); // $ SPURIOUS: sensitive=password
sink(passwordFile);
sink(ms.harmless.as_str());
sink(ms.password_file_path.as_str()); // $ SPURIOUS: sensitive=password
sink(ms.password_file_path.as_str());
sink(ms.password_enabled.as_str()); // $ SPURIOUS: sensitive=password
sink(ms.numfailed.as_str());
@@ -127,11 +128,11 @@ fn test_credentials(
sink(hashkey);
sink(hash_key);
sink(sessionkeypath); // $ SPURIOUS: sensitive=id
sink(account_key_path); // $ SPURIOUS: sensitive=id
sink(sessionkeypath);
sink(account_key_path);
sink(ms.get_certificate_url()); // $ SPURIOUS: sensitive=certificate
sink(ms.get_certificate_file()); // $ SPURIOUS: sensitive=certificate
sink(ms.get_certificate_url());
sink(ms.get_certificate_file());
sink(get_public_key());
sink(get_next_token());
@@ -160,16 +161,19 @@ impl DeviceInfo {
fn test_device_info(&self, other: &DeviceInfo) {
// private device info
sink(&self.api_key); // $ MISSING: sensitive=id
sink(&other.api_key); // $ MISSING: sensitive=id
sink(&self.deviceApiToken); // $ MISSING: sensitive=id
sink(&self.finger_print); // $ MISSING: sensitive=id
sink(&self.ip_address); // $ MISSING: sensitive=id
sink(self.macaddr12); // $ MISSING: sensitive=id
sink(&self.mac_addr); // $ MISSING: sensitive=id
sink(self.mac_addr.values); // $ MISSING: sensitive=id
sink(self.mac_addr.values[0]); // $ MISSING: sensitive=id
sink(&self.networkMacAddress); // $ MISSING: sensitive=id
sink(&self.api_key); // $ sensitive=password
sink(&other.api_key); // $ sensitive=password
sink(&self.deviceApiToken); // $ sensitive=password
sink(self.macaddr12); // $ sensitive=private
sink(&self.mac_addr); // $ sensitive=private
sink(self.mac_addr.values); // $ sensitive=private
sink(self.mac_addr.values[0]); // $ sensitive=private
sink(&self.networkMacAddress); // $ sensitive=private
// dubious (may or may not be private device info, depending on context)
sink(&self.finger_print);
sink(&self.ip_address);
// not private device info
@@ -267,26 +271,26 @@ fn test_private_info(
sink(info.emergency_contact.as_str()); // $ sensitive=private
sink(info.name_of_employer.as_str()); // $ sensitive=private
sink(&info.gender); // $ MISSING: sensitive=private
sink(info.genderString.as_str()); // $ MISSING: sensitive=private
sink(&info.gender); // $ sensitive=private
sink(info.genderString.as_str()); // $ sensitive=private
let sex = "Male";
let gender = Gender::Female;
let a = Gender::Female;
sink(sex); // $ MISSING: sensitive=private
sink(gender); // $ MISSING: sensitive=private
sink(sex); // $ sensitive=private
sink(gender); // $ sensitive=private
sink(a); // $ MISSING: sensitive=private
sink(info.patient_id); // $ MISSING: sensitive=private
sink(info.linkedPatientId); // $ MISSING: sensitive=private
sink(info.patient_record.as_str()); // $ MISSING: sensitive=private
sink(info.patient_record.trim()); // $ MISSING: sensitive=private
sink(info.patient_id); // $ sensitive=private
sink(info.linkedPatientId); // $ sensitive=private
sink(info.patient_record.as_str()); // $ sensitive=private
sink(info.patient_record.trim()); // $ sensitive=private
sink(&info.medical_notes); // $ sensitive=private
sink(info.medical_notes[0].as_str()); // $ sensitive=private
for n in info.medical_notes.iter() {
sink(n.as_str()); // $ MISSING: sensitive=private
}
sink(info.confidentialMessage.as_str()); // $ MISSING: sensitive=private
sink(info.confidentialMessage.to_lowercase()); // $ MISSING: sensitive=private
sink(info.confidentialMessage.as_str()); // $ sensitive=secret
sink(info.confidentialMessage.to_lowercase()); // $ sensitive=secret
sink(info.latitude); // $ sensitive=private
let x = info.longitude.unwrap();
@@ -296,12 +300,12 @@ fn test_private_info(
sink(info.financials.credit_card_no.as_str()); // $ sensitive=private
sink(info.financials.credit_rating); // $ sensitive=private
sink(info.financials.user_ccn.as_str()); // $ sensitive=private
sink(info.financials.cvv.as_str()); // $ MISSING: sensitive=private
sink(info.financials.beneficiary.as_str()); // $ MISSING: sensitive=private
sink(info.financials.routing_number); // $ MISSING: sensitive=private
sink(info.financials.routingNumberText.as_str()); // $ MISSING: sensitive=private
sink(info.financials.iban.as_str()); // $ MISSING: sensitive=private
sink(info.financials.iBAN.as_str()); // $ MISSING: sensitive=private
sink(info.financials.cvv.as_str()); // $ sensitive=private
sink(info.financials.beneficiary.as_str()); // $ sensitive=private
sink(info.financials.routing_number); // $ sensitive=private
sink(info.financials.routingNumberText.as_str()); // $ sensitive=private
sink(info.financials.iban.as_str()); // $ sensitive=private
sink(info.financials.iBAN.as_str()); // $ sensitive=private
sink(ContactDetails::HomePhoneNumber("123".to_string())); // $ sensitive=private
sink(ContactDetails::MobileNumber("123".to_string())); // $ sensitive=private
@@ -343,8 +347,8 @@ fn test_private_info(
sink(info.financials.harmless.as_str());
sink(info.financials.num_accounts); // $ SPURIOUS: sensitive=id
sink(info.financials.total_accounts); // $ SPURIOUS: sensitive=id
sink(info.financials.accounting); // $ SPURIOUS: sensitive=id
sink(info.financials.unaccounted); // $ SPURIOUS: sensitive=id
sink(info.financials.accounting);
sink(info.financials.unaccounted);
sink(info.financials.multiband);
sink(ContactDetails::FavouriteColor("blue".to_string()));
@@ -362,5 +366,5 @@ impl MyArray {
fn test_iterator() {
let iter = std::iter::repeat(1).take(10);
sink(MyArray::from_trusted_iterator(iter)); // $ SPURIOUS: sensitive=secret
sink(MyArray::from_trusted_iterator(iter));
}

View File

@@ -1,8 +1,8 @@
multipleCallTargets
| dereference.rs:61:15:61:24 | e1.deref() |
| main.rs:2213:13:2213:31 | ...::from(...) |
| main.rs:2214:13:2214:31 | ...::from(...) |
| main.rs:2215:13:2215:31 | ...::from(...) |
| main.rs:2221:13:2221:31 | ...::from(...) |
| main.rs:2222:13:2222:31 | ...::from(...) |
| main.rs:2223:13:2223:31 | ...::from(...) |
| main.rs:2278:13:2278:31 | ...::from(...) |
| main.rs:2279:13:2279:31 | ...::from(...) |
| main.rs:2280:13:2280:31 | ...::from(...) |
| main.rs:2286:13:2286:31 | ...::from(...) |
| main.rs:2287:13:2287:31 | ...::from(...) |
| main.rs:2288:13:2288:31 | ...::from(...) |

View File

@@ -0,0 +1,108 @@
// Test cases for type inference and method resolution with `dyn` types
use std::fmt::Debug;
trait MyTrait1 {
// MyTrait1::m
fn m(&self) -> String;
}
trait GenericGet<A> {
// GenericGet::get
fn get(&self) -> A;
}
trait AssocTrait<GP> {
type AP;
// AssocTrait::get
fn get(&self) -> (GP, Self::AP);
}
#[derive(Clone, Debug)]
struct MyStruct {
value: i32,
}
impl MyTrait1 for MyStruct {
// MyStruct1::m
fn m(&self) -> String {
format!("MyTrait1: {}", self.value) // $ fieldof=MyStruct
}
}
#[derive(Clone, Debug)]
struct GenStruct<A: Clone + Debug> {
value: A,
}
impl<A: Clone + Debug> GenericGet<A> for GenStruct<A> {
// GenStruct<A>::get
fn get(&self) -> A {
self.value.clone() // $ fieldof=GenStruct target=clone
}
}
impl<GGP> AssocTrait<GGP> for GenStruct<GGP>
where
GGP: Clone + Debug,
{
type AP = bool;
// GenStruct<GGP>::get
fn get(&self) -> (GGP, bool) {
(self.value.clone(), true) // $ fieldof=GenStruct target=clone
}
}
fn get_a<A, G: GenericGet<A> + ?Sized>(a: &G) -> A {
a.get() // $ target=GenericGet::get
}
fn get_box_trait<A: Clone + Debug + 'static>(a: A) -> Box<dyn GenericGet<A>> {
Box::new(GenStruct { value: a }) // $ target=new
}
fn test_basic_dyn_trait(obj: &dyn MyTrait1) {
let _result = (*obj).m(); // $ target=deref target=MyTrait1::m type=_result:String
}
fn test_generic_dyn_trait(obj: &dyn GenericGet<String>) {
let _result1 = (*obj).get(); // $ target=deref target=GenericGet::get type=_result1:String
let _result2 = get_a(obj); // $ target=get_a type=_result2:String
}
fn test_poly_dyn_trait() {
let obj = get_box_trait(true); // $ target=get_box_trait
let _result = (*obj).get(); // $ target=deref target=GenericGet::get type=_result:bool
}
fn assoc_dyn_get<A, B>(a: &dyn AssocTrait<A, AP = B>) -> (A, B) {
a.get() // $ target=AssocTrait::get
}
fn assoc_get<A, B, T: AssocTrait<A, AP = B> + ?Sized>(a: &T) -> (A, B) {
a.get() // $ target=AssocTrait::get
}
fn test_assoc_type(obj: &dyn AssocTrait<i64, AP = bool>) {
let (
_gp, // $ type=_gp:i64
_ap, // $ type=_ap:bool
) = (*obj).get(); // $ target=deref target=AssocTrait::get
let (
_gp, // $ type=_gp:i64
_ap, // $ type=_ap:bool
) = assoc_dyn_get(obj); // $ target=assoc_dyn_get
let (
_gp, // $ type=_gp:i64
_ap, // $ type=_ap:bool
) = assoc_get(obj); // $ target=assoc_get
}
pub fn test() {
test_basic_dyn_trait(&MyStruct { value: 42 }); // $ target=test_basic_dyn_trait
test_generic_dyn_trait(&GenStruct {
value: "".to_string(),
}); // $ target=test_generic_dyn_trait
test_poly_dyn_trait(); // $ target=test_poly_dyn_trait
test_assoc_type(&GenStruct { value: 100 }); // $ target=test_assoc_type
}

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