Skip to content

Commit 58d86fd

Browse files
authored
Merge pull request #18714 from paldepind/rust-pointer
Rust: Handle writes to references and add encoding of reference content
2 parents c7412cc + 1105576 commit 58d86fd

File tree

10 files changed

+205
-107
lines changed

10 files changed

+205
-107
lines changed

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

+15
Original file line numberDiff line numberDiff line change
@@ -1211,6 +1211,17 @@ module RustDataFlow implements InputSig<Location> {
12111211
)
12121212
}
12131213

1214+
pragma[nomagic]
1215+
private predicate referenceAssignment(Node node1, Node node2, ReferenceContent c) {
1216+
exists(AssignmentExprCfgNode assignment, PrefixExprCfgNode deref |
1217+
assignment.getLhs() = deref and
1218+
deref.getOperatorName() = "*" and
1219+
node1.asExpr() = assignment.getRhs() and
1220+
node2.asExpr() = deref.getExpr() and
1221+
exists(c)
1222+
)
1223+
}
1224+
12141225
pragma[nomagic]
12151226
private predicate storeContentStep(Node node1, Content c, Node node2) {
12161227
exists(CallExprCfgNode call, int pos |
@@ -1242,6 +1253,8 @@ module RustDataFlow implements InputSig<Location> {
12421253
or
12431254
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
12441255
or
1256+
referenceAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
1257+
or
12451258
exists(AssignmentExprCfgNode assignment, IndexExprCfgNode index |
12461259
c instanceof ElementContent and
12471260
assignment.getLhs() = index and
@@ -1285,6 +1298,8 @@ module RustDataFlow implements InputSig<Location> {
12851298
predicate clearsContent(Node n, ContentSet cs) {
12861299
fieldAssignment(_, n, cs.(SingletonContentSet).getContent())
12871300
or
1301+
referenceAssignment(_, n, cs.(SingletonContentSet).getContent())
1302+
or
12881303
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(Node::FlowSummaryNode).getSummaryNode(),
12891304
cs)
12901305
or

rust/ql/lib/codeql/rust/dataflow/internal/FlowSummaryImpl.qll

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ module Input implements InputSig<Location, RustDataFlow> {
8989
arg = v.getExtendedCanonicalPath() + "(" + v.getPosition() + ")"
9090
)
9191
or
92+
result = "Reference" and
93+
c = TReferenceContent() and
94+
arg = ""
95+
or
9296
result = "Element" and
9397
c = TElementContent() and
9498
arg = ""

rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll

+2-3
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
8181
}
8282

8383
bindingset[c]
84-
string paramReturnNodeAsOutput(R::Callable c, ParameterPosition pos) {
85-
// TODO: Implement this to support returning through parameters.
86-
result = "paramReturnNodeAsOutput(" + c + ", " + pos + ")"
84+
string paramReturnNodeAsOutput(Callable c, ParameterPosition pos) {
85+
result = paramReturnNodeAsContentOutput(c, pos)
8786
}
8887

8988
bindingset[c]

rust/ql/test/library-tests/dataflow/global/inline-flow.expected

+17
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ edges
4242
| main.rs:101:13:101:30 | mn.data_through(...) | main.rs:101:9:101:9 | b | provenance | |
4343
| main.rs:101:29:101:29 | a | main.rs:77:28:77:33 | ...: i64 | provenance | |
4444
| main.rs:101:29:101:29 | a | main.rs:101:13:101:30 | mn.data_through(...) | provenance | |
45+
| main.rs:139:25:139:30 | ...: i64 | main.rs:140:10:140:10 | c | provenance | |
46+
| main.rs:140:6:140:6 | [post] n [&ref] | main.rs:139:12:139:22 | ...: ... [Return] [&ref] | provenance | |
47+
| main.rs:140:10:140:10 | c | main.rs:140:6:140:6 | [post] n [&ref] | provenance | |
48+
| main.rs:148:13:148:13 | [post] m [&ref] | main.rs:149:11:149:11 | m [&ref] | provenance | |
49+
| main.rs:148:16:148:25 | source(...) | main.rs:139:25:139:30 | ...: i64 | provenance | |
50+
| main.rs:148:16:148:25 | source(...) | main.rs:148:13:148:13 | [post] m [&ref] | provenance | |
51+
| main.rs:149:11:149:11 | m [&ref] | main.rs:149:10:149:11 | * ... | provenance | |
4552
nodes
4653
| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } |
4754
| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) |
@@ -92,11 +99,20 @@ nodes
9299
| main.rs:101:13:101:30 | mn.data_through(...) | semmle.label | mn.data_through(...) |
93100
| main.rs:101:29:101:29 | a | semmle.label | a |
94101
| main.rs:102:10:102:10 | b | semmle.label | b |
102+
| main.rs:139:12:139:22 | ...: ... [Return] [&ref] | semmle.label | ...: ... [Return] [&ref] |
103+
| main.rs:139:25:139:30 | ...: i64 | semmle.label | ...: i64 |
104+
| main.rs:140:6:140:6 | [post] n [&ref] | semmle.label | [post] n [&ref] |
105+
| main.rs:140:10:140:10 | c | semmle.label | c |
106+
| main.rs:148:13:148:13 | [post] m [&ref] | semmle.label | [post] m [&ref] |
107+
| main.rs:148:16:148:25 | source(...) | semmle.label | source(...) |
108+
| main.rs:149:10:149:11 | * ... | semmle.label | * ... |
109+
| main.rs:149:11:149:11 | m [&ref] | semmle.label | m [&ref] |
95110
subpaths
96111
| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:36:13:36:27 | pass_through(...) |
97112
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) |
98113
| main.rs:55:26:55:26 | a | main.rs:51:21:51:26 | ...: i64 | main.rs:51:36:53:5 | { ... } | main.rs:55:13:55:27 | pass_through(...) |
99114
| main.rs:101:29:101:29 | a | main.rs:77:28:77:33 | ...: i64 | main.rs:77:43:83:5 | { ... } | main.rs:101:13:101:30 | mn.data_through(...) |
115+
| main.rs:148:16:148:25 | source(...) | main.rs:139:25:139:30 | ...: i64 | main.rs:139:12:139:22 | ...: ... [Return] [&ref] | main.rs:148:13:148:13 | [post] m [&ref] |
100116
testFailures
101117
#select
102118
| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) | source(...) |
@@ -107,3 +123,4 @@ testFailures
107123
| main.rs:68:14:68:14 | n | main.rs:94:13:94:21 | source(...) | main.rs:68:14:68:14 | n | $@ | main.rs:94:13:94:21 | source(...) | source(...) |
108124
| main.rs:89:10:89:10 | a | main.rs:74:13:74:21 | source(...) | main.rs:89:10:89:10 | a | $@ | main.rs:74:13:74:21 | source(...) | source(...) |
109125
| main.rs:102:10:102:10 | b | main.rs:100:13:100:21 | source(...) | main.rs:102:10:102:10 | b | $@ | main.rs:100:13:100:21 | source(...) | source(...) |
126+
| main.rs:149:10:149:11 | * ... | main.rs:148:16:148:25 | source(...) | main.rs:149:10:149:11 | * ... | $@ | main.rs:148:16:148:25 | source(...) | source(...) |

rust/ql/test/library-tests/dataflow/global/main.rs

+25
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,29 @@ pub fn test_operator_overloading() {
134134
sink(d.value); // $ MISSING: hasValueFlow=7
135135
}
136136

137+
// Flow out of mutable parameters.
138+
139+
fn set_int(n: &mut i64, c: i64) {
140+
*n = c;
141+
}
142+
143+
fn mutates_argument_1() {
144+
// Passing an already borrowed value to a function and then reading from the same borrow.
145+
let mut n = 0;
146+
let m = &mut n;
147+
sink(*m);
148+
set_int(m, source(37));
149+
sink(*m); // $ hasValueFlow=37
150+
}
151+
152+
fn mutates_argument_2() {
153+
// Borrowing at the call and then reading from the unborrowed variable.
154+
let mut n = 0;
155+
sink(n);
156+
set_int(&mut n, source(88));
157+
sink(n); // $ MISSING: hasValueFlow=88
158+
}
159+
137160
fn main() {
138161
data_out_of_call();
139162
data_in_to_call();
@@ -145,4 +168,6 @@ fn main() {
145168
data_through_method();
146169

147170
test_operator_overloading();
171+
mutates_argument_1();
172+
mutates_argument_2();
148173
}

rust/ql/test/library-tests/dataflow/global/viableCallable.expected

+18-8
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,21 @@
2929
| main.rs:131:28:131:36 | source(...) | main.rs:1:1:3:1 | fn source |
3030
| main.rs:133:13:133:20 | a.add(...) | main.rs:114:5:117:5 | fn add |
3131
| main.rs:134:5:134:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
32-
| main.rs:138:5:138:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
33-
| main.rs:139:5:139:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
34-
| main.rs:140:5:140:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
35-
| main.rs:141:5:141:34 | data_through_nested_function(...) | main.rs:48:1:57:1 | fn data_through_nested_function |
36-
| main.rs:143:5:143:24 | data_out_of_method(...) | main.rs:86:1:90:1 | fn data_out_of_method |
37-
| main.rs:144:5:144:28 | data_in_to_method_call(...) | main.rs:92:1:96:1 | fn data_in_to_method_call |
38-
| main.rs:145:5:145:25 | data_through_method(...) | main.rs:98:1:103:1 | fn data_through_method |
39-
| main.rs:147:5:147:31 | test_operator_overloading(...) | main.rs:120:1:135:1 | fn test_operator_overloading |
32+
| main.rs:147:5:147:12 | sink(...) | main.rs:5:1:7:1 | fn sink |
33+
| main.rs:148:5:148:26 | set_int(...) | main.rs:139:1:141:1 | fn set_int |
34+
| main.rs:148:16:148:25 | source(...) | main.rs:1:1:3:1 | fn source |
35+
| main.rs:149:5:149:12 | sink(...) | main.rs:5:1:7:1 | fn sink |
36+
| main.rs:155:5:155:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
37+
| main.rs:156:5:156:31 | set_int(...) | main.rs:139:1:141:1 | fn set_int |
38+
| main.rs:156:21:156:30 | source(...) | main.rs:1:1:3:1 | fn source |
39+
| main.rs:157:5:157:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
40+
| main.rs:161:5:161:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
41+
| main.rs:162:5:162:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
42+
| main.rs:163:5:163:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
43+
| main.rs:164:5:164:34 | data_through_nested_function(...) | main.rs:48:1:57:1 | fn data_through_nested_function |
44+
| main.rs:166:5:166:24 | data_out_of_method(...) | main.rs:86:1:90:1 | fn data_out_of_method |
45+
| main.rs:167:5:167:28 | data_in_to_method_call(...) | main.rs:92:1:96:1 | fn data_in_to_method_call |
46+
| main.rs:168:5:168:25 | data_through_method(...) | main.rs:98:1:103:1 | fn data_through_method |
47+
| main.rs:170:5:170:31 | test_operator_overloading(...) | main.rs:120:1:135:1 | fn test_operator_overloading |
48+
| main.rs:171:5:171:24 | mutates_argument_1(...) | main.rs:143:1:150:1 | fn mutates_argument_1 |
49+
| main.rs:172:5:172:24 | mutates_argument_2(...) | main.rs:152:1:158:1 | fn mutates_argument_2 |

0 commit comments

Comments
 (0)