Skip to content

Commit 7033a26

Browse files
committed
Rust: Model slice/array types in path resolution
1 parent 467bd54 commit 7033a26

File tree

9 files changed

+180
-139
lines changed

9 files changed

+180
-139
lines changed

rust/ql/lib/codeql/rust/frameworks/stdlib/Builtins.qll

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,13 @@ class F32 extends FloatingPointTypeImpl {
136136
class F64 extends FloatingPointTypeImpl {
137137
F64() { this.getName() = "f64" }
138138
}
139+
140+
/** The builtin slice type `[T]`. */
141+
class SliceType extends BuiltinType {
142+
SliceType() { this.getName() = "Slice" }
143+
}
144+
145+
/** The builtin array type `[T; N]`. */
146+
class ArrayType extends BuiltinType {
147+
ArrayType() { this.getName() = "Array" }
148+
}

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

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,7 +718,19 @@ final class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
718718

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

721-
TypeItemNode resolveSelfTy() { result = resolvePath(this.getSelfPath()) }
721+
TypeItemNode resolveSelfTyBuiltin() {
722+
this.(Impl).getSelfTy() instanceof SliceTypeRepr and
723+
result instanceof Builtins::SliceType
724+
or
725+
this.(Impl).getSelfTy() instanceof ArrayTypeRepr and
726+
result instanceof Builtins::ArrayType
727+
}
728+
729+
TypeItemNode resolveSelfTy() {
730+
result = resolvePath(this.getSelfPath())
731+
or
732+
result = this.resolveSelfTyBuiltin()
733+
}
722734

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

@@ -893,7 +905,11 @@ private class ModuleItemNode extends ModuleLikeNode instanceof Module {
893905
}
894906

895907
private class ImplItemNodeImpl extends ImplItemNode {
896-
TypeItemNode resolveSelfTyCand() { result = resolvePathCand(this.getSelfPath()) }
908+
TypeItemNode resolveSelfTyCand() {
909+
result = resolvePathCand(this.getSelfPath())
910+
or
911+
result = this.resolveSelfTyBuiltin()
912+
}
897913

898914
TraitItemNode resolveTraitTyCand() { result = resolvePathCand(this.getTraitPath()) }
899915
}
@@ -1743,6 +1759,14 @@ private ItemNode resolvePathCand0(RelevantPath path, Namespace ns) {
17431759
or
17441760
result = resolveUseTreeListItem(_, _, path, _) and
17451761
ns = result.getNamespace()
1762+
or
1763+
path.getSegment().getTypeRepr() instanceof SliceTypeRepr and
1764+
result = any(BuiltinSourceFile b).getASuccessor("Slice") and
1765+
ns.isType()
1766+
or
1767+
path.getSegment().getTypeRepr() instanceof ArrayTypeRepr and
1768+
result = any(BuiltinSourceFile b).getASuccessor("Array") and
1769+
ns.isType()
17461770
}
17471771

17481772
pragma[nomagic]
@@ -2106,7 +2130,8 @@ pragma[nomagic]
21062130
private predicate builtin(string name, ItemNode i) {
21072131
exists(BuiltinSourceFile builtins |
21082132
builtins.getFile().getBaseName() = "types.rs" and
2109-
i = builtins.getASuccessor(name)
2133+
i = builtins.getASuccessor(name) and
2134+
not name = ["Array", "Slice"]
21102135
)
21112136
}
21122137

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

Lines changed: 14 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ private import codeql.rust.internal.CachedStages
77
private import codeql.rust.elements.internal.generated.Raw
88
private import codeql.rust.elements.internal.generated.Synth
99
private import codeql.rust.frameworks.stdlib.Stdlib
10+
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
1011

1112
/**
1213
* Holds if a dyn trait type should have a type parameter associated with `n`. A
@@ -44,24 +45,20 @@ newtype TType =
4445
TEnum(Enum e) or
4546
TTrait(Trait t) or
4647
TUnion(Union u) or
47-
TArrayType() or // todo: add size?
4848
TRefType() or // todo: add mut?
4949
TImplTraitType(ImplTraitTypeRepr impl) or
5050
TDynTraitType(Trait t) { t = any(DynTraitTypeRepr dt).getTrait() } or
51-
TSliceType() or
5251
TNeverType() or
5352
TPtrType() or
5453
TTupleTypeParameter(int arity, int i) { exists(TTuple(arity)) and i in [0 .. arity - 1] } or
5554
TTypeParamTypeParameter(TypeParam t) or
5655
TAssociatedTypeTypeParameter(TypeAlias t) { any(TraitItemNode trait).getAnAssocItem() = t } or
57-
TArrayTypeParameter() or
5856
TDynTraitTypeParameter(AstNode n) { dynTraitTypeParameter(_, n) } or
5957
TImplTraitTypeParameter(ImplTraitTypeRepr implTrait, TypeParam tp) {
6058
implTraitTypeParam(implTrait, _, tp)
6159
} or
6260
TRefTypeParameter() or
6361
TSelfTypeParameter(Trait t) or
64-
TSliceTypeParameter() or
6562
TPtrTypeParameter()
6663

6764
private predicate implTraitTypeParam(ImplTraitTypeRepr implTrait, int i, TypeParam tp) {
@@ -228,17 +225,10 @@ class UnionType extends Type, TUnion {
228225
* Array types like `[i64; 5]` are modeled as normal generic types
229226
* with a single type argument.
230227
*/
231-
class ArrayType extends Type, TArrayType {
232-
ArrayType() { this = TArrayType() }
228+
class ArrayType extends StructType {
229+
ArrayType() { this.getStruct() instanceof Builtins::ArrayType }
233230

234-
override TypeParameter getPositionalTypeParameter(int i) {
235-
result = TArrayTypeParameter() and
236-
i = 0
237-
}
238-
239-
override string toString() { result = "[]" }
240-
241-
override Location getLocation() { result instanceof EmptyLocation }
231+
override string toString() { result = "[;]" }
242232
}
243233

244234
/**
@@ -339,17 +329,10 @@ class ImplTraitReturnType extends ImplTraitType {
339329
* Slice types like `[i64]` are modeled as normal generic types
340330
* with a single type argument.
341331
*/
342-
class SliceType extends Type, TSliceType {
343-
SliceType() { this = TSliceType() }
344-
345-
override TypeParameter getPositionalTypeParameter(int i) {
346-
result = TSliceTypeParameter() and
347-
i = 0
348-
}
332+
class SliceType extends StructType {
333+
SliceType() { this.getStruct() instanceof Builtins::SliceType }
349334

350335
override string toString() { result = "[]" }
351-
352-
override Location getLocation() { result instanceof EmptyLocation }
353336
}
354337

355338
class NeverType extends Type, TNeverType {
@@ -392,7 +375,14 @@ class TypeParamTypeParameter extends TypeParameter, TTypeParamTypeParameter {
392375

393376
TypeParam getTypeParam() { result = typeParam }
394377

395-
override string toString() { result = typeParam.toString() }
378+
override string toString() {
379+
if this = any(ArrayType at).getATypeParameter()
380+
then result = "[T;...]"
381+
else
382+
if this = any(SliceType st).getATypeParameter()
383+
then result = "[T]"
384+
else result = typeParam.toString()
385+
}
396386

397387
override Location getLocation() { result = typeParam.getLocation() }
398388
}
@@ -454,13 +444,6 @@ class TupleTypeParameter extends TypeParameter, TTupleTypeParameter {
454444
TupleType getTupleType() { result = TTuple(arity) }
455445
}
456446

457-
/** An implicit array type parameter. */
458-
class ArrayTypeParameter extends TypeParameter, TArrayTypeParameter {
459-
override string toString() { result = "[T;...]" }
460-
461-
override Location getLocation() { result instanceof EmptyLocation }
462-
}
463-
464447
class DynTraitTypeParameter extends TypeParameter, TDynTraitTypeParameter {
465448
private AstNode n;
466449

@@ -515,13 +498,6 @@ class RefTypeParameter extends TypeParameter, TRefTypeParameter {
515498
override Location getLocation() { result instanceof EmptyLocation }
516499
}
517500

518-
/** An implicit slice type parameter. */
519-
class SliceTypeParameter extends TypeParameter, TSliceTypeParameter {
520-
override string toString() { result = "[T]" }
521-
522-
override Location getLocation() { result instanceof EmptyLocation }
523-
}
524-
525501
class PtrTypeParameter extends TypeParameter, TPtrTypeParameter {
526502
override string toString() { result = "*T" }
527503

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,25 +87,15 @@ private module Input1 implements InputSig1<Location> {
8787
int getTypeParameterId(TypeParameter tp) {
8888
tp =
8989
rank[result](TypeParameter tp0, int kind, int id1, int id2 |
90-
tp0 instanceof ArrayTypeParameter and
91-
kind = 0 and
92-
id1 = 0 and
93-
id2 = 0
94-
or
9590
tp0 instanceof RefTypeParameter and
9691
kind = 0 and
9792
id1 = 0 and
98-
id2 = 1
99-
or
100-
tp0 instanceof SliceTypeParameter and
101-
kind = 0 and
102-
id1 = 0 and
103-
id2 = 2
93+
id2 = 0
10494
or
10595
tp0 instanceof PtrTypeParameter and
10696
kind = 0 and
10797
id1 = 0 and
108-
id2 = 3
98+
id2 = 1
10999
or
110100
kind = 1 and
111101
id1 = 0 and
@@ -555,6 +545,16 @@ private predicate bodyReturns(Expr body, Expr e) {
555545
)
556546
}
557547

548+
pragma[nomagic]
549+
TypeParamTypeParameter getArrayTypeParameter() {
550+
result = any(ArrayType t).getPositionalTypeParameter(0)
551+
}
552+
553+
pragma[nomagic]
554+
TypeParamTypeParameter getSliceTypeParameter() {
555+
result = any(SliceType t).getPositionalTypeParameter(0)
556+
}
557+
558558
/**
559559
* Holds if the type tree of `n1` at `prefix1` should be equal to the type tree
560560
* of `n2` at `prefix2` and type information should propagate in both directions
@@ -649,12 +649,12 @@ private predicate typeEquality(AstNode n1, TypePath prefix1, AstNode n2, TypePat
649649
ale.getAnExpr() = n2 and
650650
ale.getNumberOfExprs() = 1
651651
) and
652-
prefix1 = TypePath::singleton(TArrayTypeParameter()) and
652+
prefix1 = TypePath::singleton(getArrayTypeParameter()) and
653653
prefix2.isEmpty()
654654
or
655655
// an array repeat expression (`[1; 3]`) has the type of the repeat operand
656656
n1.(ArrayRepeatExpr).getRepeatOperand() = n2 and
657-
prefix1 = TypePath::singleton(TArrayTypeParameter()) and
657+
prefix1 = TypePath::singleton(getArrayTypeParameter()) and
658658
prefix2.isEmpty()
659659
or
660660
exists(Struct s |
@@ -703,7 +703,7 @@ private predicate lubCoercion(AstNode parent, AstNode child, TypePath prefix) {
703703
child = ale.getAnExpr() and
704704
ale.getNumberOfExprs() > 1
705705
) and
706-
prefix = TypePath::singleton(TArrayTypeParameter())
706+
prefix = TypePath::singleton(getArrayTypeParameter())
707707
or
708708
bodyReturns(parent, child) and
709709
strictcount(Expr e | bodyReturns(parent, e)) > 1 and
@@ -2886,7 +2886,7 @@ private Type inferAwaitExprType(AstNode n, TypePath path) {
28862886
* Gets the root type of the array expression `ae`.
28872887
*/
28882888
pragma[nomagic]
2889-
private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result = TArrayType() }
2889+
private Type inferArrayExprType(ArrayExpr ae) { exists(ae) and result instanceof ArrayType }
28902890

28912891
/**
28922892
* Gets the root type of the range expression `re`.
@@ -2922,11 +2922,11 @@ private Type inferIndexExprType(IndexExpr ie, TypePath path) {
29222922
// todo: remove?
29232923
exprPath.isCons(TTypeParamTypeParameter(any(Vec v).getElementTypeParam()), path)
29242924
or
2925-
exprPath.isCons(any(ArrayTypeParameter tp), path)
2925+
exprPath.isCons(getArrayTypeParameter(), path)
29262926
or
29272927
exists(TypePath path0 |
29282928
exprPath.isCons(any(RefTypeParameter tp), path0) and
2929-
path0.isCons(any(SliceTypeParameter tp), path)
2929+
path0.isCons(getSliceTypeParameter(), path)
29302930
)
29312931
)
29322932
}
@@ -3071,7 +3071,7 @@ private Type inferForLoopExprType(AstNode n, TypePath path) {
30713071
or
30723072
// TODO: Remove once we can handle the `impl<I: Iterator> IntoIterator for I` implementation
30733073
tp = getIteratorItemTypeParameter() and
3074-
inferType(fe.getIterable()) != TArrayType()
3074+
inferType(fe.getIterable()) != getArrayTypeParameter()
30753075
)
30763076
}
30773077

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ class ParenthesizedArgListMention extends TypeMention instanceof ParenthesizedAr
4444
class ArrayTypeReprMention extends TypeMention instanceof ArrayTypeRepr {
4545
override Type resolveTypeAt(TypePath path) {
4646
path.isEmpty() and
47-
result = TArrayType()
47+
result instanceof ArrayType
4848
or
4949
exists(TypePath suffix |
5050
result = super.getElementTypeRepr().(TypeMention).resolveTypeAt(suffix) and
51-
path = TypePath::cons(TArrayTypeParameter(), suffix)
51+
path = TypePath::cons(getArrayTypeParameter(), suffix)
5252
)
5353
}
5454
}
@@ -68,11 +68,11 @@ class RefTypeReprMention extends TypeMention instanceof RefTypeRepr {
6868
class SliceTypeReprMention extends TypeMention instanceof SliceTypeRepr {
6969
override Type resolveTypeAt(TypePath path) {
7070
path.isEmpty() and
71-
result = TSliceType()
71+
result instanceof SliceType
7272
or
7373
exists(TypePath suffix |
7474
result = super.getTypeRepr().(TypeMention).resolveTypeAt(suffix) and
75-
path = TypePath::cons(TSliceTypeParameter(), suffix)
75+
path = TypePath::cons(getSliceTypeParameter(), suffix)
7676
)
7777
}
7878
}

rust/ql/lib/codeql/rust/security/Barriers.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import rust
77
private import codeql.rust.dataflow.DataFlow
88
private import codeql.rust.internal.TypeInference as TypeInference
99
private import codeql.rust.internal.Type
10-
private import codeql.rust.frameworks.stdlib.Builtins
10+
private import codeql.rust.frameworks.stdlib.Builtins as Builtins
1111

1212
/**
1313
* A node whose type is a numeric or boolean type, which may be an appropriate
@@ -19,8 +19,8 @@ class NumericTypeBarrier extends DataFlow::Node {
1919
t = TypeInference::inferType(this.asExpr().getExpr()) and
2020
s = t.getStruct()
2121
|
22-
s instanceof NumericType or
23-
s instanceof Bool
22+
s instanceof Builtins::NumericType or
23+
s instanceof Builtins::Bool
2424
)
2525
}
2626
}
@@ -35,8 +35,8 @@ class IntegralOrBooleanTypeBarrier extends DataFlow::Node {
3535
t = TypeInference::inferType(this.asExpr().getExpr()) and
3636
s = t.getStruct()
3737
|
38-
s instanceof IntegralType or
39-
s instanceof Bool
38+
s instanceof Builtins::IntegralType or
39+
s instanceof Builtins::Bool
4040
)
4141
}
4242
}

rust/ql/test/library-tests/type-inference/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2560,7 +2560,7 @@ mod loops {
25602560

25612561
// for loops with containers
25622562

2563-
let vals3 = vec![1, 2, 3]; // $ MISSING: type=vals3:Vec type=vals3:T.i32
2563+
let vals3 = vec![1, 2, 3]; // $ type=vals3:Vec $ MISSING: type=vals3:T.i32
25642564
for i in vals3 {} // $ MISSING: type=i:i32
25652565

25662566
let vals4a: Vec<u16> = [1u16, 2, 3].to_vec(); // $ certainType=vals4a:Vec certainType=vals4a:T.u16
@@ -2579,7 +2579,7 @@ mod loops {
25792579
vals7.push(1u8); // $ target=push
25802580
for u in vals7 {} // $ type=u:u8
25812581

2582-
let matrix1 = vec![vec![1, 2], vec![3, 4]]; // $ MISSING: type=matrix1:Vec type=matrix1:T.Vec type=matrix1:T.T.i32
2582+
let matrix1 = vec![vec![1, 2], vec![3, 4]]; // $ type=matrix1:Vec $ MISSING: type=matrix1:T.Vec type=matrix1:T.T.i32
25832583
#[rustfmt::skip]
25842584
let _ = for row in matrix1 { // $ MISSING: type=row:Vec type=row:T.i32
25852585
for cell in row { // $ MISSING: type=cell:i32

0 commit comments

Comments
 (0)