Skip to content

Commit c4d46f2

Browse files
committed
Rust: Fix type inference for library parameters
The old logic relied on parameters having a pattern, which is not the case for parameters extracted from library code.
1 parent 8fe2699 commit c4d46f2

File tree

4 files changed

+55
-69
lines changed

4 files changed

+55
-69
lines changed

rust/ql/lib/codeql/rust/internal/TypeInference.qll

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
569569
exists(Param p, int i, boolean inMethod |
570570
paramPos(this.getParamList(), p, i, inMethod) and
571571
dpos = TPositionalDeclarationPosition(i, inMethod) and
572-
result = inferAnnotatedType(p.getPat(), path)
572+
result = p.getTypeRepr().(TypeMention).resolveTypeAt(path)
573573
)
574574
or
575575
exists(SelfParam self |
@@ -676,9 +676,9 @@ private module CallExprBaseMatchingInput implements MatchingInputSig {
676676
}
677677

678678
override AstNode getNodeAt(AccessPosition apos) {
679-
result = super.getOperand(0) and apos = TSelfAccessPosition()
679+
result = super.getOperand(0) and apos = TPositionalAccessPosition(0, false)
680680
or
681-
result = super.getOperand(1) and apos = TPositionalAccessPosition(0, true)
681+
result = super.getOperand(1) and apos = TPositionalAccessPosition(1, false)
682682
or
683683
result = this and apos = TReturnAccessPosition()
684684
}
@@ -774,7 +774,15 @@ private Type inferCallExprBaseType(AstNode n, TypePath path) {
774774
TypePath path0
775775
|
776776
n = a.getNodeAt(apos) and
777-
result = CallExprBaseMatching::inferAccessType(a, apos, path0)
777+
result = CallExprBaseMatching::inferAccessType(a, apos, path0) and
778+
// Many operators are heavily overloaded, for example `i32` implements
779+
// both `Add` and `Add<Rhs = &i32>`, so we avoid propagating type
780+
// information back into operands, as otherwise e.g. `2` in `1 + 2` would
781+
// also have inferred type `&i32`.
782+
//
783+
// A more principled solution would be to only resolve the correct method,
784+
// based on the type of the right operand as well.
785+
if a instanceof Operation then apos.isReturn() else any()
778786
|
779787
if apos.isSelf()
780788
then
@@ -1363,7 +1371,7 @@ private module Debug {
13631371
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
13641372
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
13651373
filepath.matches("%/main.rs") and
1366-
startline = 948
1374+
startline = 1248
13671375
)
13681376
}
13691377

@@ -1372,8 +1380,8 @@ private module Debug {
13721380
result = inferType(n, path)
13731381
}
13741382

1375-
Function debugResolveMethodCallExpr(MethodCallExpr mce) {
1376-
mce = getRelevantLocatable() and
1377-
result = resolveMethodCallTarget(mce)
1383+
Function debugResolveMethodCallExpr(MethodCall mc) {
1384+
mc = getRelevantLocatable() and
1385+
result = resolveMethodCallTarget(mc)
13781386
}
13791387
}

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ models
66
| 5 | Summary: lang:core; <crate::option::Option>::unwrap; Argument[self].Field[crate::option::Option::Some(0)]; ReturnValue; value |
77
| 6 | Summary: lang:core; <crate::option::Option>::zip; Argument[0].Field[crate::option::Option::Some(0)]; ReturnValue.Field[crate::option::Option::Some(0)].Field[1]; value |
88
| 7 | Summary: lang:core; <crate::pin::Pin>::into_inner; Argument[0]; ReturnValue; value |
9-
| 8 | Summary: lang:core; <crate::pin::Pin>::new; Argument[0]; ReturnValue; value |
10-
| 9 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
11-
| 10 | Summary: lang:core; <i64 as crate::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
12-
| 11 | Summary: lang:core; crate::ptr::read; Argument[0].Reference; ReturnValue; value |
13-
| 12 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value |
9+
| 8 | Summary: lang:core; <crate::pin::Pin>::into_inner_unchecked; Argument[0]; ReturnValue; value |
10+
| 9 | Summary: lang:core; <crate::pin::Pin>::new; Argument[0]; ReturnValue; value |
11+
| 10 | Summary: lang:core; <crate::pin::Pin>::new_unchecked; Argument[0].Reference; ReturnValue; value |
12+
| 11 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Field[crate::result::Result::Ok(0)]; ReturnValue; value |
13+
| 12 | Summary: lang:core; <i64 as crate::clone::Clone>::clone; Argument[self].Reference; ReturnValue; value |
14+
| 13 | Summary: lang:core; crate::ptr::read; Argument[0].Reference; ReturnValue; value |
15+
| 14 | Summary: lang:core; crate::ptr::write; Argument[1]; Argument[0].Reference; value |
1416
edges
1517
| main.rs:12:9:12:9 | a [Some] | main.rs:13:10:13:19 | a.unwrap() | provenance | MaD:5 |
1618
| main.rs:12:9:12:9 | a [Some] | main.rs:14:13:14:13 | a [Some] | provenance | |
@@ -20,18 +22,18 @@ edges
2022
| main.rs:14:9:14:9 | b [Some] | main.rs:15:10:15:19 | b.unwrap() | provenance | MaD:5 |
2123
| main.rs:14:13:14:13 | a [Some] | main.rs:14:13:14:21 | a.clone() [Some] | provenance | generated |
2224
| main.rs:14:13:14:21 | a.clone() [Some] | main.rs:14:9:14:9 | b [Some] | provenance | |
23-
| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:9 |
25+
| main.rs:19:9:19:9 | a [Ok] | main.rs:20:10:20:19 | a.unwrap() | provenance | MaD:11 |
2426
| main.rs:19:9:19:9 | a [Ok] | main.rs:21:13:21:13 | a [Ok] | provenance | |
2527
| main.rs:19:31:19:44 | Ok(...) [Ok] | main.rs:19:9:19:9 | a [Ok] | provenance | |
2628
| main.rs:19:34:19:43 | source(...) | main.rs:19:31:19:44 | Ok(...) [Ok] | provenance | |
27-
| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:9 |
29+
| main.rs:21:9:21:9 | b [Ok] | main.rs:22:10:22:19 | b.unwrap() | provenance | MaD:11 |
2830
| main.rs:21:13:21:13 | a [Ok] | main.rs:21:13:21:21 | a.clone() [Ok] | provenance | generated |
2931
| main.rs:21:13:21:21 | a.clone() [Ok] | main.rs:21:9:21:9 | b [Ok] | provenance | |
3032
| main.rs:26:9:26:9 | a | main.rs:27:10:27:10 | a | provenance | |
3133
| main.rs:26:9:26:9 | a | main.rs:28:13:28:13 | a | provenance | |
3234
| main.rs:26:13:26:22 | source(...) | main.rs:26:9:26:9 | a | provenance | |
3335
| main.rs:28:9:28:9 | b | main.rs:29:10:29:10 | b | provenance | |
34-
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | MaD:10 |
36+
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | MaD:12 |
3537
| main.rs:28:13:28:13 | a | main.rs:28:13:28:21 | a.clone() | provenance | generated |
3638
| main.rs:28:13:28:21 | a.clone() | main.rs:28:9:28:9 | b | provenance | |
3739
| main.rs:43:18:43:22 | SelfParam [Wrapper] | main.rs:44:26:44:29 | self [Wrapper] | provenance | |
@@ -64,8 +66,8 @@ edges
6466
| main.rs:69:18:69:23 | TuplePat [tuple.1] | main.rs:69:22:69:22 | m | provenance | |
6567
| main.rs:69:22:69:22 | m | main.rs:71:22:71:22 | m | provenance | |
6668
| main.rs:92:29:92:29 | [post] y [&ref] | main.rs:93:33:93:33 | y [&ref] | provenance | |
67-
| main.rs:92:32:92:41 | source(...) | main.rs:92:29:92:29 | [post] y [&ref] | provenance | MaD:12 |
68-
| main.rs:93:33:93:33 | y [&ref] | main.rs:93:18:93:34 | ...::read(...) | provenance | MaD:11 |
69+
| main.rs:92:32:92:41 | source(...) | main.rs:92:29:92:29 | [post] y [&ref] | provenance | MaD:14 |
70+
| main.rs:93:33:93:33 | y [&ref] | main.rs:93:18:93:34 | ...::read(...) | provenance | MaD:13 |
6971
| main.rs:108:13:108:17 | mut i | main.rs:109:34:109:34 | i | provenance | |
7072
| main.rs:108:13:108:17 | mut i | main.rs:110:33:110:33 | i | provenance | |
7173
| main.rs:108:13:108:17 | mut i | main.rs:111:47:111:47 | i | provenance | |
@@ -74,7 +76,7 @@ edges
7476
| main.rs:109:13:109:20 | mut pin1 [&ref] | main.rs:114:15:114:18 | pin1 [&ref] | provenance | |
7577
| main.rs:109:13:109:20 | mut pin1 [&ref] | main.rs:115:31:115:34 | pin1 [&ref] | provenance | |
7678
| main.rs:109:24:109:35 | ...::new(...) [&ref] | main.rs:109:13:109:20 | mut pin1 [&ref] | provenance | |
77-
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [&ref] | provenance | MaD:8 |
79+
| main.rs:109:33:109:34 | &i [&ref] | main.rs:109:24:109:35 | ...::new(...) [&ref] | provenance | MaD:9 |
7880
| main.rs:109:34:109:34 | i | main.rs:109:33:109:34 | &i [&ref] | provenance | |
7981
| main.rs:110:13:110:20 | mut pin2 [&ref] | main.rs:116:15:116:18 | pin2 [&ref] | provenance | |
8082
| main.rs:110:24:110:34 | ...::pin(...) [&ref] | main.rs:110:13:110:20 | mut pin2 [&ref] | provenance | |
@@ -92,6 +94,15 @@ edges
9294
| main.rs:122:22:122:49 | MyStruct {...} [MyStruct] | main.rs:122:13:122:18 | mut ms [MyStruct] | provenance | |
9395
| main.rs:122:38:122:47 | source(...) | main.rs:122:22:122:49 | MyStruct {...} [MyStruct] | provenance | |
9496
| main.rs:127:14:127:15 | ms [MyStruct] | main.rs:127:14:127:19 | ms.val | provenance | |
97+
| main.rs:136:13:136:18 | mut ms [MyStruct] | main.rs:137:44:137:45 | ms [MyStruct] | provenance | |
98+
| main.rs:136:22:136:49 | MyStruct {...} [MyStruct] | main.rs:136:13:136:18 | mut ms [MyStruct] | provenance | |
99+
| main.rs:136:38:136:47 | source(...) | main.rs:136:22:136:49 | MyStruct {...} [MyStruct] | provenance | |
100+
| main.rs:137:13:137:20 | mut pin5 [MyStruct] | main.rs:139:40:139:43 | pin5 [MyStruct] | provenance | |
101+
| main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | main.rs:137:13:137:20 | mut pin5 [MyStruct] | provenance | |
102+
| main.rs:137:43:137:45 | &ms [&ref, MyStruct] | main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | provenance | MaD:10 |
103+
| main.rs:137:44:137:45 | ms [MyStruct] | main.rs:137:43:137:45 | &ms [&ref, MyStruct] | provenance | |
104+
| main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | main.rs:139:14:139:48 | ... .val | provenance | |
105+
| main.rs:139:40:139:43 | pin5 [MyStruct] | main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | provenance | MaD:8 |
95106
nodes
96107
| main.rs:12:9:12:9 | a [Some] | semmle.label | a [Some] |
97108
| main.rs:12:13:12:28 | Some(...) [Some] | semmle.label | Some(...) [Some] |
@@ -178,6 +189,16 @@ nodes
178189
| main.rs:122:38:122:47 | source(...) | semmle.label | source(...) |
179190
| main.rs:127:14:127:15 | ms [MyStruct] | semmle.label | ms [MyStruct] |
180191
| main.rs:127:14:127:19 | ms.val | semmle.label | ms.val |
192+
| main.rs:136:13:136:18 | mut ms [MyStruct] | semmle.label | mut ms [MyStruct] |
193+
| main.rs:136:22:136:49 | MyStruct {...} [MyStruct] | semmle.label | MyStruct {...} [MyStruct] |
194+
| main.rs:136:38:136:47 | source(...) | semmle.label | source(...) |
195+
| main.rs:137:13:137:20 | mut pin5 [MyStruct] | semmle.label | mut pin5 [MyStruct] |
196+
| main.rs:137:24:137:46 | ...::new_unchecked(...) [MyStruct] | semmle.label | ...::new_unchecked(...) [MyStruct] |
197+
| main.rs:137:43:137:45 | &ms [&ref, MyStruct] | semmle.label | &ms [&ref, MyStruct] |
198+
| main.rs:137:44:137:45 | ms [MyStruct] | semmle.label | ms [MyStruct] |
199+
| main.rs:139:14:139:44 | ...::into_inner_unchecked(...) [MyStruct] | semmle.label | ...::into_inner_unchecked(...) [MyStruct] |
200+
| main.rs:139:14:139:48 | ... .val | semmle.label | ... .val |
201+
| main.rs:139:40:139:43 | pin5 [MyStruct] | semmle.label | pin5 [MyStruct] |
181202
subpaths
182203
| main.rs:50:15:50:15 | w [Wrapper] | main.rs:43:18:43:22 | SelfParam [Wrapper] | main.rs:43:33:45:9 | { ... } [Wrapper] | main.rs:53:17:53:25 | w.clone() [Wrapper] |
183204
testFailures
@@ -198,3 +219,4 @@ testFailures
198219
| main.rs:116:14:116:18 | * ... | main.rs:108:21:108:30 | source(...) | main.rs:116:14:116:18 | * ... | $@ | main.rs:108:21:108:30 | source(...) | source(...) |
199220
| main.rs:117:14:117:18 | * ... | main.rs:108:21:108:30 | source(...) | main.rs:117:14:117:18 | * ... | $@ | main.rs:108:21:108:30 | source(...) | source(...) |
200221
| main.rs:127:14:127:19 | ms.val | main.rs:122:38:122:47 | source(...) | main.rs:127:14:127:19 | ms.val | $@ | main.rs:122:38:122:47 | source(...) | source(...) |
222+
| main.rs:139:14:139:48 | ... .val | main.rs:136:38:136:47 | source(...) | main.rs:139:14:139:48 | ... .val | $@ | main.rs:136:38:136:47 | source(...) | source(...) |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ mod ptr {
9595
}
9696
}
9797

98-
use std::pin::Pin;
9998
use std::pin::pin;
99+
use std::pin::Pin;
100100

101101
#[derive(Clone)]
102102
struct MyStruct {
@@ -136,7 +136,7 @@ fn test_pin() {
136136
let mut ms = MyStruct { val: source(42) };
137137
let mut pin5 = Pin::new_unchecked(&ms);
138138
sink(pin5.val); // $ MISSING: hasValueFlow=42
139-
sink(Pin::into_inner_unchecked(pin5).val); // $ MISSING: hasValueFlow=42
139+
sink(Pin::into_inner_unchecked(pin5).val); // $ hasValueFlow=42
140140
}
141141

142142
{

0 commit comments

Comments
 (0)