mirror of
https://github.com/github/codeql.git
synced 2026-05-25 08:37:20 +02:00
Compare commits
86 Commits
alexet/glo
...
move-cors-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3d608fa33 | ||
|
|
6c751ce934 | ||
|
|
4dac80a998 | ||
|
|
021aa13ee2 | ||
|
|
791a7e242e | ||
|
|
2baca58b27 | ||
|
|
fd4233e30e | ||
|
|
84ffbbec33 | ||
|
|
95743d7109 | ||
|
|
92daa7d42c | ||
|
|
358617f533 | ||
|
|
6c00ceaec9 | ||
|
|
ac52a1b123 | ||
|
|
9d72fab287 | ||
|
|
92bce4e432 | ||
|
|
9761580b7e | ||
|
|
37b508bf43 | ||
|
|
13d9d8ad3f | ||
|
|
4b947db0f8 | ||
|
|
2951ae9c7c | ||
|
|
b2ee625268 | ||
|
|
478f39a967 | ||
|
|
6511e21f81 | ||
|
|
2192ed04be | ||
|
|
4140579dd6 | ||
|
|
7f659804e4 | ||
|
|
cfe25593ee | ||
|
|
466bf85a67 | ||
|
|
1b2f160b55 | ||
|
|
b1ee795225 | ||
|
|
621b4833f3 | ||
|
|
39f602c032 | ||
|
|
bb56b0d45b | ||
|
|
9a0c5877ea | ||
|
|
97cf15affc | ||
|
|
a20fed8ae5 | ||
|
|
a8cc14493f | ||
|
|
82387461ee | ||
|
|
b3dc6cba78 | ||
|
|
5da7ae877b | ||
|
|
199f2473e5 | ||
|
|
5f8c457295 | ||
|
|
cbe5561eb6 | ||
|
|
83fe9e0d51 | ||
|
|
31a73d466b | ||
|
|
56ae8684e1 | ||
|
|
fcc3800756 | ||
|
|
091163bf8e | ||
|
|
78c40e209b | ||
|
|
574bb871e0 | ||
|
|
329fd803e2 | ||
|
|
9d736723fb | ||
|
|
50785f7f21 | ||
|
|
f5605c94c5 | ||
|
|
12942667bf | ||
|
|
605c8e201e | ||
|
|
604af65b02 | ||
|
|
709c111522 | ||
|
|
d1da041fcf | ||
|
|
8432f6e42e | ||
|
|
965f1fc547 | ||
|
|
f148f434e1 | ||
|
|
ad391df03f | ||
|
|
68f0dfe046 | ||
|
|
4f6b698ca3 | ||
|
|
8ccb2ed059 | ||
|
|
6d33a7ec70 | ||
|
|
f2dd96ecf4 | ||
|
|
57f1d07b2b | ||
|
|
680e31dc48 | ||
|
|
0f5be2d096 | ||
|
|
909f57261c | ||
|
|
7a7db0efe8 | ||
|
|
df5f76872f | ||
|
|
918700ff6f | ||
|
|
da0742f3ec | ||
|
|
30c6082b5d | ||
|
|
e121579a85 | ||
|
|
9f59a3501c | ||
|
|
4778ef616a | ||
|
|
8f6f9f4359 | ||
|
|
123458fd21 | ||
|
|
a6b4a18d51 | ||
|
|
8f95e26ed6 | ||
|
|
99e62d66e5 | ||
|
|
cd6975f7b7 |
7
.github/copilot-instructions.md
vendored
7
.github/copilot-instructions.md
vendored
@@ -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`
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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"]
|
||||
@@ -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
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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``"
|
||||
|
||||
@@ -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
BIN
java/kotlin-extractor/deps/kotlin-compiler-2.2.20-Beta1.jar
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.20-Beta1.jar
(Stored with Git LFS)
Normal file
BIN
java/kotlin-extractor/deps/kotlin-compiler-embeddable-2.2.20-Beta1.jar
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
java/kotlin-extractor/deps/kotlin-stdlib-2.2.20-Beta1.jar
(Stored with Git LFS)
Normal file
BIN
java/kotlin-extractor/deps/kotlin-stdlib-2.2.20-Beta1.jar
(Stored with Git LFS)
Normal file
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
4
java/ql/lib/change-notes/2025-07-23-kotlin-2.2.20.md
Normal file
4
java/ql/lib/change-notes/2025-07-23-kotlin-2.2.20.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Kotlin versions up to 2.2.2\ *x* are now supported.
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Provides predicates for reasoning about runtime call targets through virtual
|
||||
* dispatch.
|
||||
*/
|
||||
overlay[local?]
|
||||
module;
|
||||
|
||||
import java
|
||||
|
||||
@@ -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 $.
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/java-queries
|
||||
pack: codeql/java-all
|
||||
extensible: extractorInformationSkipKey
|
||||
data: []
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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]"]
|
||||
|
||||
6
javascript/ql/lib/ext/cors.model.yml
Normal file
6
javascript/ql/lib/ext/cors.model.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/javascript-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ["cors", "Argument[0].Member[origin]", "cors-misconfiguration"]
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>;
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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.
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
@@ -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") }
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
./experimental/Security/CWE-942/CorsPermissiveConfiguration.ql
|
||||
@@ -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 |
|
||||
@@ -0,0 +1,2 @@
|
||||
query: Security/CWE-942/CorsPermissiveConfiguration.ql
|
||||
postprocess: utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -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
|
||||
});
|
||||
});
|
||||
@@ -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));
|
||||
});
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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?"
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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])
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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? |
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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.
|
||||
2
rust/ql/.generated.list
generated
2
rust/ql/.generated.list
generated
@@ -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
2
rust/ql/.gitattributes
generated
vendored
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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() =
|
||||
["\"..\"", "\"../\"", "\"..\\\""]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Type inference now supports trait objects, i.e., `dyn Trait` types.
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,6 +79,8 @@ module TaintedPathConfig implements DataFlow::StateConfigSig {
|
||||
stateFrom instanceof NotNormalized and
|
||||
stateTo instanceof NormalizedUnchecked
|
||||
}
|
||||
|
||||
predicate observeDiffInformedIncrementalMode() { any() }
|
||||
}
|
||||
|
||||
module TaintedPathFlow = TaintTracking::GlobalWithState<TaintedPathConfig>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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] |
|
||||
|
||||
@@ -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() |
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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(...) |
|
||||
|
||||
108
rust/ql/test/library-tests/type-inference/dyn_type.rs
Normal file
108
rust/ql/test/library-tests/type-inference/dyn_type.rs
Normal 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
Reference in New Issue
Block a user