Skip to content

Commit 5c450de

Browse files
committed
fix validating arrays of ZSTs
Fixes rust-lang#54751
1 parent de79ea6 commit 5c450de

File tree

4 files changed

+43
-19
lines changed

4 files changed

+43
-19
lines changed

Diff for: src/librustc_mir/interpret/place.rs

+12
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ impl MemPlace {
131131
}
132132

133133
impl<'tcx> MPlaceTy<'tcx> {
134+
/// Produces a MemPlace that works for ZST but nothing else
135+
#[inline]
136+
pub fn dangling(layout: TyLayout<'tcx>, cx: impl HasDataLayout) -> Self {
137+
MPlaceTy {
138+
mplace: MemPlace::from_scalar_ptr(
139+
Scalar::from_uint(layout.align.abi(), cx.pointer_size()),
140+
layout.align
141+
),
142+
layout
143+
}
144+
}
145+
134146
#[inline]
135147
fn from_aligned_ptr(ptr: Pointer, layout: TyLayout<'tcx>) -> Self {
136148
MPlaceTy { mplace: MemPlace::from_ptr(ptr, layout.align), layout }

Diff for: src/librustc_mir/interpret/validity.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
365365
// The fields don't need to correspond to any bit pattern of the union's fields.
366366
// See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
367367
},
368-
layout::FieldPlacement::Array { stride, .. } if !dest.layout.is_zst() => {
369-
let dest = dest.to_mem_place(); // non-ZST array/slice/str cannot be immediate
368+
layout::FieldPlacement::Array { stride, .. } => {
369+
let dest = if dest.layout.is_zst() {
370+
// it's a ZST, the memory content cannot matter
371+
MPlaceTy::dangling(dest.layout, self)
372+
} else {
373+
// non-ZST array/slice/str cannot be immediate
374+
dest.to_mem_place()
375+
};
370376
match dest.layout.ty.sty {
371377
// Special handling for strings to verify UTF-8
372378
ty::Str => {
@@ -429,9 +435,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
429435
}
430436
}
431437
},
432-
layout::FieldPlacement::Array { .. } => {
433-
// An empty array. Nothing to do.
434-
}
435438
layout::FieldPlacement::Arbitrary { ref offsets, .. } => {
436439
for i in 0..offsets.len() {
437440
let field = self.operand_field(dest, i as u64)?;

Diff for: src/test/ui/consts/const-eval/ub-uninhabit.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,20 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
union Foo {
12-
a: usize,
13-
b: Bar,
14-
c: &'static Bar,
15-
}
11+
#![feature(const_transmute)]
12+
13+
use std::mem;
1614

1715
#[derive(Copy, Clone)]
1816
enum Bar {}
1917

20-
const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b };
18+
const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
19+
//~^ ERROR this constant likely exhibits undefined behavior
20+
21+
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
2122
//~^ ERROR this constant likely exhibits undefined behavior
2223

23-
const BAD_BAD_REF: &Bar = unsafe { Foo { a: 1 }.c };
24+
const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
2425
//~^ ERROR this constant likely exhibits undefined behavior
2526

2627
fn main() {

Diff for: src/test/ui/consts/const-eval/ub-uninhabit.stderr

+15-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
error[E0080]: this constant likely exhibits undefined behavior
2-
--> $DIR/ub-uninhabit.rs:20:1
2+
--> $DIR/ub-uninhabit.rs:18:1
33
|
4-
LL | const BAD_BAD_BAD: Bar = unsafe { Foo { a: 1 }.b };
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
4+
LL | const BAD_BAD_BAD: Bar = unsafe { mem::transmute(()) };
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type
66
|
77
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
88

99
error[E0080]: this constant likely exhibits undefined behavior
10-
--> $DIR/ub-uninhabit.rs:23:1
10+
--> $DIR/ub-uninhabit.rs:21:1
1111
|
12-
LL | const BAD_BAD_REF: &Bar = unsafe { Foo { a: 1 }.c };
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
12+
LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .<deref>
1414
|
1515
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
1616

17-
error: aborting due to 2 previous errors
17+
error[E0080]: this constant likely exhibits undefined behavior
18+
--> $DIR/ub-uninhabit.rs:24:1
19+
|
20+
LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { mem::transmute(()) };
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at [0]
22+
|
23+
= note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior
24+
25+
error: aborting due to 3 previous errors
1826

1927
For more information about this error, try `rustc --explain E0080`.

0 commit comments

Comments
 (0)