Skip to content

Commit 0e3907b

Browse files
authored
Merge pull request #19035 from hvitved/rust/type-inference-path-limit
Rust: Limit `TypePath`s to at most length 10
2 parents 43a03de + dfc3927 commit 0e3907b

File tree

5 files changed

+78
-1
lines changed

5 files changed

+78
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
extractionWarning
2+
| loop/main.rs:1:1:1:1 | semantic analyzer unavailable (not included as a module) |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// The code in this file is not valid Rust code, but it is used to test that
2+
// our type inference implementation does not run into an infinite loop.
3+
4+
struct S<T>(T);
5+
6+
trait T1<T>: T2<S<T>> {
7+
fn foo(self) {}
8+
}
9+
10+
trait T2<T>: T1<S<T>> {
11+
fn bar(self) {
12+
self.foo()
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
qltest_cargo_check: false

rust/ql/test/library-tests/type-inference/type-inference.expected

+39
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,42 @@
11
inferType
2+
| loop/main.rs:7:12:7:15 | SelfParam | | loop/main.rs:6:1:8:1 | trait T1 |
3+
| loop/main.rs:7:12:7:15 | SelfParam | T | loop/main.rs:6:10:6:10 | T |
4+
| loop/main.rs:11:12:11:15 | SelfParam | | loop/main.rs:6:1:8:1 | trait T1 |
5+
| loop/main.rs:11:12:11:15 | SelfParam | | loop/main.rs:10:1:14:1 | trait T2 |
6+
| loop/main.rs:11:12:11:15 | SelfParam | T | loop/main.rs:4:1:4:15 | struct S |
7+
| loop/main.rs:11:12:11:15 | SelfParam | T | loop/main.rs:10:10:10:10 | T |
8+
| loop/main.rs:11:12:11:15 | SelfParam | T.T | loop/main.rs:4:1:4:15 | struct S |
9+
| loop/main.rs:11:12:11:15 | SelfParam | T.T | loop/main.rs:10:10:10:10 | T |
10+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T | loop/main.rs:4:1:4:15 | struct S |
11+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
12+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T | loop/main.rs:10:10:10:10 | T |
13+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
14+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
15+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
16+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
17+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
18+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
19+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
20+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
21+
| loop/main.rs:11:12:11:15 | SelfParam | T.T.T.T.T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
22+
| loop/main.rs:12:9:12:12 | self | | loop/main.rs:6:1:8:1 | trait T1 |
23+
| loop/main.rs:12:9:12:12 | self | | loop/main.rs:10:1:14:1 | trait T2 |
24+
| loop/main.rs:12:9:12:12 | self | T | loop/main.rs:4:1:4:15 | struct S |
25+
| loop/main.rs:12:9:12:12 | self | T | loop/main.rs:10:10:10:10 | T |
26+
| loop/main.rs:12:9:12:12 | self | T.T | loop/main.rs:4:1:4:15 | struct S |
27+
| loop/main.rs:12:9:12:12 | self | T.T | loop/main.rs:10:10:10:10 | T |
28+
| loop/main.rs:12:9:12:12 | self | T.T.T | loop/main.rs:4:1:4:15 | struct S |
29+
| loop/main.rs:12:9:12:12 | self | T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
30+
| loop/main.rs:12:9:12:12 | self | T.T.T.T | loop/main.rs:10:10:10:10 | T |
31+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
32+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
33+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
34+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
35+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
36+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
37+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
38+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T.T.T.T | loop/main.rs:4:1:4:15 | struct S |
39+
| loop/main.rs:12:9:12:12 | self | T.T.T.T.T.T.T.T.T.T | loop/main.rs:10:10:10:10 | T |
240
| main.rs:5:19:5:22 | SelfParam | | main.rs:2:5:2:21 | struct Foo |
341
| main.rs:5:33:7:9 | { ... } | | main.rs:2:5:2:21 | struct Foo |
442
| main.rs:6:13:6:16 | self | | main.rs:2:5:2:21 | struct Foo |
@@ -783,6 +821,7 @@ inferType
783821
| main.rs:582:11:582:20 | ...::Foo {...} | | main.rs:2:5:2:21 | struct Foo |
784822
| main.rs:582:23:582:32 | ...::Foo {...} | | main.rs:2:5:2:21 | struct Foo |
785823
resolveMethodCallExpr
824+
| loop/main.rs:12:9:12:18 | self.foo(...) | loop/main.rs:7:5:7:19 | fn foo |
786825
| main.rs:23:9:23:14 | x.m1(...) | main.rs:5:9:7:9 | fn m1 |
787826
| main.rs:24:9:24:14 | y.m2(...) | main.rs:9:9:11:9 | fn m2 |
788827
| main.rs:67:26:67:31 | x.m2(...) | main.rs:52:9:54:9 | fn m2 |

shared/typeinference/codeql/typeinference/internal/TypeInference.qll

+22-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ signature module InputSig1<LocationSig Location> {
6868
predicate typeArgumentParameterPositionMatch(
6969
TypeArgumentPosition tapos, TypeParameterPosition tppos
7070
);
71+
72+
/**
73+
* Gets the limit on the length of type paths. Set to `none()` if there should
74+
* be no limit.
75+
*
76+
* Having a limit can be useful to avoid inifinite recursion on malformed
77+
* programs.
78+
*/
79+
default int getTypePathLimit() { result = 10 }
7180
}
7281

7382
module Make1<LocationSig Location, InputSig1<Location> Input1> {
@@ -143,6 +152,15 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
143152
/** Holds if this type path is empty. */
144153
predicate isEmpty() { this = "" }
145154

155+
/** Gets the length of this path. */
156+
bindingset[this]
157+
pragma[inline_late]
158+
int length() {
159+
this.isEmpty() and result = 0
160+
or
161+
result = strictcount(this.indexOf(".")) + 1
162+
}
163+
146164
/** Gets the path obtained by appending `suffix` onto this path. */
147165
bindingset[suffix, result]
148166
bindingset[this, result]
@@ -153,7 +171,10 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
153171
else
154172
if suffix.isEmpty()
155173
then result = this
156-
else result = this + "." + suffix
174+
else (
175+
result = this + "." + suffix and
176+
not result.length() > getTypePathLimit()
177+
)
157178
}
158179

159180
/** Holds if this path starts with `tp`, followed by `suffix`. */

0 commit comments

Comments
 (0)