Skip to content

Commit 1d2ac33

Browse files
committed
Rust: Model async-std::fs.
1 parent 49b4adc commit 1d2ac33

File tree

5 files changed

+85
-22
lines changed

5 files changed

+85
-22
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/rust-all
4+
extensible: sourceModel
5+
data:
6+
- ["async_std::fs::read::read", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "file", "manual"]
7+
- ["async_std::fs::read_to_string::read_to_string", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "file", "manual"]
8+
- ["async_std::fs::read_link::read_link", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "file", "manual"]
9+
- ["<async_std::fs::dir_entry::DirEntry>::path", "ReturnValue", "file", "manual"]
10+
- ["<async_std::fs::dir_entry::DirEntry>::file_name", "ReturnValue", "file", "manual"]
11+
- ["<async_std::fs::file::File>::open", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "file", "manual"]
12+
- addsTo:
13+
pack: codeql/rust-all
14+
extensible: sinkModel
15+
data:
16+
- ["async_std::fs::copy::copy", "Argument[0]", "path-injection", "manual"]
17+
- ["async_std::fs::copy::copy", "Argument[1]", "path-injection", "manual"]
18+
- ["async_std::fs::create_dir::create_dir", "Argument[0]", "path-injection", "manual"]
19+
- ["async_std::fs::create_dir_all::create_dir_all", "Argument[0]", "path-injection", "manual"]
20+
- ["async_std::fs::hard_link::hard_link", "Argument[0]", "path-injection", "manual"]
21+
- ["async_std::fs::hard_link::hard_link", "Argument[1]", "path-injection", "manual"]
22+
- ["async_std::fs::metadata::metadata", "Argument[0]", "path-injection", "manual"]
23+
- ["async_std::fs::read::read", "Argument[0]", "path-injection", "manual"]
24+
- ["async_std::fs::read_dir::read_dir", "Argument[0]", "path-injection", "manual"]
25+
- ["async_std::fs::read_link::read_link", "Argument[0]", "path-injection", "manual"]
26+
- ["async_std::fs::read_to_string::read_to_string", "Argument[0]", "path-injection", "manual"]
27+
- ["async_std::fs::remove_dir::remove_dir", "Argument[0]", "path-injection", "manual"]
28+
- ["async_std::fs::remove_dir_all::remove_dir_all", "Argument[0]", "path-injection", "manual"]
29+
- ["async_std::fs::remove_file::remove_file", "Argument[0]", "path-injection", "manual"]
30+
- ["async_std::fs::rename::rename", "Argument[0]", "path-injection", "manual"]
31+
- ["async_std::fs::rename::rename", "Argument[1]", "path-injection", "manual"]
32+
- ["async_std::fs::set_permissions::set_permissions", "Argument[0]", "path-injection", "manual"]
33+
- ["async_std::fs::symlink_metadata::symlink_metadata", "Argument[0]", "path-injection", "manual"]
34+
- ["async_std::fs::write::write", "Argument[0]", "path-injection", "manual"]
35+
- ["<async_std::fs::dir_builder::DirBuilder>::create", "Argument[0]", "path-injection", "manual"]
36+
- ["<async_std::fs::file::File>::create", "Argument[0]", "path-injection", "manual"]
37+
- ["<async_std::fs::file::File>::open", "Argument[0]", "path-injection", "manual"]
38+
- addsTo:
39+
pack: codeql/rust-all
40+
extensible: summaryModel
41+
data:
42+
- ["async_std::fs::canonicalize::canonicalize", "Argument[0]", "ReturnValue.Future.Field[core::result::Result::Ok(0)]", "taint", "manual"]

rust/ql/test/library-tests/dataflow/sources/TaintSources.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
| test.rs:637:21:637:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
7777
| test.rs:638:21:638:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
7878
| test.rs:646:21:646:41 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
79+
| test.rs:660:20:660:44 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
7980
| test.rs:688:26:688:53 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). |
8081
| test.rs:707:26:707:61 | ...::connect_timeout | Flow source 'RemoteSource' of type remote (DEFAULT). |
8182
| test.rs:759:28:759:57 | ...::connect | Flow source 'RemoteSource' of type remote (DEFAULT). |

rust/ql/test/library-tests/dataflow/sources/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ use async_std::io::ReadExt;
657657
async fn test_async_std_file() -> std::io::Result<()> {
658658
// --- file ---
659659

660-
let mut file = async_std::fs::File::open("file.txt").await?; // $ MISSING: Alert[rust/summary/taint-sources]
660+
let mut file = async_std::fs::File::open("file.txt").await?; // $ Alert[rust/summary/taint-sources]
661661

662662
{
663663
let mut buffer = [0u8; 100];
Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,40 @@
11
#select
22
| src/main.rs:11:5:11:22 | ...::read_to_string | src/main.rs:7:11:7:19 | file_name | src/main.rs:11:5:11:22 | ...::read_to_string | This path depends on a $@. | src/main.rs:7:11:7:19 | file_name | user-provided value |
33
| src/main.rs:104:13:104:31 | ...::open | src/main.rs:103:17:103:30 | ...::args | src/main.rs:104:13:104:31 | ...::open | This path depends on a $@. | src/main.rs:103:17:103:30 | ...::args | user-provided value |
4+
| src/main.rs:113:13:113:37 | ...::open | src/main.rs:103:17:103:30 | ...::args | src/main.rs:113:13:113:37 | ...::open | This path depends on a $@. | src/main.rs:103:17:103:30 | ...::args | user-provided value |
45
edges
56
| src/main.rs:7:11:7:19 | file_name | src/main.rs:9:35:9:43 | file_name | provenance | |
67
| src/main.rs:9:9:9:17 | file_path | src/main.rs:11:24:11:32 | file_path | provenance | |
78
| src/main.rs:9:21:9:44 | ...::from(...) | src/main.rs:9:9:9:17 | file_path | provenance | |
8-
| src/main.rs:9:35:9:43 | file_name | src/main.rs:9:21:9:44 | ...::from(...) | provenance | MaD:7 |
9-
| src/main.rs:9:35:9:43 | file_name | src/main.rs:9:21:9:44 | ...::from(...) | provenance | MaD:7 |
10-
| src/main.rs:11:24:11:32 | file_path | src/main.rs:11:5:11:22 | ...::read_to_string | provenance | MaD:2 Sink:MaD:2 |
9+
| src/main.rs:9:35:9:43 | file_name | src/main.rs:9:21:9:44 | ...::from(...) | provenance | MaD:9 |
10+
| src/main.rs:9:35:9:43 | file_name | src/main.rs:9:21:9:44 | ...::from(...) | provenance | MaD:9 |
11+
| src/main.rs:11:24:11:32 | file_path | src/main.rs:11:5:11:22 | ...::read_to_string | provenance | MaD:3 Sink:MaD:3 |
1112
| src/main.rs:103:9:103:13 | path1 | src/main.rs:104:33:104:37 | path1 | provenance | |
12-
| src/main.rs:103:17:103:30 | ...::args | src/main.rs:103:17:103:32 | ...::args(...) [element] | provenance | Src:MaD:3 |
13-
| src/main.rs:103:17:103:32 | ...::args(...) [element] | src/main.rs:103:17:103:39 | ... .nth(...) [Some] | provenance | MaD:5 |
14-
| src/main.rs:103:17:103:39 | ... .nth(...) [Some] | src/main.rs:103:17:103:48 | ... .unwrap() | provenance | MaD:6 |
13+
| src/main.rs:103:9:103:13 | path1 | src/main.rs:112:45:112:49 | path1 | provenance | |
14+
| src/main.rs:103:17:103:30 | ...::args | src/main.rs:103:17:103:32 | ...::args(...) [element] | provenance | Src:MaD:4 |
15+
| src/main.rs:103:17:103:32 | ...::args(...) [element] | src/main.rs:103:17:103:39 | ... .nth(...) [Some] | provenance | MaD:6 |
16+
| src/main.rs:103:17:103:39 | ... .nth(...) [Some] | src/main.rs:103:17:103:48 | ... .unwrap() | provenance | MaD:7 |
1517
| src/main.rs:103:17:103:48 | ... .unwrap() | src/main.rs:103:9:103:13 | path1 | provenance | |
16-
| src/main.rs:104:33:104:37 | path1 | src/main.rs:104:33:104:45 | path1.clone() | provenance | MaD:4 |
17-
| src/main.rs:104:33:104:45 | path1.clone() | src/main.rs:104:13:104:31 | ...::open | provenance | MaD:1 Sink:MaD:1 |
18+
| src/main.rs:104:33:104:37 | path1 | src/main.rs:104:33:104:45 | path1.clone() | provenance | MaD:5 |
19+
| src/main.rs:104:33:104:45 | path1.clone() | src/main.rs:104:13:104:31 | ...::open | provenance | MaD:2 Sink:MaD:2 |
20+
| src/main.rs:112:9:112:13 | path4 | src/main.rs:113:39:113:43 | path4 | provenance | |
21+
| src/main.rs:112:17:112:58 | ...::canonicalize(...) [future, Ok] | src/main.rs:112:17:112:64 | await ... [Ok] | provenance | |
22+
| src/main.rs:112:17:112:64 | await ... [Ok] | src/main.rs:112:17:112:73 | ... .unwrap() | provenance | MaD:8 |
23+
| src/main.rs:112:17:112:73 | ... .unwrap() | src/main.rs:112:9:112:13 | path4 | provenance | |
24+
| src/main.rs:112:45:112:49 | path1 | src/main.rs:112:45:112:57 | path1.clone() | provenance | MaD:5 |
25+
| src/main.rs:112:45:112:57 | path1.clone() | src/main.rs:112:17:112:58 | ...::canonicalize(...) [future, Ok] | provenance | MaD:10 |
26+
| src/main.rs:113:39:113:43 | path4 | src/main.rs:113:13:113:37 | ...::open | provenance | MaD:1 Sink:MaD:1 |
1827
models
19-
| 1 | Sink: <std::fs::File>::open; Argument[0]; path-injection |
20-
| 2 | Sink: std::fs::read_to_string; Argument[0]; path-injection |
21-
| 3 | Source: std::env::args; ReturnValue.Element; commandargs |
22-
| 4 | Summary: <_ as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
23-
| 5 | Summary: <_ as core::iter::traits::iterator::Iterator>::nth; Argument[self].Element; ReturnValue.Field[core::option::Option::Some(0)]; value |
24-
| 6 | Summary: <core::option::Option>::unwrap; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
25-
| 7 | Summary: <std::path::PathBuf as core::convert::From>::from; Argument[0]; ReturnValue; taint |
28+
| 1 | Sink: <async_std::fs::file::File>::open; Argument[0]; path-injection |
29+
| 2 | Sink: <std::fs::File>::open; Argument[0]; path-injection |
30+
| 3 | Sink: std::fs::read_to_string; Argument[0]; path-injection |
31+
| 4 | Source: std::env::args; ReturnValue.Element; commandargs |
32+
| 5 | Summary: <_ as core::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
33+
| 6 | Summary: <_ as core::iter::traits::iterator::Iterator>::nth; Argument[self].Element; ReturnValue.Field[core::option::Option::Some(0)]; value |
34+
| 7 | Summary: <core::option::Option>::unwrap; Argument[self].Field[core::option::Option::Some(0)]; ReturnValue; value |
35+
| 8 | Summary: <core::result::Result>::unwrap; Argument[self].Field[core::result::Result::Ok(0)]; ReturnValue; value |
36+
| 9 | Summary: <std::path::PathBuf as core::convert::From>::from; Argument[0]; ReturnValue; taint |
37+
| 10 | Summary: async_std::fs::canonicalize::canonicalize; Argument[0]; ReturnValue.Future.Field[core::result::Result::Ok(0)]; taint |
2638
nodes
2739
| src/main.rs:7:11:7:19 | file_name | semmle.label | file_name |
2840
| src/main.rs:9:9:9:17 | file_path | semmle.label | file_path |
@@ -38,4 +50,12 @@ nodes
3850
| src/main.rs:104:13:104:31 | ...::open | semmle.label | ...::open |
3951
| src/main.rs:104:33:104:37 | path1 | semmle.label | path1 |
4052
| src/main.rs:104:33:104:45 | path1.clone() | semmle.label | path1.clone() |
53+
| src/main.rs:112:9:112:13 | path4 | semmle.label | path4 |
54+
| src/main.rs:112:17:112:58 | ...::canonicalize(...) [future, Ok] | semmle.label | ...::canonicalize(...) [future, Ok] |
55+
| src/main.rs:112:17:112:64 | await ... [Ok] | semmle.label | await ... [Ok] |
56+
| src/main.rs:112:17:112:73 | ... .unwrap() | semmle.label | ... .unwrap() |
57+
| src/main.rs:112:45:112:49 | path1 | semmle.label | path1 |
58+
| src/main.rs:112:45:112:57 | path1.clone() | semmle.label | path1.clone() |
59+
| src/main.rs:113:13:113:37 | ...::open | semmle.label | ...::open |
60+
| src/main.rs:113:39:113:43 | path4 | semmle.label | path4 |
4161
subpaths

rust/ql/test/query-tests/security/CWE-022/src/main.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ async fn more_simple_cases() {
110110
let _ = tokio::fs::File::open(path3); // $ MISSING: path-injection-sink Alert[rust/path-injection]=arg1
111111

112112
let path4 = async_std::fs::canonicalize(path1.clone()).await.unwrap();
113-
let _ = async_std::fs::File::open(path4); // $ MISSING: path-injection-sink Alert[rust/path-injection]=arg1
113+
let _ = async_std::fs::File::open(path4); // $ path-injection-sink Alert[rust/path-injection]=arg1
114114

115115
let path5 = std::path::Path::new(&path1);
116116
let _ = std::fs::File::open(path5); // $ path-injection-sink MISSING: Alert[rust/path-injection]=arg1
@@ -153,11 +153,11 @@ fn sinks(path1: &Path, path2: &Path) {
153153
let _ = tokio::fs::DirBuilder::new().recursive(true).create(path1); // $ MISSING: path-injection-sink
154154
let _ = tokio::fs::OpenOptions::new().open(path1); // $ MISSING: path-injection-sink
155155

156-
let _ = async_std::fs::read(path1); // $ MISSING: path-injection-sink
157-
let _ = async_std::fs::read_to_string(path1); // $ MISSING: path-injection-sink
158-
let _ = async_std::fs::remove_file(path1); // $ MISSING: path-injection-sink
159-
let _ = async_std::fs::DirBuilder::new().create(path1); // $ MISSING: path-injection-sink
160-
let _ = async_std::fs::DirBuilder::new().recursive(true).create(path1); // $ MISSING: path-injection-sink
156+
let _ = async_std::fs::read(path1); // $ path-injection-sink
157+
let _ = async_std::fs::read_to_string(path1); // $ path-injection-sink
158+
let _ = async_std::fs::remove_file(path1); // $ path-injection-sink
159+
let _ = async_std::fs::DirBuilder::new().create(path1); // $ path-injection-sink
160+
let _ = async_std::fs::DirBuilder::new().recursive(true).create(path1); // $ path-injection-sink
161161
let _ = async_std::fs::OpenOptions::new().open(path1); // $ MISSING: path-injection-sink
162162
}
163163

0 commit comments

Comments
 (0)