Skip to content

Commit e1bddb6

Browse files
authored
Merge pull request #19304 from geoffw0/rustio
Rust: Model sources for std::io
2 parents e05c030 + c561da4 commit e1bddb6

File tree

6 files changed

+325
-3
lines changed

6 files changed

+325
-3
lines changed

rust/ql/lib/codeql/rust/Concepts.qll

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,58 @@ class ModeledEnvironmentSource extends EnvironmentSource::Range {
102102
ModeledEnvironmentSource() { sourceNode(this, "environment-source") }
103103
}
104104

105+
/**
106+
* A data flow source corresponding to a file access.
107+
*/
108+
final class FileSource = FileSource::Range;
109+
110+
/**
111+
* An externally modeled source for data from a file access.
112+
*/
113+
class ModeledFileSource extends FileSource::Range {
114+
ModeledFileSource() { sourceNode(this, "file") }
115+
}
116+
117+
/**
118+
* Provides a class for modeling new sources for file accesses.
119+
*/
120+
module FileSource {
121+
/**
122+
* A data flow source corresponding to a file access.
123+
*/
124+
abstract class Range extends ThreatModelSource::Range {
125+
override string getThreatModel() { result = "file" }
126+
127+
override string getSourceType() { result = "FileSource" }
128+
}
129+
}
130+
131+
/**
132+
* A data flow source corresponding to standard input.
133+
*/
134+
final class StdInSource = StdInSource::Range;
135+
136+
/**
137+
* An externally modeled source for data from standard input.
138+
*/
139+
class ModeledStdInSourceSource extends StdInSource::Range {
140+
ModeledStdInSourceSource() { sourceNode(this, "stdin") }
141+
}
142+
143+
/**
144+
* Provides a class for modeling new sources for standard input.
145+
*/
146+
module StdInSource {
147+
/**
148+
* A data flow source corresponding to standard input.
149+
*/
150+
abstract class Range extends ThreatModelSource::Range {
151+
override string getThreatModel() { result = "stdin" }
152+
153+
override string getSourceType() { result = "StdInSource" }
154+
}
155+
}
156+
105157
/**
106158
* A data flow source corresponding to the program's database reads.
107159
*/

rust/ql/lib/codeql/rust/frameworks/stdlib/fs.model.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,14 @@ extensions:
22
- addsTo:
33
pack: codeql/rust-all
44
extensible: sourceModel
5-
data: []
5+
data:
6+
- ["lang:std", "crate::fs::read", "ReturnValue.Field[crate::result::Result::Ok(0)]", "file", "manual"]
7+
- ["lang:std", "crate::fs::read_to_string", "ReturnValue.Field[crate::result::Result::Ok(0)]", "file", "manual"]
8+
- ["lang:std", "crate::fs::read_link", "ReturnValue.Field[crate::result::Result::Ok(0)]", "file", "manual"]
9+
- ["lang:std", "<crate::fs::DirEntry>::path", "ReturnValue", "file", "manual"]
10+
- ["lang:std", "<crate::fs::DirEntry>::file_name", "ReturnValue", "file", "manual"]
11+
- ["lang:std", "<crate::fs::File>::open", "ReturnValue.Field[crate::result::Result::Ok(0)]", "file", "manual"]
12+
- ["lang:std", "<crate::fs::File>::open_buffered", "ReturnValue.Field[crate::result::Result::Ok(0)]", "file", "manual"]
613
- addsTo:
714
pack: codeql/rust-all
815
extensible: sinkModel
@@ -34,7 +41,6 @@ extensions:
3441
- ["lang:std", "<crate::fs::File>::create_new", "Argument[0]", "path-injection", "manual"]
3542
- ["lang:std", "<crate::fs::File>::open", "Argument[0]", "path-injection", "manual"]
3643
- ["lang:std", "<crate::fs::File>::open_buffered", "Argument[0]", "path-injection", "manual"]
37-
3844
- addsTo:
3945
pack: codeql/rust-all
4046
extensible: summaryModel
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/rust-all
4+
extensible: sourceModel
5+
data:
6+
- ["lang:std", "crate::io::stdio::stdin", "ReturnValue", "stdin", "manual"]
7+
- addsTo:
8+
pack: codeql/rust-all
9+
extensible: summaryModel
10+
data:
11+
- ["lang:std", "<crate::io::buffered::bufreader::BufReader>::new", "Argument[0]", "ReturnValue", "taint", "manual"]
12+
- ["lang:std", "<crate::io::buffered::bufreader::BufReader as crate::io::BufRead>::fill_buf", "Argument[self]", "ReturnValue.Field[crate::result::Result::Ok(0)]", "taint", "manual"]
13+
- ["lang:std", "<crate::io::buffered::bufreader::BufReader>::buffer", "Argument[self]", "ReturnValue", "taint", "manual"]
14+
- ["lang:std", "<crate::io::stdio::Stdin as crate::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
15+
- ["lang:std", "<crate::io::stdio::StdinLock as crate::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
16+
- ["lang:std", "<crate::fs::File as crate::io::Read>::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
17+
- ["lang:std", "crate::io::Read::read", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
18+
- ["lang:std", "<crate::io::stdio::Stdin as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
19+
- ["lang:std", "<crate::io::stdio::StdinLock as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
20+
- ["lang:std", "<crate::fs::File as crate::io::Read>::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
21+
- ["lang:std", "crate::io::Read::read_to_string", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
22+
- ["lang:std", ":<crate::io::stdio::Stdin as crate::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
23+
- ["lang:std", ":<crate::io::stdio::StdinLock as crate::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
24+
- ["lang:std", "<crate::fs::File as crate::io::Read>::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
25+
- ["lang:std", "crate::io::Read::read_to_end", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
26+
- ["lang:std", "<crate::io::stdio::Stdin as crate::io::Read>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
27+
- ["lang:std", "<crate::io::stdio::StdinLock as crate::io::Read>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
28+
- ["lang:std", "<crate::fs::File as crate::io::Read>::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
29+
- ["lang:std", "crate::io::Read::read_exact", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
30+
- ["lang:std", "crate::io::BufRead::read_line", "Argument[self]", "Argument[0].Reference", "taint", "manual"]
31+
- ["lang:std", "crate::io::BufRead::read_until", "Argument[self]", "Argument[1].Reference", "taint", "manual"]
32+
- ["lang:std", "crate::io::BufRead::split", "Argument[self]", "ReturnValue", "taint", "manual"]
33+
- ["lang:std", "crate::io::BufRead::lines", "Argument[self]", "ReturnValue", "taint", "manual"]
34+
- ["lang:std", "crate::io::Read::bytes", "Argument[self]", "ReturnValue", "taint", "manual"]
35+
- ["lang:std", "crate::io::Read::chain", "Argument[self]", "ReturnValue", "taint", "manual"]
36+
- ["lang:std", "crate::io::Read::chain", "Argument[0]", "ReturnValue", "taint", "manual"]
37+
- ["lang:std", "crate::io::Read::take", "Argument[self]", "ReturnValue", "taint", "manual"]
38+
- ["lang:std", "<crate::io::stdio::Stdin>::lock", "Argument[self]", "ReturnValue", "taint", "manual"]

rust/ql/test/library-tests/dataflow/local/DataFlowStep.expected

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1940,8 +1940,25 @@ storeStep
19401940
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<u8 as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:proc_macro::_::<u8 as crate::bridge::rpc::DecodeMut>::decode |
19411941
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<u32 as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:proc_macro::_::<u32 as crate::bridge::rpc::DecodeMut>::decode |
19421942
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<usize as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:proc_macro::_::<usize as crate::bridge::rpc::DecodeMut>::decode |
1943+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_:::<crate::io::stdio::Stdin as crate::io::Read>::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_:::<crate::io::stdio::Stdin as crate::io::Read>::read_to_end |
1944+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_:::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_:::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_end |
1945+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::fs::File as crate::io::Read>::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::fs::File as crate::io::Read>::read |
1946+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::fs::File as crate::io::Read>::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::fs::File as crate::io::Read>::read_exact |
1947+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::fs::File as crate::io::Read>::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::fs::File as crate::io::Read>::read_to_end |
1948+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::fs::File as crate::io::Read>::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::fs::File as crate::io::Read>::read_to_string |
19431949
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::IoSlice>::advance_slices | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::IoSlice>::advance_slices |
19441950
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::IoSliceMut>::advance_slices | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::IoSliceMut>::advance_slices |
1951+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read |
1952+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read_exact |
1953+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::Stdin as crate::io::Read>::read_to_string |
1954+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read |
1955+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_exact |
1956+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::<crate::io::stdio::StdinLock as crate::io::Read>::read_to_string |
1957+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::BufRead::read_line | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::BufRead::read_line |
1958+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read |
1959+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_exact | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_exact |
1960+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_to_end | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_to_end |
1961+
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:std::_::crate::io::Read::read_to_string | &ref | file://:0:0:0:0 | [post] [summary param] 0 in lang:std::_::crate::io::Read::read_to_string |
19451962
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<&[u8] as crate::bridge::rpc::DecodeMut>::decode |
19461963
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::<u8 as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<u8 as crate::bridge::rpc::DecodeMut>::decode |
19471964
| file://:0:0:0:0 | [summary] to write: Argument[0].Reference.Reference in lang:proc_macro::_::<u32 as crate::bridge::rpc::DecodeMut>::decode | &ref | file://:0:0:0:0 | [summary] to write: Argument[0].Reference in lang:proc_macro::_::<u32 as crate::bridge::rpc::DecodeMut>::decode |
@@ -1957,6 +1974,7 @@ storeStep
19571974
| file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:core::_::<crate::cell::RefMut>::map_split | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:core::_::<crate::cell::RefMut>::map_split |
19581975
| file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0].Reference in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_while | &ref | file://:0:0:0:0 | [summary] to write: Argument[1].Parameter[0] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_while |
19591976
| file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:core::_::<_ as crate::clone::uninit::CopySpec>::clone_one |
1977+
| file://:0:0:0:0 | [summary] to write: Argument[1].Reference in lang:std::_::crate::io::BufRead::read_until | &ref | file://:0:0:0:0 | [post] [summary param] 1 in lang:std::_::crate::io::BufRead::read_until |
19601978
| file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::max_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::max_by |
19611979
| file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::max_by_key | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::max_by_key |
19621980
| file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0].Reference in lang:core::_::crate::cmp::min_by | &ref | file://:0:0:0:0 | [summary] to write: Argument[2].Parameter[0] in lang:core::_::crate::cmp::min_by |
@@ -2185,6 +2203,7 @@ storeStep
21852203
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<crate::result::Result>::or_else | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<crate::result::Result>::or_else |
21862204
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:core::_::<str>::parse | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:core::_::<str>::parse |
21872205
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<&[u8] as crate::io::BufRead>::fill_buf |
2206+
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::io::buffered::bufreader::BufReader as crate::io::BufRead>::fill_buf | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::io::buffered::bufreader::BufReader as crate::io::BufRead>::fill_buf |
21882207
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::path::Path>::canonicalize | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::path::Path>::canonicalize |
21892208
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait |
21902209
| file://:0:0:0:0 | [summary] to write: ReturnValue.Field[crate::result::Result::Ok(0)] in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout | Ok | file://:0:0:0:0 | [summary] to write: ReturnValue in lang:std::_::<crate::sync::poison::condvar::Condvar>::wait_timeout |

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,28 @@
2222
| test.rs:80:24:80:35 | ...::get | Flow source 'RemoteSource' of type remote (DEFAULT). |
2323
| test.rs:112:35:112:46 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). |
2424
| test.rs:119:31:119:42 | send_request | Flow source 'RemoteSource' of type remote (DEFAULT). |
25-
| test.rs:203:16:203:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). |
25+
| test.rs:205:31:205:43 | ...::read | Flow source 'FileSource' of type file (DEFAULT). |
26+
| test.rs:210:31:210:38 | ...::read | Flow source 'FileSource' of type file (DEFAULT). |
27+
| test.rs:215:22:215:39 | ...::read_to_string | Flow source 'FileSource' of type file (DEFAULT). |
28+
| test.rs:221:22:221:25 | path | Flow source 'FileSource' of type file (DEFAULT). |
29+
| test.rs:222:27:222:35 | file_name | Flow source 'FileSource' of type file (DEFAULT). |
30+
| test.rs:228:22:228:34 | ...::read_link | Flow source 'FileSource' of type file (DEFAULT). |
31+
| test.rs:243:22:243:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
32+
| test.rs:249:22:249:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
33+
| test.rs:255:22:255:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
34+
| test.rs:261:9:261:22 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
35+
| test.rs:265:17:265:30 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
36+
| test.rs:271:20:271:38 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
37+
| test.rs:304:50:304:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
38+
| test.rs:310:50:310:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
39+
| test.rs:317:50:317:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
40+
| test.rs:324:50:324:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
41+
| test.rs:331:56:331:69 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
42+
| test.rs:338:50:338:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
43+
| test.rs:345:50:345:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
44+
| test.rs:351:50:351:63 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
45+
| test.rs:360:25:360:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
46+
| test.rs:361:25:361:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
47+
| test.rs:369:25:369:43 | ...::open | Flow source 'FileSource' of type file (DEFAULT). |
48+
| test.rs:377:22:377:35 | ...::stdin | Flow source 'StdInSource' of type stdin (DEFAULT). |
49+
| test.rs:386:16:386:29 | ...::args | Flow source 'CommandLineArgs' of type commandargs (DEFAULT). |

0 commit comments

Comments
 (0)