Skip to content

Commit 9bcfd01

Browse files
authored
Merge pull request #18676 from paldepind/rust-model-clone
Rust: Model `clone`
2 parents 37ddaa3 + b2ba5f4 commit 9bcfd01

File tree

5 files changed

+186
-0
lines changed

5 files changed

+186
-0
lines changed

rust/ql/lib/codeql/rust/Frameworks.qll

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44

55
private import codeql.rust.frameworks.rustcrypto.RustCrypto
66
private import codeql.rust.frameworks.Sqlx
7+
private import codeql.rust.frameworks.stdlib.Clone
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/** A model for `clone` on the `Clone` trait. */
2+
3+
private import rust
4+
private import codeql.rust.dataflow.FlowSummary
5+
6+
/** A `clone` method. */
7+
final class CloneCallable extends SummarizedCallable::Range {
8+
CloneCallable() {
9+
// NOTE: The function target may not exist in the database, so we base this
10+
// on method calls.
11+
exists(MethodCallExpr c |
12+
c.getNameRef().getText() = "clone" and
13+
c.getArgList().getNumberOfArgs() = 0 and
14+
this = c.getResolvedCrateOrigin() + "::_::" + c.getResolvedPath()
15+
)
16+
}
17+
18+
final override predicate propagatesFlow(string input, string output, boolean preservesValue) {
19+
input = "Argument[self]" and output = "ReturnValue" and preservesValue = true
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
models
2+
| 1 | Summary: lang:core; <crate::option::Option>::unwrap; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value |
3+
| 2 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value |
4+
edges
5+
| main.rs:13:9:13:9 | a [Some] | main.rs:14:10:14:10 | a [Some] | provenance | |
6+
| main.rs:13:9:13:9 | a [Some] | main.rs:15:13:15:13 | a [Some] | provenance | |
7+
| main.rs:13:13:13:28 | Some(...) [Some] | main.rs:13:9:13:9 | a [Some] | provenance | |
8+
| main.rs:13:18:13:27 | source(...) | main.rs:13:13:13:28 | Some(...) [Some] | provenance | |
9+
| main.rs:14:10:14:10 | a [Some] | main.rs:14:10:14:19 | a.unwrap(...) | provenance | MaD:1 |
10+
| main.rs:15:9:15:9 | b [Some] | main.rs:16:10:16:10 | b [Some] | provenance | |
11+
| main.rs:15:13:15:13 | a [Some] | main.rs:15:13:15:21 | a.clone(...) [Some] | provenance | |
12+
| main.rs:15:13:15:21 | a.clone(...) [Some] | main.rs:15:9:15:9 | b [Some] | provenance | |
13+
| main.rs:16:10:16:10 | b [Some] | main.rs:16:10:16:19 | b.unwrap(...) | provenance | MaD:1 |
14+
| main.rs:20:9:20:9 | a [Ok] | main.rs:21:10:21:10 | a [Ok] | provenance | |
15+
| main.rs:20:9:20:9 | a [Ok] | main.rs:22:13:22:13 | a [Ok] | provenance | |
16+
| main.rs:20:31:20:44 | Ok(...) [Ok] | main.rs:20:9:20:9 | a [Ok] | provenance | |
17+
| main.rs:20:34:20:43 | source(...) | main.rs:20:31:20:44 | Ok(...) [Ok] | provenance | |
18+
| main.rs:21:10:21:10 | a [Ok] | main.rs:21:10:21:19 | a.unwrap(...) | provenance | MaD:2 |
19+
| main.rs:22:9:22:9 | b [Ok] | main.rs:23:10:23:10 | b [Ok] | provenance | |
20+
| main.rs:22:13:22:13 | a [Ok] | main.rs:22:13:22:21 | a.clone(...) [Ok] | provenance | |
21+
| main.rs:22:13:22:21 | a.clone(...) [Ok] | main.rs:22:9:22:9 | b [Ok] | provenance | |
22+
| main.rs:23:10:23:10 | b [Ok] | main.rs:23:10:23:19 | b.unwrap(...) | provenance | MaD:2 |
23+
| main.rs:27:9:27:9 | a | main.rs:28:10:28:10 | a | provenance | |
24+
| main.rs:27:9:27:9 | a | main.rs:29:13:29:13 | a | provenance | |
25+
| main.rs:27:13:27:22 | source(...) | main.rs:27:9:27:9 | a | provenance | |
26+
| main.rs:29:9:29:9 | b | main.rs:30:10:30:10 | b | provenance | |
27+
| main.rs:29:13:29:13 | a | main.rs:29:13:29:21 | a.clone(...) | provenance | |
28+
| main.rs:29:13:29:21 | a.clone(...) | main.rs:29:9:29:9 | b | provenance | |
29+
| main.rs:42:13:42:13 | w [Wrapper.n] | main.rs:43:15:43:15 | w [Wrapper.n] | provenance | |
30+
| main.rs:42:17:42:41 | Wrapper {...} [Wrapper.n] | main.rs:42:13:42:13 | w [Wrapper.n] | provenance | |
31+
| main.rs:42:30:42:39 | source(...) | main.rs:42:17:42:41 | Wrapper {...} [Wrapper.n] | provenance | |
32+
| main.rs:43:15:43:15 | w [Wrapper.n] | main.rs:44:13:44:28 | Wrapper {...} [Wrapper.n] | provenance | |
33+
| main.rs:43:15:43:15 | w [Wrapper.n] | main.rs:46:17:46:17 | w [Wrapper.n] | provenance | |
34+
| main.rs:44:13:44:28 | Wrapper {...} [Wrapper.n] | main.rs:44:26:44:26 | n | provenance | |
35+
| main.rs:44:26:44:26 | n | main.rs:44:38:44:38 | n | provenance | |
36+
| main.rs:46:13:46:13 | u [Wrapper.n] | main.rs:47:15:47:15 | u [Wrapper.n] | provenance | |
37+
| main.rs:46:17:46:17 | w [Wrapper.n] | main.rs:46:17:46:25 | w.clone(...) [Wrapper.n] | provenance | |
38+
| main.rs:46:17:46:25 | w.clone(...) [Wrapper.n] | main.rs:46:13:46:13 | u [Wrapper.n] | provenance | |
39+
| main.rs:47:15:47:15 | u [Wrapper.n] | main.rs:48:13:48:28 | Wrapper {...} [Wrapper.n] | provenance | |
40+
| main.rs:48:13:48:28 | Wrapper {...} [Wrapper.n] | main.rs:48:26:48:26 | n | provenance | |
41+
| main.rs:48:26:48:26 | n | main.rs:48:38:48:38 | n | provenance | |
42+
nodes
43+
| main.rs:13:9:13:9 | a [Some] | semmle.label | a [Some] |
44+
| main.rs:13:13:13:28 | Some(...) [Some] | semmle.label | Some(...) [Some] |
45+
| main.rs:13:18:13:27 | source(...) | semmle.label | source(...) |
46+
| main.rs:14:10:14:10 | a [Some] | semmle.label | a [Some] |
47+
| main.rs:14:10:14:19 | a.unwrap(...) | semmle.label | a.unwrap(...) |
48+
| main.rs:15:9:15:9 | b [Some] | semmle.label | b [Some] |
49+
| main.rs:15:13:15:13 | a [Some] | semmle.label | a [Some] |
50+
| main.rs:15:13:15:21 | a.clone(...) [Some] | semmle.label | a.clone(...) [Some] |
51+
| main.rs:16:10:16:10 | b [Some] | semmle.label | b [Some] |
52+
| main.rs:16:10:16:19 | b.unwrap(...) | semmle.label | b.unwrap(...) |
53+
| main.rs:20:9:20:9 | a [Ok] | semmle.label | a [Ok] |
54+
| main.rs:20:31:20:44 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] |
55+
| main.rs:20:34:20:43 | source(...) | semmle.label | source(...) |
56+
| main.rs:21:10:21:10 | a [Ok] | semmle.label | a [Ok] |
57+
| main.rs:21:10:21:19 | a.unwrap(...) | semmle.label | a.unwrap(...) |
58+
| main.rs:22:9:22:9 | b [Ok] | semmle.label | b [Ok] |
59+
| main.rs:22:13:22:13 | a [Ok] | semmle.label | a [Ok] |
60+
| main.rs:22:13:22:21 | a.clone(...) [Ok] | semmle.label | a.clone(...) [Ok] |
61+
| main.rs:23:10:23:10 | b [Ok] | semmle.label | b [Ok] |
62+
| main.rs:23:10:23:19 | b.unwrap(...) | semmle.label | b.unwrap(...) |
63+
| main.rs:27:9:27:9 | a | semmle.label | a |
64+
| main.rs:27:13:27:22 | source(...) | semmle.label | source(...) |
65+
| main.rs:28:10:28:10 | a | semmle.label | a |
66+
| main.rs:29:9:29:9 | b | semmle.label | b |
67+
| main.rs:29:13:29:13 | a | semmle.label | a |
68+
| main.rs:29:13:29:21 | a.clone(...) | semmle.label | a.clone(...) |
69+
| main.rs:30:10:30:10 | b | semmle.label | b |
70+
| main.rs:42:13:42:13 | w [Wrapper.n] | semmle.label | w [Wrapper.n] |
71+
| main.rs:42:17:42:41 | Wrapper {...} [Wrapper.n] | semmle.label | Wrapper {...} [Wrapper.n] |
72+
| main.rs:42:30:42:39 | source(...) | semmle.label | source(...) |
73+
| main.rs:43:15:43:15 | w [Wrapper.n] | semmle.label | w [Wrapper.n] |
74+
| main.rs:44:13:44:28 | Wrapper {...} [Wrapper.n] | semmle.label | Wrapper {...} [Wrapper.n] |
75+
| main.rs:44:26:44:26 | n | semmle.label | n |
76+
| main.rs:44:38:44:38 | n | semmle.label | n |
77+
| main.rs:46:13:46:13 | u [Wrapper.n] | semmle.label | u [Wrapper.n] |
78+
| main.rs:46:17:46:17 | w [Wrapper.n] | semmle.label | w [Wrapper.n] |
79+
| main.rs:46:17:46:25 | w.clone(...) [Wrapper.n] | semmle.label | w.clone(...) [Wrapper.n] |
80+
| main.rs:47:15:47:15 | u [Wrapper.n] | semmle.label | u [Wrapper.n] |
81+
| main.rs:48:13:48:28 | Wrapper {...} [Wrapper.n] | semmle.label | Wrapper {...} [Wrapper.n] |
82+
| main.rs:48:26:48:26 | n | semmle.label | n |
83+
| main.rs:48:38:48:38 | n | semmle.label | n |
84+
subpaths
85+
testFailures
86+
#select
87+
| main.rs:14:10:14:19 | a.unwrap(...) | main.rs:13:18:13:27 | source(...) | main.rs:14:10:14:19 | a.unwrap(...) | $@ | main.rs:13:18:13:27 | source(...) | source(...) |
88+
| main.rs:16:10:16:19 | b.unwrap(...) | main.rs:13:18:13:27 | source(...) | main.rs:16:10:16:19 | b.unwrap(...) | $@ | main.rs:13:18:13:27 | source(...) | source(...) |
89+
| main.rs:21:10:21:19 | a.unwrap(...) | main.rs:20:34:20:43 | source(...) | main.rs:21:10:21:19 | a.unwrap(...) | $@ | main.rs:20:34:20:43 | source(...) | source(...) |
90+
| main.rs:23:10:23:19 | b.unwrap(...) | main.rs:20:34:20:43 | source(...) | main.rs:23:10:23:19 | b.unwrap(...) | $@ | main.rs:20:34:20:43 | source(...) | source(...) |
91+
| main.rs:28:10:28:10 | a | main.rs:27:13:27:22 | source(...) | main.rs:28:10:28:10 | a | $@ | main.rs:27:13:27:22 | source(...) | source(...) |
92+
| main.rs:30:10:30:10 | b | main.rs:27:13:27:22 | source(...) | main.rs:30:10:30:10 | b | $@ | main.rs:27:13:27:22 | source(...) | source(...) |
93+
| main.rs:44:38:44:38 | n | main.rs:42:30:42:39 | source(...) | main.rs:44:38:44:38 | n | $@ | main.rs:42:30:42:39 | source(...) | source(...) |
94+
| main.rs:48:38:48:38 | n | main.rs:42:30:42:39 | source(...) | main.rs:48:38:48:38 | n | $@ | main.rs:42:30:42:39 | source(...) | source(...) |
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 ValueFlow::PathGraph
9+
10+
from ValueFlow::PathNode source, ValueFlow::PathNode sink
11+
where ValueFlow::flowPath(source, sink)
12+
select sink, source, sink, "$@", source, source.toString()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
2+
fn source(i: i64) -> i64 {
3+
1000 + i
4+
}
5+
6+
fn sink(s: i64) {
7+
println!("{}", s);
8+
}
9+
10+
// Flow through `clone` methods
11+
12+
fn option_clone() {
13+
let a = Some(source(88));
14+
sink(a.unwrap()); // $ hasValueFlow=88
15+
let b = a.clone();
16+
sink(b.unwrap()); // $ hasValueFlow=88
17+
}
18+
19+
fn result_clone() {
20+
let a: Result<i64, i64> = Ok(source(37));
21+
sink(a.unwrap()); // $ hasValueFlow=37
22+
let b = a.clone();
23+
sink(b.unwrap()); // $ hasValueFlow=37
24+
}
25+
26+
fn i64_clone() {
27+
let a = source(12);
28+
sink(a); // $ hasValueFlow=12
29+
let b = a.clone();
30+
sink(b); // $ hasValueFlow=12
31+
}
32+
33+
mod my_clone {
34+
use super::{source, sink};
35+
36+
#[derive(Clone)]
37+
struct Wrapper {
38+
n: i64
39+
}
40+
41+
pub fn wrapper_clone() {
42+
let w = Wrapper { n: source(73) };
43+
match w {
44+
Wrapper { n: n } => sink(n) // $ hasValueFlow=73
45+
}
46+
let u = w.clone();
47+
match u {
48+
Wrapper { n: n } => sink(n) // $ hasValueFlow=73
49+
}
50+
}
51+
}
52+
53+
fn main() {
54+
option_clone();
55+
result_clone();
56+
i64_clone();
57+
my_clone::wrapper_clone();
58+
}

0 commit comments

Comments
 (0)