Skip to content

Commit 6fa9048

Browse files
committed
WIP
1 parent 37b508b commit 6fa9048

File tree

4 files changed

+535
-4
lines changed

4 files changed

+535
-4
lines changed

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -933,15 +933,38 @@ class TypeParamItemNode extends TypeItemNode instanceof TypeParam {
933933
}
934934

935935
pragma[nomagic]
936-
Path getABoundPath() {
937-
exists(TypeBoundList tbl | result = tbl.getABound().getTypeRepr().(PathTypeRepr).getPath() |
938-
tbl = super.getTypeBoundList()
936+
TypeBound getBound(int index) {
937+
result = super.getTypeBoundList().getBound(index)
938+
or
939+
exists(int offset |
940+
offset = super.getTypeBoundList().getNumberOfBounds()
939941
or
940-
tbl = this.getAWherePred().getTypeBoundList()
942+
not super.hasTypeBoundList() and
943+
offset = 0
944+
|
945+
result = this.getAWherePred().getTypeBoundList().getBound(index - offset)
941946
)
942947
}
943948

944949
pragma[nomagic]
950+
Path getBoundPath(int index) {
951+
result = this.getBound(index).getTypeRepr().(PathTypeRepr).getPath()
952+
}
953+
954+
Path getABoundPath() { result = this.getBoundPath(_) }
955+
956+
pragma[nomagic]
957+
ItemNode resolveBound(int index) {
958+
result =
959+
rank[index + 1](int i, ItemNode item |
960+
item = resolvePath(this.getBoundPath(i))
961+
|
962+
item order by i
963+
)
964+
}
965+
966+
private predicate noFirst2() { not exists(this.resolveBound(0)) and exists(this.resolveBound(1)) }
967+
945968
ItemNode resolveABound() { result = resolvePath(this.getABoundPath()) }
946969

947970
/**

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

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1512,6 +1512,10 @@ private predicate methodCandidateTrait(Type type, Trait trait, string name, int
15121512
methodCandidate(type, name, arity, impl)
15131513
}
15141514

1515+
/**
1516+
* Holds if `mc` has `rootType` as the root type of the reciever and the target
1517+
* method is named `name` and has arity `arity`
1518+
*/
15151519
pragma[nomagic]
15161520
private predicate isMethodCall(MethodCall mc, Type rootType, string name, int arity) {
15171521
rootType = mc.getTypeAt(TypePath::nil()) and
@@ -1710,6 +1714,91 @@ private predicate methodCallHasImplCandidate(MethodCall mc, Impl impl) {
17101714
else any()
17111715
}
17121716

1717+
private module BlanketImplementation {
1718+
/**
1719+
* Holds if `impl` is a blanket implementation, that is, an implementation of a
1720+
* trait for a type parameter.
1721+
*/
1722+
private TypeParamItemNode getBlanketImplementationTypeParam(Impl impl) {
1723+
result = impl.(ImplItemNode).resolveSelfTy() and
1724+
result = impl.getGenericParamList().getAGenericParam() and
1725+
not exists(impl.getAttributeMacroExpansion())
1726+
}
1727+
1728+
/**
1729+
* Holds if `impl` is a blanket implementation for a type parameter and the type
1730+
* parameter must implement `trait`.
1731+
*/
1732+
private predicate blanketImplementationTraitBound(Impl impl, Trait t) {
1733+
t =
1734+
rank[1](Trait trait, int i |
1735+
trait = getBlanketImplementationTypeParam(impl).resolveBound(i) and
1736+
not trait.getName().getText() = ["Sized", "Fn", "FnOnce", "FnMut"]
1737+
|
1738+
trait order by i
1739+
)
1740+
}
1741+
1742+
private predicate blanketImplementationWithoutBound(Impl impl) {
1743+
not exists(impl.getAttributeMacroExpansion()) and
1744+
exists(TypeParam gp |
1745+
gp = impl.getGenericParamList().getAGenericParam() and
1746+
gp = impl.(ImplItemNode).resolveSelfTy() and
1747+
not exists(gp.(TypeParamItemNode).getABoundPath())
1748+
)
1749+
}
1750+
1751+
private predicate test(Impl impl, ItemNode resolved) {
1752+
exists(TypeParamItemNode tp |
1753+
tp = getBlanketImplementationTypeParam(impl) and
1754+
not blanketImplementationTraitBound(impl, _) and
1755+
not blanketImplementationWithoutBound(impl) and
1756+
resolved = resolvePath(tp.getBoundPath(0))
1757+
)
1758+
}
1759+
1760+
private predicate blanketImplementationMethod(
1761+
Impl impl, Trait trait, string name, int arity, Function f
1762+
) {
1763+
f = impl.(ImplItemNode).getASuccessor(name) and
1764+
blanketImplementationTraitBound(impl, trait) and
1765+
f.getParamList().hasSelfParam() and
1766+
arity = f.getParamList().getNumberOfParams() and
1767+
// Make this stronger and document
1768+
not trait.(TraitItemNode).getASuccessor(name) = f
1769+
}
1770+
1771+
predicate methodCallMatchesBlanketImpl(MethodCall mc, Type t, Impl impl, Trait trait, Function f) {
1772+
exists(string name, int arity |
1773+
isMethodCall(mc, t, name, arity) and
1774+
blanketImplementationMethod(impl, trait, name, arity, f)
1775+
)
1776+
}
1777+
1778+
module SatisfiesConstraintInput implements SatisfiesConstraintInputSig<MethodCall> {
1779+
pragma[nomagic]
1780+
predicate relevantConstraint(MethodCall mc, Type constraint) {
1781+
methodCallMatchesBlanketImpl(mc, _, _, constraint.(TraitType).getTrait(), _)
1782+
}
1783+
}
1784+
1785+
predicate debugSatisfiesConstraintType(MethodCall mc, Trait trait, TypePath path, Type ty) {
1786+
SatisfiesConstraint<MethodCall, SatisfiesConstraintInput>::satisfiesConstraintType(mc,
1787+
TTrait(trait), path, ty)
1788+
}
1789+
1790+
predicate getBlanketImpl(MethodCall mc, Type t, Impl impl, Trait trait, Function f) {
1791+
SatisfiesConstraint<MethodCall, SatisfiesConstraintInput>::satisfiesConstraintType(mc,
1792+
TTrait(trait), _, _) and
1793+
methodCallMatchesBlanketImpl(mc, t, impl, trait, f)
1794+
}
1795+
1796+
pragma[nomagic]
1797+
Function getMethodFromBlanketImpl(MethodCall mc) {
1798+
BlanketImplementation::getBlanketImpl(mc, _, _, _, result)
1799+
}
1800+
}
1801+
17131802
/** Gets a method from an `impl` block that matches the method call `mc`. */
17141803
pragma[nomagic]
17151804
private Function getMethodFromImpl(MethodCall mc) {
@@ -1745,6 +1834,8 @@ private Function resolveMethodCallTarget(MethodCall mc) {
17451834
// The method comes from an `impl` block targeting the type of the receiver.
17461835
result = getMethodFromImpl(mc)
17471836
or
1837+
result = BlanketImplementation::getMethodFromBlanketImpl(mc)
1838+
or
17481839
// The type of the receiver is a type parameter and the method comes from a
17491840
// trait bound on the type parameter.
17501841
result = getTypeParameterMethod(mc.getTypeAt(TypePath::nil()), mc.getMethodName())

0 commit comments

Comments
 (0)