Skip to content

Commit 9c37acc

Browse files
committed
Rust: Fix context-based type inference explosion
1 parent 793d2c7 commit 9c37acc

File tree

4 files changed

+39
-17
lines changed

4 files changed

+39
-17
lines changed

rust/ql/lib/codeql/rust/internal/typeinference/FunctionOverloading.qll

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,8 @@ predicate traitTypeParameterOccurrence(
9595
tp = trait.(TraitTypeAbstraction).getATypeParameter()
9696
}
9797

98-
/**
99-
* Holds if resolving the function `f` in `impl` with the name `functionName`
100-
* requires inspecting the type of applied _arguments_ at position `pos` in
101-
* order to determine whether it is the correct resolution.
102-
*/
10398
pragma[nomagic]
104-
predicate functionResolutionDependsOnArgument(
99+
private predicate functionResolutionDependsOnArgument0(
105100
ImplItemNode impl, Function f, FunctionPosition pos, TypePath path, Type type
106101
) {
107102
/*
@@ -133,7 +128,32 @@ predicate functionResolutionDependsOnArgument(
133128
implHasSibling(impl, trait) and
134129
traitTypeParameterOccurrence(trait, _, functionName, pos, path, _) and
135130
type = getAssocFunctionTypeAt(f, impl, pos, path) and
136-
f = impl.getASuccessor(functionName) and
131+
f = impl.getASuccessor(functionName)
132+
)
133+
}
134+
135+
/**
136+
* Holds if resolving the function `f` in `impl` requires inspecting the type
137+
* of applied _arguments_ at position `pos` (including the return type) in
138+
* order to determine whether it is the correct resolution.
139+
*/
140+
pragma[nomagic]
141+
predicate functionResolutionDependsOnArgument(
142+
ImplItemNode impl, Function f, FunctionPosition pos, TypePath path, Type type
143+
) {
144+
functionResolutionDependsOnArgument0(impl, f, pos, path, type) and
145+
(
137146
pos.isPosition()
147+
or
148+
// Only disambiguate based on return type when all other positions are trivially
149+
// satisfied for all arguments.
150+
pos.isReturn() and
151+
forall(FunctionPosition pos0, TypePath path0, Type type0 |
152+
pos0.isPosition() and
153+
functionResolutionDependsOnArgument0(impl, f, pos0, path0, type0)
154+
|
155+
path0.isEmpty() and
156+
type0.(TypeParamTypeParameter).getTypeParam() = any(TypeParam tp | not tp.hasTypeBound())
157+
)
138158
)
139159
}

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,13 +1172,13 @@ private module ContextTyping {
11721172
*/
11731173
module CheckContextTyping<inferCallTypeSig/3 inferCallType> {
11741174
pragma[nomagic]
1175-
private Type inferCallTypeFromContextCand(AstNode n, TypePath path, TypePath prefix) {
1175+
private Type inferCallTypeFromContextCand(AstNode n, TypePath prefix, TypePath path) {
11761176
result = inferCallType(n, false, path) and
11771177
hasUnknownType(n) and
11781178
prefix = path
11791179
or
11801180
exists(TypePath mid |
1181-
result = inferCallTypeFromContextCand(n, path, mid) and
1181+
result = inferCallTypeFromContextCand(n, mid, path) and
11821182
mid.isSnoc(prefix, _)
11831183
)
11841184
}
@@ -1188,7 +1188,7 @@ private module ContextTyping {
11881188
result = inferCallType(n, true, path)
11891189
or
11901190
exists(TypePath prefix |
1191-
result = inferCallTypeFromContextCand(n, path, prefix) and
1191+
result = inferCallTypeFromContextCand(n, prefix, path) and
11921192
hasUnknownTypeAt(n, prefix)
11931193
)
11941194
}
@@ -2669,9 +2669,8 @@ private module NonMethodResolution {
26692669
then
26702670
// We only check that the context of the call provides relevant type information
26712671
// when no argument can
2672-
not exists(FunctionPosition pos0 |
2673-
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos0, _, _) and
2674-
not pos0.isReturn()
2672+
not exists(FunctionPosition pos0 | not pos0.isReturn() |
2673+
FunctionOverloading::traitTypeParameterOccurrence(trait, traitFunction, _, pos0, _, _)
26752674
or
26762675
FunctionOverloading::functionResolutionDependsOnArgument(impl, implFunction, pos0, _, _)
26772676
)
@@ -2837,7 +2836,7 @@ private module NonMethodResolution {
28372836
NonMethodFunction resolveTraitFunctionViaPathResolution(TraitItemNode trait) {
28382837
this.hasTrait() and
28392838
result = this.getPathResolutionResolved() and
2840-
result = trait.getASuccessor(_)
2839+
result = trait.getAnAssocItem()
28412840
}
28422841
}
28432842

rust/ql/test/query-tests/security/CWE-312/CONSISTENCY/PathResolutionConsistency.expected

Lines changed: 0 additions & 2 deletions
This file was deleted.

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,11 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
980980
not t = abs.getATypeParameter()
981981
}
982982

983+
pragma[nomagic]
984+
private predicate hasTypeConstraint(HasTypeTree term, Type constraint) {
985+
hasTypeConstraint(term, constraint, constraint)
986+
}
987+
983988
/**
984989
* Holds if the type tree at `tt` satisfies the constraint `constraint`
985990
* with the type `t` at `path`.
@@ -994,7 +999,7 @@ module Make1<LocationSig Location, InputSig1<Location> Input1> {
994999
path = prefix0.append(suffix)
9951000
)
9961001
or
997-
hasTypeConstraint(tt, constraint, constraint) and
1002+
hasTypeConstraint(tt, constraint) and
9981003
t = getTypeAt(tt, path)
9991004
}
10001005

0 commit comments

Comments
 (0)