Merge pull request #18714 from paldepind/rust-pointer

Rust: Handle writes to references and add encoding of reference content
This commit is contained in:
Simon Friis Vindum
2025-02-11 14:12:56 +01:00
committed by GitHub
10 changed files with 205 additions and 107 deletions

View File

@@ -1211,6 +1211,17 @@ module RustDataFlow implements InputSig<Location> {
)
}
pragma[nomagic]
private predicate referenceAssignment(Node node1, Node node2, ReferenceContent c) {
exists(AssignmentExprCfgNode assignment, PrefixExprCfgNode deref |
assignment.getLhs() = deref and
deref.getOperatorName() = "*" and
node1.asExpr() = assignment.getRhs() and
node2.asExpr() = deref.getExpr() and
exists(c)
)
}
pragma[nomagic]
private predicate storeContentStep(Node node1, Content c, Node node2) {
exists(CallExprCfgNode call, int pos |
@@ -1242,6 +1253,8 @@ module RustDataFlow implements InputSig<Location> {
or
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
or
referenceAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
or
exists(AssignmentExprCfgNode assignment, IndexExprCfgNode index |
c instanceof ElementContent and
assignment.getLhs() = index and
@@ -1285,6 +1298,8 @@ module RustDataFlow implements InputSig<Location> {
predicate clearsContent(Node n, ContentSet cs) {
fieldAssignment(_, n, cs.(SingletonContentSet).getContent())
or
referenceAssignment(_, n, cs.(SingletonContentSet).getContent())
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(Node::FlowSummaryNode).getSummaryNode(),
cs)
or

View File

@@ -89,6 +89,10 @@ module Input implements InputSig<Location, RustDataFlow> {
arg = v.getExtendedCanonicalPath() + "(" + v.getPosition() + ")"
)
or
result = "Reference" and
c = TReferenceContent() and
arg = ""
or
result = "Element" and
c = TElementContent() and
arg = ""

View File

@@ -81,9 +81,8 @@ module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataF
}
bindingset[c]
string paramReturnNodeAsOutput(R::Callable c, ParameterPosition pos) {
// TODO: Implement this to support returning through parameters.
result = "paramReturnNodeAsOutput(" + c + ", " + pos + ")"
string paramReturnNodeAsOutput(Callable c, ParameterPosition pos) {
result = paramReturnNodeAsContentOutput(c, pos)
}
bindingset[c]

View File

@@ -42,6 +42,13 @@ edges
| main.rs:101:13:101:30 | mn.data_through(...) | main.rs:101:9:101:9 | b | provenance | |
| main.rs:101:29:101:29 | a | main.rs:77:28:77:33 | ...: i64 | provenance | |
| main.rs:101:29:101:29 | a | main.rs:101:13:101:30 | mn.data_through(...) | provenance | |
| main.rs:139:25:139:30 | ...: i64 | main.rs:140:10:140:10 | c | provenance | |
| main.rs:140:6:140:6 | [post] n [&ref] | main.rs:139:12:139:22 | ...: ... [Return] [&ref] | provenance | |
| main.rs:140:10:140:10 | c | main.rs:140:6:140:6 | [post] n [&ref] | provenance | |
| main.rs:148:13:148:13 | [post] m [&ref] | main.rs:149:11:149:11 | m [&ref] | provenance | |
| main.rs:148:16:148:25 | source(...) | main.rs:139:25:139:30 | ...: i64 | provenance | |
| main.rs:148:16:148:25 | source(...) | main.rs:148:13:148:13 | [post] m [&ref] | provenance | |
| main.rs:149:11:149:11 | m [&ref] | main.rs:149:10:149:11 | * ... | provenance | |
nodes
| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } |
| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) |
@@ -92,11 +99,20 @@ nodes
| main.rs:101:13:101:30 | mn.data_through(...) | semmle.label | mn.data_through(...) |
| main.rs:101:29:101:29 | a | semmle.label | a |
| main.rs:102:10:102:10 | b | semmle.label | b |
| main.rs:139:12:139:22 | ...: ... [Return] [&ref] | semmle.label | ...: ... [Return] [&ref] |
| main.rs:139:25:139:30 | ...: i64 | semmle.label | ...: i64 |
| main.rs:140:6:140:6 | [post] n [&ref] | semmle.label | [post] n [&ref] |
| main.rs:140:10:140:10 | c | semmle.label | c |
| main.rs:148:13:148:13 | [post] m [&ref] | semmle.label | [post] m [&ref] |
| main.rs:148:16:148:25 | source(...) | semmle.label | source(...) |
| main.rs:149:10:149:11 | * ... | semmle.label | * ... |
| main.rs:149:11:149:11 | m [&ref] | semmle.label | m [&ref] |
subpaths
| 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(...) |
| 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(...) |
| 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(...) |
| 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(...) |
| 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] |
testFailures
#select
| 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
| 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(...) |
| 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(...) |
| 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(...) |
| 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(...) |

View File

@@ -134,6 +134,29 @@ pub fn test_operator_overloading() {
sink(d.value); // $ MISSING: hasValueFlow=7
}
// Flow out of mutable parameters.
fn set_int(n: &mut i64, c: i64) {
*n = c;
}
fn mutates_argument_1() {
// Passing an already borrowed value to a function and then reading from the same borrow.
let mut n = 0;
let m = &mut n;
sink(*m);
set_int(m, source(37));
sink(*m); // $ hasValueFlow=37
}
fn mutates_argument_2() {
// Borrowing at the call and then reading from the unborrowed variable.
let mut n = 0;
sink(n);
set_int(&mut n, source(88));
sink(n); // $ MISSING: hasValueFlow=88
}
fn main() {
data_out_of_call();
data_in_to_call();
@@ -145,4 +168,6 @@ fn main() {
data_through_method();
test_operator_overloading();
mutates_argument_1();
mutates_argument_2();
}

View File

@@ -29,11 +29,21 @@
| main.rs:131:28:131:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:133:13:133:20 | a.add(...) | main.rs:114:5:117:5 | fn add |
| main.rs:134:5:134:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:138:5:138:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:139:5:139:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
| main.rs:140:5:140:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
| main.rs:141:5:141:34 | data_through_nested_function(...) | main.rs:48:1:57:1 | fn data_through_nested_function |
| main.rs:143:5:143:24 | data_out_of_method(...) | main.rs:86:1:90:1 | fn data_out_of_method |
| main.rs:144:5:144:28 | data_in_to_method_call(...) | main.rs:92:1:96:1 | fn data_in_to_method_call |
| main.rs:145:5:145:25 | data_through_method(...) | main.rs:98:1:103:1 | fn data_through_method |
| main.rs:147:5:147:31 | test_operator_overloading(...) | main.rs:120:1:135:1 | fn test_operator_overloading |
| main.rs:147:5:147:12 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:148:5:148:26 | set_int(...) | main.rs:139:1:141:1 | fn set_int |
| main.rs:148:16:148:25 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:149:5:149:12 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:155:5:155:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:156:5:156:31 | set_int(...) | main.rs:139:1:141:1 | fn set_int |
| main.rs:156:21:156:30 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:157:5:157:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:161:5:161:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:162:5:162:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
| main.rs:163:5:163:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
| main.rs:164:5:164:34 | data_through_nested_function(...) | main.rs:48:1:57:1 | fn data_through_nested_function |
| main.rs:166:5:166:24 | data_out_of_method(...) | main.rs:86:1:90:1 | fn data_out_of_method |
| main.rs:167:5:167:28 | data_in_to_method_call(...) | main.rs:92:1:96:1 | fn data_in_to_method_call |
| main.rs:168:5:168:25 | data_through_method(...) | main.rs:98:1:103:1 | fn data_through_method |
| main.rs:170:5:170:31 | test_operator_overloading(...) | main.rs:120:1:135:1 | fn test_operator_overloading |
| main.rs:171:5:171:24 | mutates_argument_1(...) | main.rs:143:1:150:1 | fn mutates_argument_1 |
| main.rs:172:5:172:24 | mutates_argument_2(...) | main.rs:152:1:158:1 | fn mutates_argument_2 |

View File

@@ -8,42 +8,45 @@ edges
| main.rs:15:9:15:9 | c | main.rs:16:10:16:10 | c | provenance | |
| main.rs:15:13:15:14 | * ... | main.rs:15:9:15:9 | c | provenance | |
| main.rs:15:14:15:14 | b [&ref] | main.rs:15:13:15:14 | * ... | provenance | |
| main.rs:35:25:35:26 | &... [&ref] | main.rs:35:26:35:26 | n | provenance | |
| main.rs:35:25:35:32 | ...: ... [&ref] | main.rs:35:25:35:26 | &... [&ref] | provenance | |
| main.rs:35:26:35:26 | n | main.rs:36:10:36:10 | n | provenance | |
| main.rs:40:9:40:11 | val | main.rs:41:27:41:29 | val | provenance | |
| main.rs:40:15:40:24 | source(...) | main.rs:40:9:40:11 | val | provenance | |
| main.rs:41:26:41:29 | &val [&ref] | main.rs:35:25:35:32 | ...: ... [&ref] | provenance | |
| main.rs:41:27:41:29 | val | main.rs:41:26:41:29 | &val [&ref] | provenance | |
| main.rs:49:18:49:21 | SelfParam [MyNumber] | main.rs:50:15:50:18 | self [MyNumber] | provenance | |
| main.rs:50:15:50:18 | self [MyNumber] | main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | main.rs:51:32:51:37 | number | provenance | |
| main.rs:51:32:51:37 | number | main.rs:49:31:55:5 | { ... } | provenance | |
| main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | main.rs:58:15:58:18 | self [&ref, MyNumber] | provenance | |
| main.rs:58:15:58:18 | self [&ref, MyNumber] | main.rs:59:13:59:39 | &... [&ref, MyNumber] | provenance | |
| main.rs:59:13:59:39 | &... [&ref, MyNumber] | main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | main.rs:59:33:59:38 | number | provenance | |
| main.rs:59:33:59:38 | number | main.rs:57:33:63:5 | { ... } | provenance | |
| main.rs:67:9:67:17 | my_number [MyNumber] | main.rs:68:10:68:18 | my_number [MyNumber] | provenance | |
| main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | main.rs:67:9:67:17 | my_number [MyNumber] | provenance | |
| main.rs:67:40:67:49 | source(...) | main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:49:18:49:21 | SelfParam [MyNumber] | provenance | |
| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:68:10:68:30 | my_number.to_number(...) | provenance | |
| main.rs:77:9:77:17 | my_number [&ref, MyNumber] | main.rs:78:10:78:18 | my_number [&ref, MyNumber] | provenance | |
| main.rs:77:21:77:51 | &... [&ref, MyNumber] | main.rs:77:9:77:17 | my_number [&ref, MyNumber] | provenance | |
| main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | main.rs:77:21:77:51 | &... [&ref, MyNumber] | provenance | |
| main.rs:77:41:77:50 | source(...) | main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | provenance | |
| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:78:10:78:31 | my_number.get_number(...) | provenance | |
| main.rs:82:9:82:9 | a [&ref, tuple.0] | main.rs:85:19:85:19 | a [&ref, tuple.0] | provenance | |
| main.rs:82:13:82:28 | &... [&ref, tuple.0] | main.rs:82:9:82:9 | a [&ref, tuple.0] | provenance | |
| main.rs:82:14:82:28 | TupleExpr [tuple.0] | main.rs:82:13:82:28 | &... [&ref, tuple.0] | provenance | |
| main.rs:82:15:82:24 | source(...) | main.rs:82:14:82:28 | TupleExpr [tuple.0] | provenance | |
| main.rs:85:9:85:9 | b | main.rs:88:10:88:10 | b | provenance | |
| main.rs:85:19:85:19 | a [&ref, tuple.0] | main.rs:86:9:86:15 | &... [&ref, tuple.0] | provenance | |
| main.rs:86:9:86:15 | &... [&ref, tuple.0] | main.rs:86:10:86:15 | TuplePat [tuple.0] | provenance | |
| main.rs:86:10:86:15 | TuplePat [tuple.0] | main.rs:86:11:86:11 | n | provenance | |
| main.rs:86:11:86:11 | n | main.rs:85:9:85:9 | b | provenance | |
| main.rs:31:6:31:6 | [post] b [&ref] | main.rs:32:11:32:11 | b [&ref] | provenance | |
| main.rs:31:10:31:19 | source(...) | main.rs:31:6:31:6 | [post] b [&ref] | provenance | |
| main.rs:32:11:32:11 | b [&ref] | main.rs:32:10:32:11 | * ... | provenance | |
| main.rs:37:25:37:26 | &... [&ref] | main.rs:37:26:37:26 | n | provenance | |
| main.rs:37:25:37:32 | ...: ... [&ref] | main.rs:37:25:37:26 | &... [&ref] | provenance | |
| main.rs:37:26:37:26 | n | main.rs:38:10:38:10 | n | provenance | |
| main.rs:42:9:42:11 | val | main.rs:43:27:43:29 | val | provenance | |
| main.rs:42:15:42:24 | source(...) | main.rs:42:9:42:11 | val | provenance | |
| main.rs:43:26:43:29 | &val [&ref] | main.rs:37:25:37:32 | ...: ... [&ref] | provenance | |
| main.rs:43:27:43:29 | val | main.rs:43:26:43:29 | &val [&ref] | provenance | |
| main.rs:51:18:51:21 | SelfParam [MyNumber] | main.rs:52:15:52:18 | self [MyNumber] | provenance | |
| main.rs:52:15:52:18 | self [MyNumber] | main.rs:53:13:53:38 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:53:13:53:38 | ...::MyNumber(...) [MyNumber] | main.rs:53:32:53:37 | number | provenance | |
| main.rs:53:32:53:37 | number | main.rs:51:31:57:5 | { ... } | provenance | |
| main.rs:59:19:59:23 | SelfParam [&ref, MyNumber] | main.rs:60:15:60:18 | self [&ref, MyNumber] | provenance | |
| main.rs:60:15:60:18 | self [&ref, MyNumber] | main.rs:61:13:61:39 | &... [&ref, MyNumber] | provenance | |
| main.rs:61:13:61:39 | &... [&ref, MyNumber] | main.rs:61:14:61:39 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:61:14:61:39 | ...::MyNumber(...) [MyNumber] | main.rs:61:33:61:38 | number | provenance | |
| main.rs:61:33:61:38 | number | main.rs:59:33:65:5 | { ... } | provenance | |
| main.rs:69:9:69:17 | my_number [MyNumber] | main.rs:70:10:70:18 | my_number [MyNumber] | provenance | |
| main.rs:69:21:69:50 | ...::MyNumber(...) [MyNumber] | main.rs:69:9:69:17 | my_number [MyNumber] | provenance | |
| main.rs:69:40:69:49 | source(...) | main.rs:69:21:69:50 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:70:10:70:18 | my_number [MyNumber] | main.rs:51:18:51:21 | SelfParam [MyNumber] | provenance | |
| main.rs:70:10:70:18 | my_number [MyNumber] | main.rs:70:10:70:30 | my_number.to_number(...) | provenance | |
| main.rs:79:9:79:17 | my_number [&ref, MyNumber] | main.rs:80:10:80:18 | my_number [&ref, MyNumber] | provenance | |
| main.rs:79:21:79:51 | &... [&ref, MyNumber] | main.rs:79:9:79:17 | my_number [&ref, MyNumber] | provenance | |
| main.rs:79:22:79:51 | ...::MyNumber(...) [MyNumber] | main.rs:79:21:79:51 | &... [&ref, MyNumber] | provenance | |
| main.rs:79:41:79:50 | source(...) | main.rs:79:22:79:51 | ...::MyNumber(...) [MyNumber] | provenance | |
| main.rs:80:10:80:18 | my_number [&ref, MyNumber] | main.rs:59:19:59:23 | SelfParam [&ref, MyNumber] | provenance | |
| main.rs:80:10:80:18 | my_number [&ref, MyNumber] | main.rs:80:10:80:31 | my_number.get_number(...) | provenance | |
| main.rs:84:9:84:9 | a [&ref, tuple.0] | main.rs:87:19:87:19 | a [&ref, tuple.0] | provenance | |
| main.rs:84:13:84:28 | &... [&ref, tuple.0] | main.rs:84:9:84:9 | a [&ref, tuple.0] | provenance | |
| main.rs:84:14:84:28 | TupleExpr [tuple.0] | main.rs:84:13:84:28 | &... [&ref, tuple.0] | provenance | |
| main.rs:84:15:84:24 | source(...) | main.rs:84:14:84:28 | TupleExpr [tuple.0] | provenance | |
| main.rs:87:9:87:9 | b | main.rs:90:10:90:10 | b | provenance | |
| main.rs:87:19:87:19 | a [&ref, tuple.0] | main.rs:88:9:88:15 | &... [&ref, tuple.0] | provenance | |
| main.rs:88:9:88:15 | &... [&ref, tuple.0] | main.rs:88:10:88:15 | TuplePat [tuple.0] | provenance | |
| main.rs:88:10:88:15 | TuplePat [tuple.0] | main.rs:88:11:88:11 | n | provenance | |
| main.rs:88:11:88:11 | n | main.rs:87:9:87:9 | b | provenance | |
nodes
| main.rs:13:9:13:9 | a | semmle.label | a |
| main.rs:13:13:13:22 | source(...) | semmle.label | source(...) |
@@ -54,53 +57,58 @@ nodes
| main.rs:15:13:15:14 | * ... | semmle.label | * ... |
| main.rs:15:14:15:14 | b [&ref] | semmle.label | b [&ref] |
| main.rs:16:10:16:10 | c | semmle.label | c |
| main.rs:35:25:35:26 | &... [&ref] | semmle.label | &... [&ref] |
| main.rs:35:25:35:32 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
| main.rs:35:26:35:26 | n | semmle.label | n |
| main.rs:36:10:36:10 | n | semmle.label | n |
| main.rs:40:9:40:11 | val | semmle.label | val |
| main.rs:40:15:40:24 | source(...) | semmle.label | source(...) |
| main.rs:41:26:41:29 | &val [&ref] | semmle.label | &val [&ref] |
| main.rs:41:27:41:29 | val | semmle.label | val |
| main.rs:49:18:49:21 | SelfParam [MyNumber] | semmle.label | SelfParam [MyNumber] |
| main.rs:49:31:55:5 | { ... } | semmle.label | { ... } |
| main.rs:50:15:50:18 | self [MyNumber] | semmle.label | self [MyNumber] |
| main.rs:51:13:51:38 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:51:32:51:37 | number | semmle.label | number |
| main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | semmle.label | SelfParam [&ref, MyNumber] |
| main.rs:57:33:63:5 | { ... } | semmle.label | { ... } |
| main.rs:58:15:58:18 | self [&ref, MyNumber] | semmle.label | self [&ref, MyNumber] |
| main.rs:59:13:59:39 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] |
| main.rs:59:14:59:39 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:59:33:59:38 | number | semmle.label | number |
| main.rs:67:9:67:17 | my_number [MyNumber] | semmle.label | my_number [MyNumber] |
| main.rs:67:21:67:50 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:67:40:67:49 | source(...) | semmle.label | source(...) |
| main.rs:68:10:68:18 | my_number [MyNumber] | semmle.label | my_number [MyNumber] |
| main.rs:68:10:68:30 | my_number.to_number(...) | semmle.label | my_number.to_number(...) |
| main.rs:77:9:77:17 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] |
| main.rs:77:21:77:51 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] |
| main.rs:77:22:77:51 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:77:41:77:50 | source(...) | semmle.label | source(...) |
| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] |
| main.rs:78:10:78:31 | my_number.get_number(...) | semmle.label | my_number.get_number(...) |
| main.rs:82:9:82:9 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] |
| main.rs:82:13:82:28 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] |
| main.rs:82:14:82:28 | TupleExpr [tuple.0] | semmle.label | TupleExpr [tuple.0] |
| main.rs:82:15:82:24 | source(...) | semmle.label | source(...) |
| main.rs:85:9:85:9 | b | semmle.label | b |
| main.rs:85:19:85:19 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] |
| main.rs:86:9:86:15 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] |
| main.rs:86:10:86:15 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
| main.rs:86:11:86:11 | n | semmle.label | n |
| main.rs:88:10:88:10 | b | semmle.label | b |
| main.rs:31:6:31:6 | [post] b [&ref] | semmle.label | [post] b [&ref] |
| main.rs:31:10:31:19 | source(...) | semmle.label | source(...) |
| main.rs:32:10:32:11 | * ... | semmle.label | * ... |
| main.rs:32:11:32:11 | b [&ref] | semmle.label | b [&ref] |
| main.rs:37:25:37:26 | &... [&ref] | semmle.label | &... [&ref] |
| main.rs:37:25:37:32 | ...: ... [&ref] | semmle.label | ...: ... [&ref] |
| main.rs:37:26:37:26 | n | semmle.label | n |
| main.rs:38:10:38:10 | n | semmle.label | n |
| main.rs:42:9:42:11 | val | semmle.label | val |
| main.rs:42:15:42:24 | source(...) | semmle.label | source(...) |
| main.rs:43:26:43:29 | &val [&ref] | semmle.label | &val [&ref] |
| main.rs:43:27:43:29 | val | semmle.label | val |
| main.rs:51:18:51:21 | SelfParam [MyNumber] | semmle.label | SelfParam [MyNumber] |
| main.rs:51:31:57:5 | { ... } | semmle.label | { ... } |
| main.rs:52:15:52:18 | self [MyNumber] | semmle.label | self [MyNumber] |
| main.rs:53:13:53:38 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:53:32:53:37 | number | semmle.label | number |
| main.rs:59:19:59:23 | SelfParam [&ref, MyNumber] | semmle.label | SelfParam [&ref, MyNumber] |
| main.rs:59:33:65:5 | { ... } | semmle.label | { ... } |
| main.rs:60:15:60:18 | self [&ref, MyNumber] | semmle.label | self [&ref, MyNumber] |
| main.rs:61:13:61:39 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] |
| main.rs:61:14:61:39 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:61:33:61:38 | number | semmle.label | number |
| main.rs:69:9:69:17 | my_number [MyNumber] | semmle.label | my_number [MyNumber] |
| main.rs:69:21:69:50 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:69:40:69:49 | source(...) | semmle.label | source(...) |
| main.rs:70:10:70:18 | my_number [MyNumber] | semmle.label | my_number [MyNumber] |
| main.rs:70:10:70:30 | my_number.to_number(...) | semmle.label | my_number.to_number(...) |
| main.rs:79:9:79:17 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] |
| main.rs:79:21:79:51 | &... [&ref, MyNumber] | semmle.label | &... [&ref, MyNumber] |
| main.rs:79:22:79:51 | ...::MyNumber(...) [MyNumber] | semmle.label | ...::MyNumber(...) [MyNumber] |
| main.rs:79:41:79:50 | source(...) | semmle.label | source(...) |
| main.rs:80:10:80:18 | my_number [&ref, MyNumber] | semmle.label | my_number [&ref, MyNumber] |
| main.rs:80:10:80:31 | my_number.get_number(...) | semmle.label | my_number.get_number(...) |
| main.rs:84:9:84:9 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] |
| main.rs:84:13:84:28 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] |
| main.rs:84:14:84:28 | TupleExpr [tuple.0] | semmle.label | TupleExpr [tuple.0] |
| main.rs:84:15:84:24 | source(...) | semmle.label | source(...) |
| main.rs:87:9:87:9 | b | semmle.label | b |
| main.rs:87:19:87:19 | a [&ref, tuple.0] | semmle.label | a [&ref, tuple.0] |
| main.rs:88:9:88:15 | &... [&ref, tuple.0] | semmle.label | &... [&ref, tuple.0] |
| main.rs:88:10:88:15 | TuplePat [tuple.0] | semmle.label | TuplePat [tuple.0] |
| main.rs:88:11:88:11 | n | semmle.label | n |
| main.rs:90:10:90:10 | b | semmle.label | b |
subpaths
| main.rs:68:10:68:18 | my_number [MyNumber] | main.rs:49:18:49:21 | SelfParam [MyNumber] | main.rs:49:31:55:5 | { ... } | main.rs:68:10:68:30 | my_number.to_number(...) |
| main.rs:78:10:78:18 | my_number [&ref, MyNumber] | main.rs:57:19:57:23 | SelfParam [&ref, MyNumber] | main.rs:57:33:63:5 | { ... } | main.rs:78:10:78:31 | my_number.get_number(...) |
| main.rs:70:10:70:18 | my_number [MyNumber] | main.rs:51:18:51:21 | SelfParam [MyNumber] | main.rs:51:31:57:5 | { ... } | main.rs:70:10:70:30 | my_number.to_number(...) |
| main.rs:80:10:80:18 | my_number [&ref, MyNumber] | main.rs:59:19:59:23 | SelfParam [&ref, MyNumber] | main.rs:59:33:65:5 | { ... } | main.rs:80:10:80:31 | my_number.get_number(...) |
testFailures
#select
| main.rs:16:10:16:10 | c | main.rs:13:13:13:22 | source(...) | main.rs:16:10:16:10 | c | $@ | main.rs:13:13:13:22 | source(...) | source(...) |
| main.rs:36:10:36:10 | n | main.rs:40:15:40:24 | source(...) | main.rs:36:10:36:10 | n | $@ | main.rs:40:15:40:24 | source(...) | source(...) |
| main.rs:68:10:68:30 | my_number.to_number(...) | main.rs:67:40:67:49 | source(...) | main.rs:68:10:68:30 | my_number.to_number(...) | $@ | main.rs:67:40:67:49 | source(...) | source(...) |
| main.rs:78:10:78:31 | my_number.get_number(...) | main.rs:77:41:77:50 | source(...) | main.rs:78:10:78:31 | my_number.get_number(...) | $@ | main.rs:77:41:77:50 | source(...) | source(...) |
| main.rs:88:10:88:10 | b | main.rs:82:15:82:24 | source(...) | main.rs:88:10:88:10 | b | $@ | main.rs:82:15:82:24 | source(...) | source(...) |
| main.rs:32:10:32:11 | * ... | main.rs:31:10:31:19 | source(...) | main.rs:32:10:32:11 | * ... | $@ | main.rs:31:10:31:19 | source(...) | source(...) |
| main.rs:38:10:38:10 | n | main.rs:42:15:42:24 | source(...) | main.rs:38:10:38:10 | n | $@ | main.rs:42:15:42:24 | source(...) | source(...) |
| main.rs:70:10:70:30 | my_number.to_number(...) | main.rs:69:40:69:49 | source(...) | main.rs:70:10:70:30 | my_number.to_number(...) | $@ | main.rs:69:40:69:49 | source(...) | source(...) |
| main.rs:80:10:80:31 | my_number.get_number(...) | main.rs:79:41:79:50 | source(...) | main.rs:80:10:80:31 | my_number.get_number(...) | $@ | main.rs:79:41:79:50 | source(...) | source(...) |
| main.rs:90:10:90:10 | b | main.rs:84:15:84:24 | source(...) | main.rs:90:10:90:10 | b | $@ | main.rs:84:15:84:24 | source(...) | source(...) |

View File

@@ -29,7 +29,9 @@ fn write_and_read_through_borrow() {
let b = &mut a;
sink(*b);
*b = source(37);
sink(*b); // $ MISSING: hasValueFlow=37
sink(*b); // $ hasValueFlow=37
*b = 0;
sink(*b); // now cleared
}
fn takes_borrowed_value(&n: &i64) {

View File

@@ -44,7 +44,9 @@ impl<T> MyOption<T> {
}
}
// summary=repo::test;<crate::option::MyOption>::as_ref;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// NOTE: The returned value inside the variant should be inside a `Reference`, requires handling
// `ref` in patterns.
// summary=repo::test;<crate::option::MyOption>::as_ref;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
pub fn as_ref(&self) -> MyOption<&T> {
match *self {
MySome(ref x) => MySome(x),
@@ -52,7 +54,7 @@ impl<T> MyOption<T> {
}
}
// summary=repo::test;<crate::option::MyOption>::as_mut;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::as_mut;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
pub fn as_mut(&mut self) -> MyOption<&mut T> {
match *self {
MySome(ref mut x) => MySome(x),
@@ -285,8 +287,11 @@ impl<T> MyOption<T> {
}
}
// MISSING: summary=repo::test;<crate::option::MyOption>::insert;Argument[0];ReturnValue;value;dfc-generated
// SPURIOUS-summary=repo::test;<crate::option::MyOption>::insert;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::insert;Argument[0];Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// The below should be `ReturnValue.Reference` and not just `ReturnValue`.
// SPURIOUS-summary=repo::test;<crate::option::MyOption>::insert;Argument[0];ReturnValue;value;dfc-generated
// The content of `self` is overwritten so it does not flow to the return value.
// SPURIOUS-summary=repo::test;<crate::option::MyOption>::insert;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
pub fn insert(&mut self, value: T) -> &mut T {
*self = MySome(value);
@@ -294,13 +299,14 @@ impl<T> MyOption<T> {
unsafe { self.as_mut().unwrap_unchecked() }
}
// summary=repo::test;<crate::option::MyOption>::get_or_insert;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
// MISSING: repo::test;<crate::option::MyOption>::get_or_insert;Argument[0];ReturnValue;value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::get_or_insert;Argument[0];Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::get_or_insert;Argument[0];ReturnValue;value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::get_or_insert;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
pub fn get_or_insert(&mut self, value: T) -> &mut T {
self.get_or_insert_with(|| value)
}
// summary=repo::test;<crate::option::MyOption>::get_or_insert_default;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::get_or_insert_default;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
pub fn get_or_insert_default(&mut self) -> &mut T
where
T: Default,
@@ -308,7 +314,7 @@ impl<T> MyOption<T> {
self.get_or_insert_with(T::default)
}
// summary=repo::test;<crate::option::MyOption>::get_or_insert_with;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::get_or_insert_with;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue;value;dfc-generated
// MISSING: Mutating `self` parameter.
pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
where
@@ -329,7 +335,7 @@ impl<T> MyOption<T> {
mem::replace(self, MyNone)
}
// summary=repo::test;<crate::option::MyOption>::take_if;Argument[self].Variant[crate::option::MyOption::MySome(0)];Argument[0].Parameter[0];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::take_if;Argument[self].Reference.Variant[crate::option::MyOption::MySome(0)];Argument[0].Parameter[0];value;dfc-generated
// MISSING: Uses `take` which doesn't have flow
pub fn take_if<P>(&mut self, predicate: P) -> MyOption<T>
where
@@ -378,7 +384,7 @@ impl<T, U> MyOption<(T, U)> {
}
impl<T> MyOption<&T> {
// summary=repo::test;<crate::option::MyOption>::copied;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::copied;Argument[self].Variant[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
pub fn copied(self) -> MyOption<T>
where
T: Copy,
@@ -404,7 +410,7 @@ impl<T> MyOption<&T> {
}
impl<T> MyOption<&mut T> {
// summary=repo::test;<crate::option::MyOption>::copied;Argument[self].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption>::copied;Argument[self].Variant[crate::option::MyOption::MySome(0)].Reference;ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
pub fn copied(self) -> MyOption<T>
where
T: Copy,
@@ -474,14 +480,14 @@ impl<T> From<T> for MyOption<T> {
}
impl<'a, T> From<&'a MyOption<T>> for MyOption<&'a T> {
// summary=repo::test;<crate::option::MyOption as crate::convert::From>::from;Argument[0].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption as crate::convert::From>::from;Argument[0].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
fn from(o: &'a MyOption<T>) -> MyOption<&'a T> {
o.as_ref()
}
}
impl<'a, T> From<&'a mut MyOption<T>> for MyOption<&'a mut T> {
// summary=repo::test;<crate::option::MyOption as crate::convert::From>::from;Argument[0].Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
// summary=repo::test;<crate::option::MyOption as crate::convert::From>::from;Argument[0].Reference.Variant[crate::option::MyOption::MySome(0)];ReturnValue.Variant[crate::option::MyOption::MySome(0)];value;dfc-generated
fn from(o: &'a mut MyOption<T>) -> MyOption<&'a mut T> {
o.as_mut()
}

View File

@@ -76,3 +76,15 @@ impl MyStruct {
pub fn apply<F>(n: i64, f: F) -> i64 where F : FnOnce(i64) -> i64 {
f(n)
}
// Flow out of mutated arguments
// summary=repo::test;crate::summaries::set_int;Argument[1];Argument[0].Reference;value;dfc-generated
pub fn set_int(n: &mut i64, c: i64) {
*n = c;
}
// summary=repo::test;crate::summaries::read_int;Argument[0].Reference;ReturnValue;value;dfc-generated
pub fn read_int(n: &mut i64) -> i64 {
*n
}