Skip to content

Commit a97937c

Browse files
committed
blanket
1 parent 23f23d4 commit a97937c

File tree

3 files changed

+184
-52
lines changed

3 files changed

+184
-52
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,7 @@ private predicate builtin(string name, ItemNode i) {
18901890

18911891
/** Provides predicates for debugging the path resolution implementation. */
18921892
private module Debug {
1893-
private Locatable getRelevantLocatable() {
1893+
Locatable getRelevantLocatable() {
18941894
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
18951895
result.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
18961896
filepath.matches("%/my3/mod.rs") and

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

Lines changed: 173 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1239,31 +1239,45 @@ private module MethodCallResolution {
12391239
strippedType = selfType.getTypeAt(strippedTypePath) and
12401240
isComplexRootStripped(strippedTypePath, strippedType) and
12411241
selfType.appliesTo(m, pos, i) and
1242-
pos.isSelf() and
1243-
not i.(ImplItemNode).isBlanketImplementation()
1242+
pos.isSelf()
12441243
)
12451244
}
12461245

12471246
pragma[nomagic]
12481247
predicate methodInfoTypeParam(
12491248
Function m, string name, int arity, ImplOrTraitItemNode i, FunctionType selfType,
1250-
TypePath strippedTypePath
1249+
TypePath strippedTypePath, TypeParam tp
12511250
) {
1252-
methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(_))
1251+
methodInfo(m, name, arity, i, selfType, strippedTypePath, TTypeParamTypeParameter(tp))
12531252
}
12541253

12551254
/**
12561255
* Same as `methodInfo`, but allows for any `strippedType` when the
12571256
* corresponding type inside `m` is a type parameter.
12581257
*/
12591258
pragma[inline]
1260-
predicate methodInfoMatch(
1259+
predicate methodInfoNonBlanketMatch(
12611260
Function m, string name, int arity, ImplOrTraitItemNode i, FunctionType selfType,
12621261
TypePath strippedTypePath, Type strippedType
12631262
) {
1264-
methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType)
1265-
or
1266-
methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath)
1263+
(
1264+
methodInfo(m, name, arity, i, selfType, strippedTypePath, strippedType) or
1265+
methodInfoTypeParam(m, name, arity, i, selfType, strippedTypePath, _)
1266+
) and
1267+
not i.(ImplItemNode).isBlanketImplementation()
1268+
}
1269+
1270+
/**
1271+
* Same as `methodInfo`, but allows for any `strippedType` when the
1272+
* corresponding type inside `m` is a type parameter.
1273+
*/
1274+
pragma[nomagic]
1275+
predicate methodInfoBlanketMatch(
1276+
Function m, string name, int arity, ImplItemNode i, FunctionType selfType, TypePath blanketPath,
1277+
TypeParam blanketTypeParam
1278+
) {
1279+
methodInfoTypeParam(m, name, arity, i, selfType, blanketPath, blanketTypeParam) and
1280+
blanketTypeParam = i.getBlanketImplementationTypeParam()
12671281
}
12681282

12691283
pragma[nomagic]
@@ -1278,7 +1292,8 @@ private module MethodCallResolution {
12781292

12791293
pragma[nomagic]
12801294
private predicate methodCallTraitCandidate(Element mc, Trait trait) {
1281-
exists(string name, int arity | mc.(MethodCall).hasNameAndArity(name, arity) |
1295+
exists(string name, int arity |
1296+
mc.(MethodCall).hasNameAndArity(name, arity) and
12821297
methodTraitInfo(name, arity, trait)
12831298
)
12841299
}
@@ -1306,19 +1321,19 @@ private module MethodCallResolution {
13061321
*/
13071322
bindingset[mc, strippedTypePath, strippedType]
13081323
pragma[inline_late]
1309-
private predicate methodCallCandidate(
1310-
MethodCall mc, ImplOrTraitItemNode i, FunctionType self, TypePath strippedTypePath,
1324+
private predicate methodCallNonBlanketCandidate(
1325+
MethodCall mc, Function m, ImplOrTraitItemNode i, FunctionType self, TypePath strippedTypePath,
13111326
Type strippedType
13121327
) {
13131328
exists(string name, int arity |
13141329
mc.hasNameAndArity(name, arity) and
1315-
methodInfoMatch(_, name, arity, i, self, strippedTypePath, strippedType)
1330+
methodInfoNonBlanketMatch(m, name, arity, i, self, strippedTypePath, strippedType)
13161331
|
13171332
i =
13181333
any(Impl impl |
13191334
not impl.hasTrait()
13201335
or
1321-
methodCallVisibleImplTraitCandidate(mc, i)
1336+
methodCallVisibleImplTraitCandidate(mc, impl)
13221337
)
13231338
or
13241339
methodCallVisibleTraitCandidate(mc, i)
@@ -1328,6 +1343,34 @@ private module MethodCallResolution {
13281343
)
13291344
}
13301345

1346+
/**
1347+
* Holds if method call `mc` may target a method in `i` with `self` parameter having
1348+
* type `selfType`.
1349+
*
1350+
* `strippedTypePath` points to the type `strippedType` inside `selfType`,
1351+
* which is the (possibly complex-stripped) root type of `selfType`.
1352+
*
1353+
* This predicate only checks for matching method names and arities, and whether
1354+
* the trait being implemented by `i` (when `i` is not a trait itself) is visible
1355+
* at `mc`.
1356+
*/
1357+
bindingset[mc]
1358+
pragma[inline_late]
1359+
private predicate methodCallBlanketCandidate(
1360+
MethodCall mc, Function m, ImplItemNode i, FunctionType self, TypePath blanketPath,
1361+
TypeParam blanketTypeParam
1362+
) {
1363+
exists(string name, int arity |
1364+
mc.hasNameAndArity(name, arity) and
1365+
methodInfoBlanketMatch(m, name, arity, i, self, blanketPath, blanketTypeParam)
1366+
|
1367+
methodCallVisibleImplTraitCandidate(mc, i)
1368+
or
1369+
mc instanceof IndexExpr and
1370+
i.resolveTraitTy() instanceof IndexTrait
1371+
)
1372+
}
1373+
13311374
/**
13321375
* A method call.
13331376
*
@@ -1408,7 +1451,7 @@ private module MethodCallResolution {
14081451
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
14091452
|
14101453
forall(ImplOrTraitItemNode i |
1411-
methodCallCandidate(this, i, _, strippedTypePath, strippedType)
1454+
methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType)
14121455
|
14131456
this.hasIncompatibleTarget(i, derefChainBorrow)
14141457
)
@@ -1427,7 +1470,7 @@ private module MethodCallResolution {
14271470
strippedType = this.getComplexstrippedType(strippedTypePath, derefChainBorrow)
14281471
|
14291472
forall(ImplOrTraitItemNode i |
1430-
methodCallCandidate(this, i, _, strippedTypePath, strippedType)
1473+
methodCallNonBlanketCandidate(this, _, i, _, strippedTypePath, strippedType)
14311474
|
14321475
this.hasIncompatibleTarget(i, derefChainBorrow)
14331476
)
@@ -1473,7 +1516,9 @@ private module MethodCallResolution {
14731516
*/
14741517
pragma[nomagic]
14751518
Function resolveCallTarget(string derefChainBorrow) {
1476-
result = MkMethodCallCand(this, derefChainBorrow).(MethodCallCand).resolveCallTarget()
1519+
exists(MethodCallCand mcc | mcc = MkMethodCallCand(this, derefChainBorrow) |
1520+
result = mcc.resolveCallTarget()
1521+
)
14771522
}
14781523

14791524
predicate receiverHasImplicitDeref(AstNode receiver) {
@@ -1561,11 +1606,11 @@ private module MethodCallResolution {
15611606
* resolve to a method in an `impl` block for the type of the receiver.
15621607
*/
15631608
pragma[nomagic]
1564-
private predicate hasNoInherentTarget() {
1609+
predicate hasNoInherentTarget() {
15651610
exists(TypePath strippedTypePath, Type strippedType, string name, int arity |
15661611
this.hasInfo(_, strippedTypePath, strippedType, name, arity) and
15671612
forall(Impl i |
1568-
methodInfoMatch(_, name, arity, i, _, strippedTypePath, strippedType) and
1613+
methodInfoNonBlanketMatch(_, name, arity, i, _, strippedTypePath, strippedType) and
15691614
not i.hasTrait()
15701615
|
15711616
this.hasIncompatibleInherentTarget(i)
@@ -1627,6 +1672,88 @@ private module MethodCallResolution {
16271672
Location getLocation() { result = mc_.getLocation() }
16281673
}
16291674

1675+
private newtype TMethodCallCandAndBlanketOffset =
1676+
MkMethodCallCandAndBlanketOffset(MethodCallCand mcc, TypePath blanketPath) {
1677+
exists(MethodCall mc, string name, int arity, TypeParam blanketTypeParam |
1678+
mcc.hasInfo(mc, _, _, name, arity) and
1679+
methodCallBlanketCandidate(mc, _, _, _, blanketPath, blanketTypeParam)
1680+
)
1681+
}
1682+
1683+
private class MethodCallCandAndBlanketOffset extends MkMethodCallCandAndBlanketOffset {
1684+
MethodCallCand mcc_;
1685+
TypePath blanketPath;
1686+
1687+
MethodCallCandAndBlanketOffset() { this = MkMethodCallCandAndBlanketOffset(mcc_, blanketPath) }
1688+
1689+
MethodCallCand getMethodCallCand() { result = mcc_ }
1690+
1691+
TypePath getBlanketPath() { result = blanketPath }
1692+
1693+
Location getLocation() { result = mcc_.getLocation() }
1694+
1695+
Type getTypeAt(TypePath path) { result = mcc_.getTypeAt(blanketPath.appendInverse(path)) }
1696+
1697+
string toString() { result = mcc_.toString() + " (blanket at " + blanketPath.toString() + ")" }
1698+
}
1699+
1700+
private module SatisfiesBlanketConstraintInput implements
1701+
SatisfiesConstraintInputSig<MethodCallCandAndBlanketOffset>
1702+
{
1703+
/**
1704+
* Holds if `impl` is a blanket implementation for a type parameter and
1705+
* `traitBound` is the first non-trivial trait bound of that type parameter.
1706+
*/
1707+
pragma[nomagic]
1708+
private predicate blanketImplementationTraitBound(TypeParamItemNode tp, Trait traitBound) {
1709+
tp = any(ImplItemNode impl).getBlanketImplementationTypeParam() and
1710+
traitBound =
1711+
min(Trait trait, int i |
1712+
trait = tp.resolveBound(i) and
1713+
// Exclude traits that are known to not narrow things down very much.
1714+
not trait.getName().getText() =
1715+
[
1716+
"Sized", "Clone",
1717+
// The auto traits
1718+
"Send", "Sync", "Unpin", "UnwindSafe", "RefUnwindSafe"
1719+
]
1720+
|
1721+
trait order by i
1722+
)
1723+
}
1724+
1725+
pragma[nomagic]
1726+
additional predicate relevantConstraint(
1727+
MethodCallCandAndBlanketOffset mcco, Function m, Trait traitBound
1728+
) {
1729+
exists(
1730+
MethodCallCand mcc, MethodCall mc, string name, int arity, TypePath blanketPath,
1731+
TypeParam blanketTypeParam
1732+
|
1733+
mcco = MkMethodCallCandAndBlanketOffset(mcc, blanketPath) and
1734+
mcc.hasInfo(mc, _, _, name, arity) and
1735+
methodCallBlanketCandidate(mc, m, _, _, blanketPath, blanketTypeParam) and
1736+
blanketImplementationTraitBound(blanketTypeParam, traitBound)
1737+
)
1738+
}
1739+
1740+
pragma[nomagic]
1741+
predicate relevantConstraint(MethodCallCandAndBlanketOffset mcco, Type constraint) {
1742+
relevantConstraint(mcco, _, constraint.(TraitType).getTrait())
1743+
}
1744+
1745+
predicate useUniversalConditions() { none() }
1746+
}
1747+
1748+
private predicate hasBlanketImpl(MethodCallCand mcc, Function f) {
1749+
exists(MethodCallCandAndBlanketOffset mcco, Trait traitBound |
1750+
mcco = MkMethodCallCandAndBlanketOffset(mcc, _) and
1751+
SatisfiesBlanketConstraintInput::relevantConstraint(mcco, f, traitBound) and
1752+
SatisfiesConstraint<MethodCallCandAndBlanketOffset, SatisfiesBlanketConstraintInput>::satisfiesConstraintType(mcco,
1753+
TTrait(traitBound), _, _)
1754+
)
1755+
}
1756+
16301757
/**
16311758
* A configuration for matching the type of a receiver against the type of
16321759
* a `self` parameter.
@@ -1638,9 +1765,16 @@ private module MethodCallResolution {
16381765
predicate potentialInstantiationOf(
16391766
MethodCallCand mcc, TypeAbstraction abs, FunctionType constraint
16401767
) {
1641-
exists(MethodCall mc, string name, int arity, TypePath strippedTypePath, Type strippedType |
1642-
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity) and
1643-
methodCallCandidate(mc, abs, constraint, strippedTypePath, strippedType)
1768+
exists(
1769+
MethodCall mc, Function m, string name, int arity, TypePath strippedTypePath,
1770+
Type strippedType
1771+
|
1772+
mcc.hasInfo(mc, strippedTypePath, strippedType, name, arity)
1773+
|
1774+
methodCallNonBlanketCandidate(mc, m, abs, constraint, strippedTypePath, strippedType)
1775+
or
1776+
methodCallBlanketCandidate(mc, m, abs, constraint, _, _) and
1777+
hasBlanketImpl(mcc, m)
16441778
)
16451779
}
16461780

@@ -1981,20 +2115,23 @@ private module FunctionCallResolution {
19812115
TypePath strippedTypePath, Type strippedType, TraitItemNode trait, Function f,
19822116
Function traitFunction
19832117
) {
1984-
MethodCallResolution::methodInfo(f, _, _, _, _, strippedTypePath, strippedType) and
1985-
traitFunction = trait.getAnAssocItem() and
1986-
(
1987-
f.implements(traitFunction)
1988-
or
1989-
f = traitFunction
2118+
exists(ImplOrTraitItemNode i |
2119+
MethodCallResolution::methodInfo(f, _, _, i, _, strippedTypePath, strippedType) and
2120+
not i.(ImplItemNode).isBlanketImplementation() and
2121+
traitFunction = trait.getAnAssocItem() and
2122+
(
2123+
f.implements(traitFunction)
2124+
or
2125+
f = traitFunction
2126+
)
19902127
)
19912128
}
19922129

19932130
pragma[nomagic]
19942131
private predicate methodInfoTypeParam(
19952132
TypePath strippedTypePath, TraitItemNode trait, Function f, Function traitFunction
19962133
) {
1997-
MethodCallResolution::methodInfoTypeParam(f, _, _, _, _, strippedTypePath) and
2134+
MethodCallResolution::methodInfoTypeParam(f, _, _, _, _, strippedTypePath, _) and
19982135
traitFunction = trait.getAnAssocItem() and
19992136
(
20002137
f.implements(traitFunction)
@@ -2274,13 +2411,15 @@ private module OperationResolution {
22742411
private module OperationIsInstantiationOfInput implements
22752412
IsInstantiationOfInputSig<Op, FunctionType>
22762413
{
2277-
pragma[inline]
2278-
private predicate methodInfoMatch(
2414+
// todo
2415+
bindingset[strippedTypePath]
2416+
private predicate methodInfoNonBlanketMatch(
22792417
TypeAbstraction abs, FunctionType constraint, Trait trait, string name, int arity,
22802418
TypePath strippedTypePath, Type strippedType
22812419
) {
2282-
MethodCallResolution::methodInfoMatch(_, name, arity, abs, constraint, strippedTypePath,
2283-
strippedType) and
2420+
MethodCallResolution::methodInfoNonBlanketMatch(_, name, arity, abs, constraint,
2421+
strippedTypePath, strippedType) and
2422+
not abs.(ImplItemNode).isBlanketImplementation() and
22842423
(
22852424
trait = abs.(ImplItemNode).resolveTraitTy()
22862425
or
@@ -2292,7 +2431,8 @@ private module OperationResolution {
22922431
predicate potentialInstantiationOf(Op op, TypeAbstraction abs, FunctionType constraint) {
22932432
exists(Trait trait, string name, int arity, TypePath strippedTypePath, Type strippedType |
22942433
op.hasInfo(strippedTypePath, strippedType, trait, name, arity) and
2295-
methodInfoMatch(abs, constraint, trait, name, arity, strippedTypePath, strippedType)
2434+
methodInfoNonBlanketMatch(abs, constraint, trait, name, arity, strippedTypePath,
2435+
strippedType)
22962436
)
22972437
}
22982438

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

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ class NonAliasPathTypeMention extends PathTypeMention {
113113

114114
NonAliasPathTypeMention() {
115115
resolved = [resolvePath(this), resolvePath(this).(Variant).getEnum().(TypeItemNode)] and
116-
not exists(resolved.(TypeAlias).getTypeRepr())
116+
not exists(resolved.(TypeAlias).getTypeRepr()) and
117+
not this = any(ImplItemNode i).getASelfPath() // handled by `ImplSelfMention`
117118
}
118119

119120
TypeItemNode getResolved() { result = resolved }
@@ -145,23 +146,6 @@ class NonAliasPathTypeMention extends PathTypeMention {
145146
private TypeMention getPositionalTypeArgument0(int i) {
146147
result = this.getSegment().getGenericArgList().getTypeArg(i)
147148
or
148-
// `Self` paths inside `impl` blocks have implicit type arguments that are
149-
// the type parameters of the `impl` block. For example, in
150-
//
151-
// ```rust
152-
// impl<T> Foo<T> {
153-
// fn m(self) -> Self {
154-
// self
155-
// }
156-
// }
157-
// ```
158-
//
159-
// the `Self` return type is shorthand for `Foo<T>`.
160-
exists(ImplItemNode node |
161-
this = node.getASelfPath() and
162-
result = node.(ImplItemNode).getSelfPath().getSegment().getGenericArgList().getTypeArg(i)
163-
)
164-
or
165149
// `Option::<i32>::Some` is valid in addition to `Option::Some::<i32>`
166150
resolvePath(this) instanceof Variant and
167151
result = this.getQualifier().getSegment().getGenericArgList().getTypeArg(i)
@@ -260,6 +244,14 @@ class NonAliasPathTypeMention extends PathTypeMention {
260244
}
261245
}
262246

247+
class ImplSelfMention extends PathTypeMention {
248+
private ImplItemNode impl;
249+
250+
ImplSelfMention() { this = impl.getASelfPath() }
251+
252+
override Type resolveTypeAt(TypePath typePath) { result = resolveImplSelfType(impl, typePath) }
253+
}
254+
263255
class PathTypeReprMention extends TypeMention, PathTypeRepr {
264256
private PathTypeMention path;
265257

0 commit comments

Comments
 (0)