Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion rust/ql/lib/codeql/rust/dataflow/internal/Content.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

private import rust
private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.frameworks.stdlib.Builtins
private import DataFlowImpl

/**
Expand All @@ -28,7 +29,11 @@ abstract class FieldContent extends Content {
class TupleFieldContent extends FieldContent, TTupleFieldContent {
private TupleField field;

TupleFieldContent() { this = TTupleFieldContent(field) }
TupleFieldContent() {
this = TTupleFieldContent(field) and
// tuples are handled using the special `TupleContent` type
not field = any(TupleType tt).getATupleField()
}

/** Holds if this field belongs to an enum variant. */
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
Expand Down
6 changes: 6 additions & 0 deletions rust/ql/lib/codeql/rust/elements/internal/StructImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ module Impl {
result.getName().getText() = name
}

/** Gets a record field, if any. */
StructField getAStructField() { result = this.getStructField(_) }

/** Gets the `i`th tuple field, if any. */
pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }

/** Gets a tuple field, if any. */
TupleField getATupleField() { result = this.getTupleField(_) }

/** Holds if this struct uses tuple fields. */
pragma[nomagic]
predicate isTuple() { this.getFieldList() instanceof TupleFieldList }
Expand Down
33 changes: 33 additions & 0 deletions rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,36 @@ class F32 extends FloatingPointTypeImpl {
class F64 extends FloatingPointTypeImpl {
F64() { this.getName() = "f64" }
}

/** The builtin slice type `[T]`. */
class SliceType extends BuiltinType {
SliceType() { this.getName() = "Slice" }
}

/** The builtin array type `[T; N]`. */
class ArrayType extends BuiltinType {
ArrayType() { this.getName() = "Array" }
}

/** The builtin reference type `&T` or `&mut T`. */
class RefType extends BuiltinType {
RefType() { this.getName() = "Ref" }
}

/** The builtin pointer type `*const T` or `*mut T`. */
class PtrType extends BuiltinType {
PtrType() { this.getName() = "Ptr" }
}

/** A builtin tuple type `(T1, T2, ...)`. */
class TupleType extends BuiltinType {
TupleType() { this.getName().matches("Tuple%") }

/** Gets the arity of this tuple type. */
int getArity() {
not this.hasGenericParamList() and
result = 0
or
result = this.getGenericParamList().getNumberOfGenericParams()
}
}
37 changes: 34 additions & 3 deletions rust/ql/lib/codeql/rust/internal/PathResolution.qll
Original file line number Diff line number Diff line change
Expand Up @@ -713,12 +713,34 @@ abstract class ImplOrTraitItemNode extends ItemNode {
predicate hasAssocItem(string name) { name = this.getAnAssocItem().getName() }
}

private TypeItemNode resolveBuiltin(TypeRepr tr) {
tr instanceof SliceTypeRepr and
result instanceof Builtins::SliceType
or
tr instanceof ArrayTypeRepr and
result instanceof Builtins::ArrayType
or
tr instanceof RefTypeRepr and
result instanceof Builtins::RefType
or
tr instanceof PtrTypeRepr and
result instanceof Builtins::PtrType
or
result.(Builtins::TupleType).getArity() = tr.(TupleTypeRepr).getNumberOfFields()
}

final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
Path getSelfPath() { result = super.getSelfTy().(PathTypeRepr).getPath() }

Path getTraitPath() { result = super.getTrait().(PathTypeRepr).getPath() }

TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
TypeItemNode resolveSelfTyBuiltin() { result = resolveBuiltin(this.(Impl).getSelfTy()) }

TypeItemNode resolveSelfTy() {
result = resolvePath(this.getSelfPath())
or
result = this.resolveSelfTyBuiltin()
}

TraitItemNode resolveTraitTy() { result = resolvePath(this.getTraitPath()) }

Expand Down Expand Up @@ -893,7 +915,11 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
}

private class ImplItemNodeImpl extends ImplItemNode {
TypeItemNode resolveSelfTyCand() { result = resolvePathCand(this.getSelfPath()) }
TypeItemNode resolveSelfTyCand() {
result = resolvePathCand(this.getSelfPath())
or
result = this.resolveSelfTyBuiltin()
}

TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
}
Expand Down Expand Up @@ -1764,6 +1790,10 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
or
result = resolveUseTreeListItem(_, _, path, _) and
ns = result.getNamespace()
or
result = resolveBuiltin(path.getSegment().getTypeRepr()) and
not path.getSegment().hasTraitTypeRepr() and
ns.isType()
}

pragma[nomagic]
Expand Down Expand Up @@ -2141,7 +2171,8 @@ pragma[nomagic]
private predicate builtin(string name, ItemNode i) {
exists(BuiltinSourceFile builtins |
builtins.getFile().getBaseName() = "types.rs" and
i = builtins.getASuccessor(name)
i = builtins.getASuccessor(name) and
i.isPublic()
)
}

Expand Down
148 changes: 37 additions & 111 deletions rust/ql/lib/codeql/rust/internal/Type.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ private import codeql.rust.internal.CachedStages
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import codeql.rust.frameworks.stdlib.Stdlib
private import codeql.rust.frameworks.stdlib.Builtins as Builtins

/**
* Holds if a dyn trait type should have a type parameter associated with `n`. A
Expand All @@ -31,39 +32,21 @@ private predicate dynTraitTypeParameter(Trait trait, AstNode n) {

cached
newtype TType =
TTuple(int arity) {
arity =
[
any(TupleTypeRepr t).getNumberOfFields(),
any(TupleExpr e).getNumberOfFields(),
any(TuplePat p).getNumberOfFields()
] and
Stages::TypeInferenceStage::ref()
} or
TStruct(Struct s) or
TStruct(Struct s) { Stages::TypeInferenceStage::ref() } or
TEnum(Enum e) or
TTrait(Trait t) or
TUnion(Union u) or
TArrayType() or // todo: add size?
TRefType() or // todo: add mut?
TImplTraitType(ImplTraitTypeRepr impl) or
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
TSliceType() or
TNeverType() or
TPtrType() or
TUnknownType() or
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
TTypeParamTypeParameter(TypeParam t) or
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
TArrayTypeParameter() or
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) {
implTraitTypeParam(implTrait, _, tp)
} or
TRefTypeParameter() or
TSelfTypeParameter(Trait t) or
TSliceTypeParameter() or
TPtrTypeParameter()
TSelfTypeParameter(Trait t)

private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
implTrait.isInReturnPos() and
Expand Down Expand Up @@ -106,26 +89,25 @@ abstract class Type extends TType {
}

/** A tuple type `(T, ...)`. */
class TupleType extends Type, TTuple {
class TupleType extends StructType {
private int arity;

TupleType() { this = TTuple(arity) }

override TypeParameter getPositionalTypeParameter(int i) {
result = TTupleTypeParameter(arity, i)
}
TupleType() { arity = this.getStruct().(Builtins::TupleType).getArity() }

/** Gets the arity of this tuple type. */
int getArity() { result = arity }

override string toString() { result = "(T_" + arity + ")" }
}

override Location getLocation() { result instanceof EmptyLocation }
pragma[nomagic]
TypeParamTypeParameter getTupleTypeParameter(int arity, int i) {
result = any(TupleType t | t.getArity() = arity).getPositionalTypeParameter(i)
}

/** The unit type `()`. */
class UnitType extends TupleType {
UnitType() { this = TTuple(0) }
UnitType() { this.getArity() = 0 }

override string toString() { result = "()" }
}
Expand Down Expand Up @@ -226,20 +208,17 @@ class UnionType extends Type, TUnion {
/**
* An array type.
*
* Array types like `[i64; 5]` are modeled as normal generic types
* with a single type argument.
* Array types like `[i64; 5]` are modeled as normal generic types.
*/
class ArrayType extends Type, TArrayType {
ArrayType() { this = TArrayType() }
class ArrayType extends StructType {
ArrayType() { this.getStruct() instanceof Builtins::ArrayType }

override TypeParameter getPositionalTypeParameter(int i) {
result = TArrayTypeParameter() and
i = 0
}

override string toString() { result = "[]" }
override string toString() { result = "[;]" }
}

override Location getLocation() { result instanceof EmptyLocation }
pragma[nomagic]
TypeParamTypeParameter getArrayTypeParameter() {
result = any(ArrayType t).getPositionalTypeParameter(0)
}

/**
Expand All @@ -248,17 +227,15 @@ class ArrayType extends Type, TArrayType {
* Reference types like `& i64` are modeled as normal generic types
* with a single type argument.
*/
class RefType extends Type, TRefType {
RefType() { this = TRefType() }

override TypeParameter getPositionalTypeParameter(int i) {
result = TRefTypeParameter() and
i = 0
}
class RefType extends StructType {
RefType() { this.getStruct() instanceof Builtins::RefType }

override string toString() { result = "&" }
}

override Location getLocation() { result instanceof EmptyLocation }
pragma[nomagic]
TypeParamTypeParameter getRefTypeParameter() {
result = any(RefType t).getPositionalTypeParameter(0)
}

/**
Expand Down Expand Up @@ -340,17 +317,15 @@ class ImplTraitReturnType extends ImplTraitType {
* Slice types like `[i64]` are modeled as normal generic types
* with a single type argument.
*/
class SliceType extends Type, TSliceType {
SliceType() { this = TSliceType() }

override TypeParameter getPositionalTypeParameter(int i) {
result = TSliceTypeParameter() and
i = 0
}
class SliceType extends StructType {
SliceType() { this.getStruct() instanceof Builtins::SliceType }

override string toString() { result = "[]" }
}

override Location getLocation() { result instanceof EmptyLocation }
pragma[nomagic]
TypeParamTypeParameter getSliceTypeParameter() {
result = any(SliceType t).getPositionalTypeParameter(0)
}

class NeverType extends Type, TNeverType {
Expand All @@ -361,11 +336,8 @@ class NeverType extends Type, TNeverType {
override Location getLocation() { result instanceof EmptyLocation }
}

class PtrType extends Type, TPtrType {
override TypeParameter getPositionalTypeParameter(int i) {
i = 0 and
result = TPtrTypeParameter()
}
class PtrType extends StructType {
PtrType() { this.getStruct() instanceof Builtins::PtrType }

override string toString() { result = "*" }

Expand Down Expand Up @@ -402,6 +374,11 @@ class UnknownType extends Type, TUnknownType {
override Location getLocation() { result instanceof EmptyLocation }
}

pragma[nomagic]
TypeParamTypeParameter getPtrTypeParameter() {
result = any(PtrType t).getPositionalTypeParameter(0)
}

/** A type parameter. */
abstract class TypeParameter extends Type {
override TypeParameter getPositionalTypeParameter(int i) { none() }
Expand Down Expand Up @@ -461,37 +438,6 @@ class AssociatedTypeTypeParameter extends TypeParameter, TAssociatedTypeTypePara
override Location getLocation() { result = typeAlias.getLocation() }
}

/**
* A tuple type parameter. For instance the `T` in `(T, U)`.
*
* Since tuples are structural their type parameters can be represented as their
* positional index. The type inference library requires that type parameters
* belong to a single type, so we also include the arity of the tuple type.
*/
class TupleTypeParameter extends TypeParameter, TTupleTypeParameter {
private int arity;
private int index;

TupleTypeParameter() { this = TTupleTypeParameter(arity, index) }

override string toString() { result = index.toString() + "(" + arity + ")" }

override Location getLocation() { result instanceof EmptyLocation }

/** Gets the index of this tuple type parameter. */
int getIndex() { result = index }

/** Gets the tuple type that corresponds to this tuple type parameter. */
TupleType getTupleType() { result = TTuple(arity) }
}

/** An implicit array type parameter. */
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
override string toString() { result = "[T;...]" }

override Location getLocation() { result instanceof EmptyLocation }
}

class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
private AstNode n;

Expand Down Expand Up @@ -539,26 +485,6 @@ class ImplTraitTypeParameter extends TypeParameter, TImplTraitTypeParameter {
override Location getLocation() { result = typeParam.getLocation() }
}

/** An implicit reference type parameter. */
class RefTypeParameter extends TypeParameter, TRefTypeParameter {
override string toString() { result = "&T" }

override Location getLocation() { result instanceof EmptyLocation }
}

/** An implicit slice type parameter. */
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
override string toString() { result = "[T]" }

override Location getLocation() { result instanceof EmptyLocation }
}

class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
override string toString() { result = "*T" }

override Location getLocation() { result instanceof EmptyLocation }
}

/**
* The implicit `Self` type parameter of a trait, that refers to the
* implementing type of the trait.
Expand Down
Loading
Loading