Skip to content

Commit d15d2d9

Browse files
committed
Rust: Block non-numeric types for number literals
1 parent 59fc7aa commit d15d2d9

File tree

3 files changed

+36
-16
lines changed

3 files changed

+36
-16
lines changed

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

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,72 +46,79 @@ class Str extends BuiltinType {
4646
Str() { this.getName() = "str" }
4747
}
4848

49+
/**
50+
* A numeric type.
51+
*
52+
* See: https://doc.rust-lang.org/reference/types/numeric.html
53+
*/
54+
abstract class NumericType extends BuiltinType { }
55+
4956
/** The builtin `i8` type. */
50-
class I8 extends BuiltinType {
57+
class I8 extends NumericType {
5158
I8() { this.getName() = "i8" }
5259
}
5360

5461
/** The builtin `i16` type. */
55-
class I16 extends BuiltinType {
62+
class I16 extends NumericType {
5663
I16() { this.getName() = "i16" }
5764
}
5865

5966
/** The builtin `i32` type. */
60-
class I32 extends BuiltinType {
67+
class I32 extends NumericType {
6168
I32() { this.getName() = "i32" }
6269
}
6370

6471
/** The builtin `i64` type. */
65-
class I64 extends BuiltinType {
72+
class I64 extends NumericType {
6673
I64() { this.getName() = "i64" }
6774
}
6875

6976
/** The builtin `i128` type. */
70-
class I128 extends BuiltinType {
77+
class I128 extends NumericType {
7178
I128() { this.getName() = "i128" }
7279
}
7380

7481
/** The builtin `u8` type. */
75-
class U8 extends BuiltinType {
82+
class U8 extends NumericType {
7683
U8() { this.getName() = "u8" }
7784
}
7885

7986
/** The builtin `u16` type. */
80-
class U16 extends BuiltinType {
87+
class U16 extends NumericType {
8188
U16() { this.getName() = "u16" }
8289
}
8390

8491
/** The builtin `u32` type. */
85-
class U32 extends BuiltinType {
92+
class U32 extends NumericType {
8693
U32() { this.getName() = "u32" }
8794
}
8895

8996
/** The builtin `u64` type. */
90-
class U64 extends BuiltinType {
97+
class U64 extends NumericType {
9198
U64() { this.getName() = "u64" }
9299
}
93100

94101
/** The builtin `u128` type. */
95-
class U128 extends BuiltinType {
102+
class U128 extends NumericType {
96103
U128() { this.getName() = "u128" }
97104
}
98105

99106
/** The builtin `usize` type. */
100-
class Usize extends BuiltinType {
107+
class Usize extends NumericType {
101108
Usize() { this.getName() = "usize" }
102109
}
103110

104111
/** The builtin `isize` type. */
105-
class Isize extends BuiltinType {
112+
class Isize extends NumericType {
106113
Isize() { this.getName() = "isize" }
107114
}
108115

109116
/** The builtin `f32` type. */
110-
class F32 extends BuiltinType {
117+
class F32 extends NumericType {
111118
F32() { this.getName() = "f32" }
112119
}
113120

114121
/** The builtin `f64` type. */
115-
class F64 extends BuiltinType {
122+
class F64 extends NumericType {
116123
F64() { this.getName() = "f64" }
117124
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ class StructType extends StructOrEnumType, TStruct {
146146

147147
StructType() { this = TStruct(struct) }
148148

149+
Struct asStruct() { result = struct }
150+
149151
override ItemNode asItemNode() { result = struct }
150152

151153
override StructField getStructField(string name) { result = struct.getStructField(name) }

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,10 +500,10 @@ module CertainTypeInference {
500500
}
501501

502502
private Type inferLogicalOperationType(AstNode n, TypePath path) {
503-
exists(Builtins::Bool t, BinaryLogicalOperation be |
503+
exists(BinaryLogicalOperation be |
504504
n = [be, be.getLhs(), be.getRhs()] and
505505
path.isEmpty() and
506-
result = TStruct(t)
506+
result.(StructType).asStruct() instanceof Builtins::Bool
507507
)
508508
}
509509

@@ -1467,6 +1467,11 @@ private Type inferLiteralType(LiteralExpr le, TypePath path, boolean certain) {
14671467
certain = true
14681468
}
14691469

1470+
predicate uncertainNumberLiteral(LiteralExpr le) {
1471+
le instanceof NumberLiteralExpr and
1472+
not CertainTypeInference::hasInferredCertainType(le)
1473+
}
1474+
14701475
pragma[nomagic]
14711476
private TraitType getFutureTraitType() { result.getTrait() instanceof FutureTrait }
14721477

@@ -2433,6 +2438,12 @@ private module Cached {
24332438
then not CertainTypeInference::certainTypeConflict(n, path, result)
24342439
else any()
24352440
) and
2441+
// Don't infer non-numerical types for number literals.
2442+
(
2443+
if uncertainNumberLiteral(n)
2444+
then result.(StructType).asStruct() instanceof Builtins::NumericType and path.isEmpty()
2445+
else any()
2446+
) and
24362447
(
24372448
result = inferAssignmentOperationType(n, path)
24382449
or

0 commit comments

Comments
 (0)