Skip to content

Commit 5b8440e

Browse files
committed
Rust: Add data flow tests for collections
1 parent 7378fbc commit 5b8440e

File tree

5 files changed

+235
-1
lines changed

5 files changed

+235
-1
lines changed

rust/ql/lib/utils/test/InlineFlowTest.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,12 @@ private module FlowTestImpl implements InputSig<Location, RustDataFlow> {
3131

3232
private string getSourceArgString(DataFlow::Node src) {
3333
defaultSource(src) and
34-
result = src.asExpr().(CallExpr).getSyntacticArgument(0).toString()
34+
exists(Expr arg | arg = src.asExpr().(CallExpr).getSyntacticArgument(0) |
35+
not arg instanceof ArrayListExpr and
36+
result = arg.toString()
37+
or
38+
result = arg.(ArrayListExpr).getExpr(0).toString()
39+
)
3540
or
3641
sourceNode(src, _) and
3742
result =

rust/ql/test/library-tests/dataflow/collections/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
models
2+
| 1 | Summary: <& as core::ops::deref::Deref>::deref; Argument[self].Reference; ReturnValue; value |
3+
edges
4+
| main.rs:15:13:15:13 | s | main.rs:16:20:16:20 | s | provenance | |
5+
| main.rs:15:17:15:25 | source(...) | main.rs:15:13:15:13 | s | provenance | |
6+
| main.rs:16:13:16:15 | arr [element] | main.rs:17:14:17:16 | arr [element] | provenance | |
7+
| main.rs:16:19:16:24 | [s; 5] [element] | main.rs:16:13:16:15 | arr [element] | provenance | |
8+
| main.rs:16:20:16:20 | s | main.rs:16:19:16:24 | [s; 5] [element] | provenance | |
9+
| main.rs:17:14:17:16 | arr [element] | main.rs:17:14:17:19 | arr[2] | provenance | |
10+
| main.rs:20:13:20:19 | mut arr | main.rs:21:14:21:19 | arr[0] | provenance | |
11+
| main.rs:20:23:20:33 | source(...) | main.rs:20:13:20:19 | mut arr | provenance | |
12+
| main.rs:24:13:24:13 | s | main.rs:25:20:25:20 | s | provenance | |
13+
| main.rs:24:17:24:25 | source(...) | main.rs:24:13:24:13 | s | provenance | |
14+
| main.rs:25:13:25:15 | arr [element] | main.rs:26:18:26:20 | arr [element] | provenance | |
15+
| main.rs:25:19:25:21 | [...] [element] | main.rs:25:13:25:15 | arr [element] | provenance | |
16+
| main.rs:25:20:25:20 | s | main.rs:25:19:25:21 | [...] [element] | provenance | |
17+
| main.rs:26:13:26:13 | x | main.rs:27:18:27:18 | x | provenance | |
18+
| main.rs:26:18:26:20 | arr [element] | main.rs:26:13:26:13 | x | provenance | |
19+
| main.rs:30:13:30:15 | arr | main.rs:32:18:32:18 | x | provenance | |
20+
| main.rs:30:19:30:29 | source(...) | main.rs:30:13:30:15 | arr | provenance | |
21+
| main.rs:37:9:37:11 | [post] arr [element] | main.rs:38:14:38:16 | arr [element] | provenance | |
22+
| main.rs:37:18:37:26 | source(...) | main.rs:37:9:37:11 | [post] arr [element] | provenance | |
23+
| main.rs:38:14:38:16 | arr [element] | main.rs:38:14:38:19 | arr[0] | provenance | |
24+
| main.rs:63:18:63:22 | SelfParam [&ref, S] | main.rs:63:56:65:9 | { ... } [&ref, S] | provenance | |
25+
| main.rs:82:13:82:13 | s | main.rs:83:19:83:19 | s | provenance | |
26+
| main.rs:82:17:82:25 | source(...) | main.rs:82:13:82:13 | s | provenance | |
27+
| main.rs:83:13:83:13 | s [S] | main.rs:85:16:85:16 | s [S] | provenance | |
28+
| main.rs:83:17:83:20 | S(...) [S] | main.rs:83:13:83:13 | s [S] | provenance | |
29+
| main.rs:83:19:83:19 | s | main.rs:83:17:83:20 | S(...) [S] | provenance | |
30+
| main.rs:85:15:85:25 | * ... [S] | main.rs:85:14:85:28 | ... .0 | provenance | |
31+
| main.rs:85:16:85:16 | s [S] | main.rs:63:18:63:22 | SelfParam [&ref, S] | provenance | |
32+
| main.rs:85:16:85:16 | s [S] | main.rs:85:16:85:25 | s.index(...) [&ref, S] | provenance | |
33+
| main.rs:85:16:85:25 | s.index(...) [&ref, S] | main.rs:85:15:85:25 | * ... [S] | provenance | MaD:1 |
34+
| main.rs:94:10:94:10 | [post] s [S] | main.rs:95:14:95:14 | s [S] | provenance | |
35+
| main.rs:94:10:94:23 | [post] s.index_mut(...) [&ref, S] | main.rs:94:10:94:10 | [post] s [S] | provenance | |
36+
| main.rs:94:27:94:38 | S(...) [S] | main.rs:94:10:94:23 | [post] s.index_mut(...) [&ref, S] | provenance | |
37+
| main.rs:94:29:94:37 | source(...) | main.rs:94:27:94:38 | S(...) [S] | provenance | |
38+
| main.rs:95:14:95:14 | s [S] | main.rs:95:14:95:16 | s.0 | provenance | |
39+
nodes
40+
| main.rs:15:13:15:13 | s | semmle.label | s |
41+
| main.rs:15:17:15:25 | source(...) | semmle.label | source(...) |
42+
| main.rs:16:13:16:15 | arr [element] | semmle.label | arr [element] |
43+
| main.rs:16:19:16:24 | [s; 5] [element] | semmle.label | [s; 5] [element] |
44+
| main.rs:16:20:16:20 | s | semmle.label | s |
45+
| main.rs:17:14:17:16 | arr [element] | semmle.label | arr [element] |
46+
| main.rs:17:14:17:19 | arr[2] | semmle.label | arr[2] |
47+
| main.rs:20:13:20:19 | mut arr | semmle.label | mut arr |
48+
| main.rs:20:23:20:33 | source(...) | semmle.label | source(...) |
49+
| main.rs:21:14:21:19 | arr[0] | semmle.label | arr[0] |
50+
| main.rs:24:13:24:13 | s | semmle.label | s |
51+
| main.rs:24:17:24:25 | source(...) | semmle.label | source(...) |
52+
| main.rs:25:13:25:15 | arr [element] | semmle.label | arr [element] |
53+
| main.rs:25:19:25:21 | [...] [element] | semmle.label | [...] [element] |
54+
| main.rs:25:20:25:20 | s | semmle.label | s |
55+
| main.rs:26:13:26:13 | x | semmle.label | x |
56+
| main.rs:26:18:26:20 | arr [element] | semmle.label | arr [element] |
57+
| main.rs:27:18:27:18 | x | semmle.label | x |
58+
| main.rs:30:13:30:15 | arr | semmle.label | arr |
59+
| main.rs:30:19:30:29 | source(...) | semmle.label | source(...) |
60+
| main.rs:32:18:32:18 | x | semmle.label | x |
61+
| main.rs:37:9:37:11 | [post] arr [element] | semmle.label | [post] arr [element] |
62+
| main.rs:37:18:37:26 | source(...) | semmle.label | source(...) |
63+
| main.rs:38:14:38:16 | arr [element] | semmle.label | arr [element] |
64+
| main.rs:38:14:38:19 | arr[0] | semmle.label | arr[0] |
65+
| main.rs:63:18:63:22 | SelfParam [&ref, S] | semmle.label | SelfParam [&ref, S] |
66+
| main.rs:63:56:65:9 | { ... } [&ref, S] | semmle.label | { ... } [&ref, S] |
67+
| main.rs:82:13:82:13 | s | semmle.label | s |
68+
| main.rs:82:17:82:25 | source(...) | semmle.label | source(...) |
69+
| main.rs:83:13:83:13 | s [S] | semmle.label | s [S] |
70+
| main.rs:83:17:83:20 | S(...) [S] | semmle.label | S(...) [S] |
71+
| main.rs:83:19:83:19 | s | semmle.label | s |
72+
| main.rs:85:14:85:28 | ... .0 | semmle.label | ... .0 |
73+
| main.rs:85:15:85:25 | * ... [S] | semmle.label | * ... [S] |
74+
| main.rs:85:16:85:16 | s [S] | semmle.label | s [S] |
75+
| main.rs:85:16:85:25 | s.index(...) [&ref, S] | semmle.label | s.index(...) [&ref, S] |
76+
| main.rs:94:10:94:10 | [post] s [S] | semmle.label | [post] s [S] |
77+
| main.rs:94:10:94:23 | [post] s.index_mut(...) [&ref, S] | semmle.label | [post] s.index_mut(...) [&ref, S] |
78+
| main.rs:94:27:94:38 | S(...) [S] | semmle.label | S(...) [S] |
79+
| main.rs:94:29:94:37 | source(...) | semmle.label | source(...) |
80+
| main.rs:95:14:95:14 | s [S] | semmle.label | s [S] |
81+
| main.rs:95:14:95:16 | s.0 | semmle.label | s.0 |
82+
subpaths
83+
| main.rs:85:16:85:16 | s [S] | main.rs:63:18:63:22 | SelfParam [&ref, S] | main.rs:63:56:65:9 | { ... } [&ref, S] | main.rs:85:16:85:25 | s.index(...) [&ref, S] |
84+
testFailures
85+
#select
86+
| main.rs:17:14:17:19 | arr[2] | main.rs:15:17:15:25 | source(...) | main.rs:17:14:17:19 | arr[2] | $@ | main.rs:15:17:15:25 | source(...) | source(...) |
87+
| main.rs:21:14:21:19 | arr[0] | main.rs:20:23:20:33 | source(...) | main.rs:21:14:21:19 | arr[0] | $@ | main.rs:20:23:20:33 | source(...) | source(...) |
88+
| main.rs:27:18:27:18 | x | main.rs:24:17:24:25 | source(...) | main.rs:27:18:27:18 | x | $@ | main.rs:24:17:24:25 | source(...) | source(...) |
89+
| main.rs:32:18:32:18 | x | main.rs:30:19:30:29 | source(...) | main.rs:32:18:32:18 | x | $@ | main.rs:30:19:30:29 | source(...) | source(...) |
90+
| main.rs:38:14:38:19 | arr[0] | main.rs:37:18:37:26 | source(...) | main.rs:38:14:38:19 | arr[0] | $@ | main.rs:37:18:37:26 | source(...) | source(...) |
91+
| main.rs:85:14:85:28 | ... .0 | main.rs:82:17:82:25 | source(...) | main.rs:85:14:85:28 | ... .0 | $@ | main.rs:82:17:82:25 | source(...) | source(...) |
92+
| main.rs:95:14:95:16 | s.0 | main.rs:94:29:94:37 | source(...) | main.rs:95:14:95:16 | s.0 | $@ | main.rs:94:29:94:37 | source(...) | source(...) |
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/**
2+
* @kind path-problem
3+
*/
4+
5+
import rust
6+
import utils.test.InlineFlowTest
7+
import DefaultFlowTest
8+
import TaintFlow::PathGraph
9+
10+
from TaintFlow::PathNode source, TaintFlow::PathNode sink
11+
where TaintFlow::flowPath(source, sink)
12+
select sink, source, sink, "$@", source, source.toString()
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
fn source<T>(s: T) -> T {
2+
s
3+
}
4+
5+
fn sink(s: i64) {
6+
println!("{}", s);
7+
}
8+
9+
mod arrays {
10+
use crate::*;
11+
use std::ops::Index;
12+
use std::ops::IndexMut;
13+
14+
pub fn f() {
15+
let s = source(0);
16+
let arr = [s; 5];
17+
sink(arr[2]); // $ hasValueFlow=0
18+
sink(*arr.index(2)); // $ MISSING: hasValueFlow=0
19+
20+
let mut arr = source([1]);
21+
sink(arr[0]); // $ hasTaintFlow=1
22+
sink(*arr.index(0)); // $ MISSING: hasTaintFlow=1
23+
24+
let s = source(2);
25+
let arr = [s];
26+
for x in arr {
27+
sink(x); // $ hasValueFlow=2
28+
}
29+
30+
let arr = source([3]);
31+
for x in arr {
32+
sink(x); // $ hasTaintFlow=3
33+
}
34+
35+
let mut arr = [0];
36+
sink(arr[0]);
37+
arr[0] = source(4);
38+
sink(arr[0]); // $ hasValueFlow=4
39+
40+
let mut arr = [0];
41+
sink(arr[0]);
42+
*arr.index_mut(0) = source(5);
43+
sink(arr[0]); // $ MISSING: hasValueFlow=5 -- needs generalized reverse flow
44+
45+
let mut arr = [0];
46+
arr[0] += source(6);
47+
sink(arr[0]); // $ MISSING: hasTaintFlow=6
48+
}
49+
}
50+
51+
mod indexers {
52+
use crate::*;
53+
use std::ops::AddAssign;
54+
use std::ops::Index;
55+
use std::ops::IndexMut;
56+
57+
#[derive(Debug)]
58+
struct S<T>(T);
59+
60+
impl<T> Index<usize> for S<T> {
61+
type Output = S<T>; // `T` would be a better choice here, but that requires generalized reverse flow for the test to pass
62+
63+
fn index(&self, index: usize) -> &Self::Output {
64+
self
65+
}
66+
}
67+
68+
impl<T> IndexMut<usize> for S<T> {
69+
// `Self::Output` is not yet handled, so use `S<T>` for now
70+
fn index_mut(&mut self, index: usize) -> &mut S<T> {
71+
self
72+
}
73+
}
74+
75+
impl std::ops::AddAssign for S<i64> {
76+
fn add_assign(&mut self, other: Self) {
77+
self.0 += other.0;
78+
}
79+
}
80+
81+
pub fn f() {
82+
let s = source(0);
83+
let s = S(s);
84+
sink(s[0].0); // $ MISSING: hasValueFlow=0
85+
sink((*s.index(0)).0); // $ hasValueFlow=0
86+
87+
let mut s = S(0);
88+
sink(s.0);
89+
s[0] = S(source(1));
90+
sink(s.0); // $ MISSING: hasValueFlow=1
91+
92+
let mut s = S(0);
93+
sink(s.0);
94+
*s.index_mut(0) = S(source(2));
95+
sink(s.0); // $ hasValueFlow=2
96+
97+
let mut s = S(0i64);
98+
sink(s.0);
99+
s[0] += S(source(3));
100+
sink(s.0); // $ MISSING: hasTaintFlow=3
101+
102+
let mut s = S(0i64);
103+
sink(s.0);
104+
*s.index_mut(0) += S(source(5));
105+
s[0] += S(source(5));
106+
sink(s.0); // $ MISSING: hasTaintFlow=5
107+
108+
let mut s = S(0i64);
109+
sink(s.0);
110+
(*s.index_mut(0)).add_assign(S(source(6)));
111+
sink(s.0); // $ MISSING: hasTaintFlow=6
112+
}
113+
}
114+
115+
fn main() {
116+
arrays::f();
117+
indexers::f();
118+
}

0 commit comments

Comments
 (0)