Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 Down Expand Up @@ -36,7 +37,11 @@ class TupleFieldContent extends FieldContent, TTupleFieldContent {
/** Holds if this field belongs to a struct. */
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }

override FieldExprCfgNode getAnAccess() { field = result.getFieldExpr().getTupleField() }
override FieldExprCfgNode getAnAccess() {
field = result.getFieldExpr().getTupleField() and
// tuples are handled using the special `TupleContent` type
not field = any(TupleType tt).getATupleField()
}

final override string toString() {
exists(Variant v, int pos, string vname |
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()
}
}
38 changes: 35 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,9 @@ 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
not name = ["Slice", "Array", "Ref", "Ptr"] and
not name.matches("Tuple%")
)
Comment on lines 2174 to 2176
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The filter excludes builtin types from the regular path resolution: not name = ["Array", "Slice", "Ref", "Ptr"] and not name.matches("Tuple%"). However, these exact names are still defined in types.rs and will be extracted.

This creates a subtle asymmetry - the structs exist in the codebase but are excluded from certain resolution paths. Consider adding a comment explaining why these specific builtin types are filtered out here, and how they are resolved through the alternative resolveBuiltin() mechanism instead.

Copilot uses AI. Check for mistakes.
}

Expand Down
Loading
Loading