Skip to content

Commit 2dcbaea

Browse files
committed
Validate transmutes in CTFE
1 parent 0b9913c commit 2dcbaea

34 files changed

Lines changed: 548 additions & 929 deletions

compiler/rustc_const_eval/src/interpret/cast.rs

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

152152
self.copy_op_allow_transmute(src, dest)?;
153+
154+
// Even if general validation is disabled, transmutes should always check their result.
155+
if !M::enforce_validity(self, dest.layout) {
156+
self.validate_operand(
157+
&dest,
158+
M::enforce_validity_recursively(self, dest.layout),
159+
/*reset_provenance_and_padding*/ true,
160+
)?;
161+
}
153162
}
154163
}
155164
interp_ok(())

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,10 @@ pub trait Machine<'tcx>: Sized {
146146
/// already been checked before.
147147
const ALL_CONSTS_ARE_PRECHECKED: bool = true;
148148

149+
/// Whether to validate the result of various operations like transmutes
150+
/// irrespective of [Machine::enforce_validity]
151+
const VALIDATE_UNSAFE_OUTPUTS: bool = true;
152+
149153
/// Whether memory accesses should be alignment-checked.
150154
fn enforce_alignment(ecx: &InterpCx<'tcx, Self>) -> bool;
151155

src/tools/miri/src/machine.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,7 @@ impl<'tcx> Machine<'tcx> for MiriMachine<'tcx> {
11071107
MonoHashMap<AllocId, (MemoryKind, Allocation<Provenance, Self::AllocExtra, Self::Bytes>)>;
11081108

11091109
const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
1110+
const VALIDATE_UNSAFE_OUTPUTS: bool = false;
11101111

11111112
const PANIC_ON_ALLOC_FAIL: bool = false;
11121113

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

Lines changed: 75 additions & 80 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
@@ -31,10 +31,10 @@ const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
3131
//~^ ERROR expected a valid enum tag
3232

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

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

3939
// # simple enum with discriminant 2
4040

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

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

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

6969
// # valid discriminant for uninhabited variant
7070

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:30:1
2+
--> $DIR/ub-enum.rs:30: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:33:1
7+
error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
8+
--> $DIR/ub-enum.rs:33: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:36:1
16+
error[E0080]: constructing invalid value at .0.<enum-tag>: encountered a pointer, but expected an integer
17+
--> $DIR/ub-enum.rs:36: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:48:1
26+
--> $DIR/ub-enum.rs:48: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:50:1
31+
error[E0080]: constructing invalid value at .<enum-tag>: encountered a pointer, but expected an integer
32+
--> $DIR/ub-enum.rs:50: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:53:1
40+
error[E0080]: constructing invalid value at .0.<enum-tag>: encountered a pointer, but expected an integer
41+
--> $DIR/ub-enum.rs:53: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
@@ -66,47 +56,32 @@ LL | const BAD_ENUM2_UNDEF: Enum2 = unsafe { MaybeUninit { uninit: () }.init };
6656
HEX_DUMP
6757
}
6858

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

7868
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
79-
--> $DIR/ub-enum.rs:83:1
69+
--> $DIR/ub-enum.rs:83:62
8070
|
8171
LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
82-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
83-
|
84-
= 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.
85-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
86-
HEX_DUMP
87-
}
72+
| ^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_VARIANT1` failed here
8873

8974
error[E0080]: constructing invalid value at .<enum-tag>: encountered an uninhabited enum variant
90-
--> $DIR/ub-enum.rs:85:1
75+
--> $DIR/ub-enum.rs:85:62
9176
|
9277
LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
93-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
94-
|
95-
= 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.
96-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
97-
HEX_DUMP
98-
}
78+
| ^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_UNINHABITED_VARIANT2` failed here
9979

100-
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`)
101-
--> $DIR/ub-enum.rs:93:1
80+
error[E0080]: constructing invalid value: encountered 0xffffffff, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
81+
--> $DIR/ub-enum.rs:93:67
10282
|
10383
LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
104-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
105-
|
106-
= 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.
107-
= note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
108-
HEX_DUMP
109-
}
84+
| ^^^^^^^^^^^^^^^^^^^^^ evaluation of `BAD_OPTION_CHAR` failed here
11085

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

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

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,38 @@
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
8+
--> $DIR/ub-incorrect-vtable.rs:23:14
149
|
1510
LL | const INVALID_VTABLE_SIZE: &dyn Trait =
1611
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
1712
|
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.
13+
= 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.
1914
= note: the raw bytes of the constant (size: 8, align: 4) {
2015
╾ALLOC2<imm>╼ ╾ALLOC3<imm>╼ │ ╾──╼╾──╼
2116
}
2217

2318
error[E0080]: constructing invalid value at .0: encountered ALLOC5<imm>, but expected a vtable pointer
24-
--> $DIR/ub-incorrect-vtable.rs:31:1
19+
--> $DIR/ub-incorrect-vtable.rs:36:14
2520
|
2621
LL | const INVALID_VTABLE_ALIGNMENT_UB: W<&dyn Trait> =
2722
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
2823
|
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.
24+
= 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.
3025
= note: the raw bytes of the constant (size: 8, align: 4) {
3126
╾ALLOC4<imm>╼ ╾ALLOC5<imm>╼ │ ╾──╼╾──╼
3227
}
3328

34-
error[E0080]: constructing invalid value at .0: encountered ALLOC7<imm>, but expected a vtable pointer
35-
--> $DIR/ub-incorrect-vtable.rs:35:1
29+
error[E0080]: constructing invalid value at .0: encountered ALLOC6<imm>, but expected a vtable pointer
30+
--> $DIR/ub-incorrect-vtable.rs:41:14
3631
|
3732
LL | const INVALID_VTABLE_SIZE_UB: W<&dyn Trait> =
3833
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
3934
|
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.
35+
= 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.
4136
= note: the raw bytes of the constant (size: 8, align: 4) {
4237
╾ALLOC6<imm>╼ ╾ALLOC7<imm>╼ │ ╾──╼╾──╼
4338
}
@@ -48,7 +43,7 @@ error[E0080]: constructing invalid value at .0: encountered ALLOC9<imm>, but exp
4843
LL | const INVALID_VTABLE_UB: W<&dyn Trait> =
4944
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ it is undefined behavior to use this value
5045
|
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.
46+
= 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.
5247
= note: the raw bytes of the constant (size: 8, align: 4) {
5348
╾ALLOC8<imm>╼ ╾ALLOC9<imm>╼ │ ╾──╼╾──╼
5449
}
@@ -61,7 +56,7 @@ LL | const G: Wide = unsafe { Transmute { t: FOO }.u };
6156
|
6257
= 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.
6358
= note: the raw bytes of the constant (size: 8, align: 4) {
64-
ALLOC10<imm>╼ ╾ALLOC11╼ │ ╾──╼╾──╼
59+
ALLOC0<imm>╼ ╾ALLOC1╼ │ ╾──╼╾──╼
6560
}
6661

6762
error: aborting due to 6 previous errors

0 commit comments

Comments
 (0)