Skip to content

Commit 1aa2951

Browse files
committed
Validate transmutes in CTFE
1 parent fa3976f commit 1aa2951

32 files changed

+511
-1054
lines changed

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ fn eval_body_using_ecx<'tcx, R: InterpretationResult<'tcx>>(
9393
// Since evaluation had no errors, validate the resulting constant.
9494
const_validate_mplace(ecx, &ret, cid)?;
9595

96-
// Only report this after validation, as validaiton produces much better diagnostics.
96+
// Only report this after validation, as validation produces much better diagnostics.
9797
// FIXME: ensure validation always reports this and stop making interning care about it.
9898

9999
match intern_result {

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
141141
}
142142

143143
self.copy_op_allow_transmute(src, dest)?;
144+
145+
// Even if general validation is disabled, transmutes should always check their result.
146+
if !M::enforce_validity(self, dest.layout) {
147+
self.validate_operand(
148+
&dest,
149+
M::enforce_validity_recursively(self, dest.layout),
150+
/*reset_provenance_and_padding*/ true,
151+
)?;
152+
}
144153
}
145154
}
146155
interp_ok(())

tests/ui/consts/const-eval/raw-bytes.32bit.stderr

Lines changed: 76 additions & 236 deletions
Large diffs are not rendered by default.

tests/ui/consts/const-eval/raw-bytes.64bit.stderr

Lines changed: 76 additions & 236 deletions
Large diffs are not rendered by default.

tests/ui/consts/const-eval/raw-bytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
7676
//~^ ERROR constructing invalid value
7777

7878
const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
79-
//~^ ERROR constructing invalid value
8079
let x: &dyn Send = &42;
8180
let meta = std::ptr::metadata(x);
8281
mem::transmute((0_usize, meta))
82+
//~^ ERROR constructing invalid value
8383
};
8484

8585
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };

tests/ui/consts/const-eval/transmute-const.stderr

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
error[E0080]: constructing invalid value: encountered 0x03, but expected a boolean
2-
--> $DIR/transmute-const.rs:4:1
2+
--> $DIR/transmute-const.rs:4:29
33
|
44
LL | static FOO: bool = unsafe { mem::transmute(3u8) };
5-
| ^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
6-
|
7-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
8-
= note: the raw bytes of the constant (size: 1, align: 1) {
9-
03 │ .
10-
}
5+
| ^^^^^^^^^^^^^^^^^^^ evaluation of `FOO` failed here
116

127
error: aborting due to 1 previous error
138

tests/ui/consts/const-eval/ub-enum.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
3030
//~^ ERROR expected a valid enum tag
3131

3232
const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
33-
//~^ ERROR unable to turn pointer into integer
33+
//~^ ERROR encountered a pointer, but expected an integer
3434

3535
const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
36-
//~^ ERROR unable to turn pointer into integer
36+
//~^ ERROR encountered a pointer, but expected an integer
3737

3838
// # simple enum with discriminant 2
3939

@@ -47,10 +47,10 @@ enum Enum2 {
4747
const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
4848
//~^ ERROR expected a valid enum tag
4949
const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
50-
//~^ ERROR unable to turn pointer into integer
50+
//~^ ERROR encountered a pointer, but expected an integer
5151
// something wrapping the enum so that we test layout first, not enum
5252
const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
53-
//~^ ERROR unable to turn pointer into integer
53+
//~^ ERROR encountered a pointer, but expected an integer
5454

5555
// Undef enum discriminant.
5656
#[repr(C)]
@@ -63,7 +63,7 @@ const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init };
6363

6464
// Pointer value in an enum with a niche that is not just 0.
6565
const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
66-
//~^ ERROR unable to turn pointer into integer
66+
//~^ ERROR encountered a pointer, but expected an integer
6767

6868
// # valid discriminant for uninhabited variant
6969

tests/ui/consts/const-eval/ub-enum.stderr

Lines changed: 26 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,47 @@
11
error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x01, but expected a valid enum tag
2-
--> $DIR/ub-enum.rs:29:1
2+
--> $DIR/ub-enum.rs:29:33
33
|
44
LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
5-
| ^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
6-
|
7-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
8-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
9-
HEX_DUMP
10-
}
5+
| ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM` failed here
116

12-
error[E0080]: unable to turn pointer into integer
13-
--> $DIR/ub-enum.rs:32:1
7+
error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
8+
--> $DIR/ub-enum.rs:32:37
149
|
1510
LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) };
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_PTR` failed here
11+
| ^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_PTR` failed here
1712
|
1813
= help: this code performed an operation that depends on the underlying bytes representing a pointer
1914
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
2015

21-
error[E0080]: unable to turn pointer into integer
22-
--> $DIR/ub-enum.rs:35:1
16+
error[E0080]: constructing invalid value at .0.<enum-tag>: encountered a pointer, but expected an integer
17+
--> $DIR/ub-enum.rs:35:47
2318
|
2419
LL | const BAD_ENUM_WRAPPED: Wrap<Enum> = unsafe { mem::transmute(&1) };
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_WRAPPED` failed here
20+
| ^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM_WRAPPED` failed here
2621
|
2722
= help: this code performed an operation that depends on the underlying bytes representing a pointer
2823
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
2924

3025
error[E0080]: constructing invalid value at .<enum-tag>: encountered 0x0, but expected a valid enum tag
31-
--> $DIR/ub-enum.rs:47:1
26+
--> $DIR/ub-enum.rs:47:35
3227
|
3328
LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
34-
| ^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
35-
|
36-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
37-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
38-
HEX_DUMP
39-
}
29+
| ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2` failed here
4030

41-
error[E0080]: unable to turn pointer into integer
42-
--> $DIR/ub-enum.rs:49:1
31+
error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
32+
--> $DIR/ub-enum.rs:49:39
4333
|
4434
LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) };
45-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_PTR` failed here
35+
| ^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_PTR` failed here
4636
|
4737
= help: this code performed an operation that depends on the underlying bytes representing a pointer
4838
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
4939

50-
error[E0080]: unable to turn pointer into integer
51-
--> $DIR/ub-enum.rs:52:1
40+
error[E0080]: constructing invalid value at .0.<enum-tag>: encountered a pointer, but expected an integer
41+
--> $DIR/ub-enum.rs:52:49
5242
|
5343
LL | const BAD_ENUM2_WRAPPED: Wrap<Enum2> = unsafe { mem::transmute(&0) };
54-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_WRAPPED` failed here
44+
| ^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_WRAPPED` failed here
5545
|
5646
= help: this code performed an operation that depends on the underlying bytes representing a pointer
5747
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
@@ -62,47 +52,32 @@ error[E0080]: using uninitialized data, but this operation requires initialized
6252
LL | const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init };
6353
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_UNDEF` failed here
6454

65-
error[E0080]: unable to turn pointer into integer
66-
--> $DIR/ub-enum.rs:65:1
55+
error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
56+
--> $DIR/ub-enum.rs:65:54
6757
|
6858
LL | const BAD_ENUM2_OPTION_PTR: Option<Enum2> = unsafe { mem::transmute(&0) };
69-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_OPTION_PTR` failed here
59+
| ^^^^^^^^^^^^^^^^^^ evaluation of `BAD_ENUM2_OPTION_PTR` failed here
7060
|
7161
= help: this code performed an operation that depends on the underlying bytes representing a pointer
7262
= help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
7363

7464
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
75-
--> $DIR/ub-enum.rs:82:1
65+
--> $DIR/ub-enum.rs:82:62
7666
|
7767
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
78-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
79-
|
80-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
81-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
82-
HEX_DUMP
83-
}
68+
| ^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_VARIANT1` failed here
8469

8570
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
86-
--> $DIR/ub-enum.rs:84:1
71+
--> $DIR/ub-enum.rs:84:62
8772
|
8873
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
89-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
90-
|
91-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
92-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
93-
HEX_DUMP
94-
}
74+
| ^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_VARIANT2` failed here
9575

96-
error[E0080]: constructing invalid value at .<enum-variant(Some)>.0.1: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
97-
--> $DIR/ub-enum.rs:92:1
76+
error[E0080]: constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
77+
--> $DIR/ub-enum.rs:92:67
9878
|
9979
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
100-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
101-
|
102-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
103-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
104-
HEX_DUMP
105-
}
80+
| ^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_OPTION_CHAR` failed here
10681

10782
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
10883
--> $DIR/ub-enum.rs:97:77

tests/ui/consts/const-eval/ub-incorrect-vtable.32bit.stderr

Lines changed: 20 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,32 @@
1-
error[E0080]: constructing invalid value: encountered ALLOC1<imm>, but expected a vtable pointer
2-
--> $DIR/ub-incorrect-vtable.rs:18:1
1+
error[E0080]: constructing invalid value: encountered ALLOC2<imm>, but expected a vtable pointer
2+
--> $DIR/ub-incorrect-vtable.rs:19:14
33
|
4-
LL | const INVALID_VTABLE_ALIGNMENT: &dyn Trait =
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
6-
|
7-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
8-
= note: the raw bytes of the constant (size: 8, align: 4) {
9-
╾ALLOC0<imm>╼ ╾ALLOC1<imm>╼ │ ╾──╼╾──╼
10-
}
4+
LL | unsafe { std::mem::transmute((&92u8, &[0usize, 1usize, 1000usize])) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_ALIGNMENT` failed here
116

127
error[E0080]: constructing invalid value: encountered ALLOC3<imm>, but expected a vtable pointer
13-
--> $DIR/ub-incorrect-vtable.rs:22:1
14-
|
15-
LL | const INVALID_VTABLE_SIZE: &dyn Trait =
16-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
8+
--> $DIR/ub-incorrect-vtable.rs:23:14
179
|
18-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
19-
= note: the raw bytes of the constant (size: 8, align: 4) {
20-
╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼ │ ╾──╼╾──╼
21-
}
10+
LL | unsafe { std::mem::transmute((&92u8, &[1usize, usize::MAX, 1usize])) };
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_SIZE` failed here
2212

23-
error[E0080]: constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
24-
--> $DIR/ub-incorrect-vtable.rs:31:1
13+
error[E0080]: constructing invalid value at .0: encountered ALLOC4<imm>, but expected a vtable pointer
14+
--> $DIR/ub-incorrect-vtable.rs:32:14
2515
|
26-
LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
27-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
28-
|
29-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
30-
= note: the raw bytes of the constant (size: 8, align: 4) {
31-
╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼ │ ╾──╼╾──╼
32-
}
16+
LL | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1000usize))) };
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_ALIGNMENT_UB` failed here
3318

34-
error[E0080]: constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
35-
--> $DIR/ub-incorrect-vtable.rs:35:1
36-
|
37-
LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
38-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
19+
error[E0080]: constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
20+
--> $DIR/ub-incorrect-vtable.rs:36:14
3921
|
40-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
41-
= note: the raw bytes of the constant (size: 8, align: 4) {
42-
╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──╼╾──╼
43-
}
22+
LL | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), usize::MAX, 1usize))) };
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_SIZE_UB` failed here
4424

45-
error[E0080]: constructing invalid value at .0: encountered ALLOC9<imm>, but expected a vtable pointer
46-
--> $DIR/ub-incorrect-vtable.rs:40:1
47-
|
48-
LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
25+
error[E0080]: constructing invalid value at .0: encountered ALLOC6<imm>, but expected a vtable pointer
26+
--> $DIR/ub-incorrect-vtable.rs:41:14
5027
|
51-
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
52-
= note: the raw bytes of the constant (size: 8, align: 4) {
53-
╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──╼╾──╼
54-
}
28+
LL | unsafe { std::mem::transmute((&92u8, &(drop_me as fn(*mut usize), 1usize, 1usize))) };
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `INVALID_VTABLE_UB` failed here
5530

5631
error[E0080]: constructing invalid value at .1: encountered a dangling reference (going beyond the bounds of its allocation)
5732
--> $DIR/ub-incorrect-vtable.rs:86:1
@@ -61,7 +36,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
6136
|
6237
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
6338
= note: the raw bytes of the constant (size: 8, align: 4) {
64-
ALLOC10<imm>╼ ╾ALLOC11╼ │ ╾──╼╾──╼
39+
ALLOC0<imm>╼ ╾ALLOC1╼ │ ╾──╼╾──╼
6540
}
6641

6742
error: aborting due to 6 previous errors

0 commit comments

Comments
 (0)