1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
//@ stderr-per-bitwidth
//@ ignore-endian-big
// ignore-tidy-linelength
//@ normalize-stderr: "╾─*ALLOC[0-9]+(\+[a-z0-9]+)?(<imm>)?─*╼" -> "╾ALLOC_ID$1╼"
//@ dont-require-annotations: NOTE
#![allow(invalid_value, unnecessary_transmutes)]
#![feature(never_type, rustc_attrs, ptr_metadata, slice_from_ptr_range, const_slice_from_ptr_range)]
use std::mem;
use std::alloc::Layout;
use std::ptr::NonNull;
use std::num::NonZero;
use std::slice::{from_ptr_range, from_raw_parts};
// # Bad enums and chars
#[repr(usize)]
#[derive(Copy, Clone)]
enum Enum {
A = 0,
}
const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) };
//~^ ERROR constructing invalid value
#[repr(usize)]
#[derive(Copy, Clone)]
enum Enum2 {
A = 2,
}
const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
#[derive(Copy, Clone)]
enum Never {}
// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do*
// have a discriminant.
enum UninhDiscriminant {
A,
B(!),
C,
D(Never),
}
const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) };
//~^ ERROR constructing invalid value
const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
//~^ ERROR constructing invalid value
// Invalid enum field content (mostly to test printing of paths for enum tuple
// variants and tuples).
// Need to create something which does not clash with enum layout optimizations.
const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
//~^ ERROR constructing invalid value
// # Bad pointers and references
const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
//~^ ERROR constructing invalid value
const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
#[rustc_layout_scalar_valid_range_start(10)]
#[rustc_layout_scalar_valid_range_end(30)]
struct RestrictedRange1(u32);
const BAD_RANGE1: RestrictedRange1 = unsafe { RestrictedRange1(42) };
//~^ ERROR constructing invalid value
#[rustc_layout_scalar_valid_range_start(30)]
#[rustc_layout_scalar_valid_range_end(10)]
struct RestrictedRange2(u32);
const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
//~^ ERROR constructing invalid value
const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {
//~^ ERROR constructing invalid value
let x: &dyn Send = &42;
let meta = std::ptr::metadata(x);
mem::transmute((0_usize, meta))
};
const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) };
//~^ ERROR constructing invalid value: encountered an unaligned reference (required 2 byte alignment but found 1)
const UNALIGNED_BOX: Box<u16> = unsafe { mem::transmute(&[0u8; 4]) };
//~^ ERROR constructing invalid value: encountered an unaligned box (required 2 byte alignment but found 1)
const NULL: &u16 = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
const NULL_BOX: Box<u16> = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) };
//~^ ERROR constructing invalid value
const USIZE_AS_BOX: Box<u8> = unsafe { mem::transmute(1337usize) };
//~^ ERROR constructing invalid value
const NULL_FN_PTR: fn() = unsafe { mem::transmute(0usize) };
//~^ ERROR constructing invalid value
const DANGLING_FN_PTR: fn() = unsafe { mem::transmute(13usize) };
//~^ ERROR constructing invalid value
const DATA_FN_PTR: fn() = unsafe { mem::transmute(&13) };
//~^ ERROR constructing invalid value
#[derive(Copy, Clone)]
enum Bar {}
const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) };
//~^ ERROR constructing invalid value
/// A newtype wrapper to prevent MIR generation from inserting reborrows that would affect the error
/// message.
#[repr(transparent)]
struct W<T>(T);
#[repr(C)]
union MaybeUninit<T: Copy> {
uninit: (),
init: T,
}
trait Trait {}
impl Trait for bool {}
// custom unsized type
struct MyStr(str);
// custom unsized type with sized fields
struct MySlice<T: ?Sized>(bool, T);
type MySliceBool = MySlice<[bool]>;
const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR constructing invalid value
const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },);
//~^ ERROR constructing invalid value
const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) };
//~^ ERROR constructing invalid value
const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
//~^ ERROR constructing invalid value
const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit::<u8> { uninit: () }]) };
//~^ ERROR constructing invalid value
const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
//~^ ERROR: constructing invalid value
// # slice
const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR constructing invalid value
const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
//~^ ERROR constructing invalid value
// bad slice box: length too big
const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
//~^ ERROR constructing invalid value
// bad data *inside* the slice
const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
//~^ ERROR encountered 0x03, but expected a boolean
// bad: sized field is not okay
const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
//~^ ERROR encountered 0x03, but expected a boolean
// bad: unsized part is not okay
const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
//~^ ERROR encountered 0x03, but expected a boolean
// bad trait object
const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
//~^ ERROR expected a vtable
// bad trait object
const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
//~^ ERROR expected a vtable
// bad trait object
const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
//~^ ERROR expected a vtable
const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
//~^ ERROR expected a vtable
// bad data *inside* the trait object
const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
//~^ ERROR expected a boolean
const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
//~^ ERROR null pointer
const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
//~^ ERROR vtable
// Uninhabited types
const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR constructing invalid value
const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; //~ ERROR constructing invalid value
const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; //~ ERROR constructing invalid value
// Reading uninitialized data
pub static S4: &[u8] = unsafe { from_raw_parts((&D1) as *const _ as _, 1) };
//~^ ERROR: constructing invalid value
// Reinterpret pointers as integers (UB in CTFE.)
pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
//~^ ERROR: constructing invalid value
// Layout mismatch
pub static S6: &[bool] = unsafe { from_raw_parts((&D0) as *const _ as _, 4) };
//~^ ERROR: constructing invalid value
// Reading padding is not ok
pub static S7: &[u16] = unsafe {
//~^ ERROR: constructing invalid value
let ptr = (&D2 as *const Struct as *const u16).add(1);
from_raw_parts(ptr, 4)
};
pub static R4: &[u8] = unsafe {
//~^ ERROR: constructing invalid value
let ptr = (&D1) as *const mem::MaybeUninit<&u32> as *const u8;
from_ptr_range(ptr..ptr.add(1))
};
pub static R5: &[u8] = unsafe {
//~^ ERROR: constructing invalid value
let ptr = &D3 as *const &u32;
from_ptr_range(ptr.cast()..ptr.add(1).cast())
};
pub static R6: &[bool] = unsafe {
//~^ ERROR: constructing invalid value
let ptr = &D0 as *const u32 as *const bool;
from_ptr_range(ptr..ptr.add(4))
};
const D0: u32 = 0x11111111; // Constant chosen for endianness-independent behavior.
const D1: mem::MaybeUninit<&u32> = mem::MaybeUninit::uninit();
const D2: Struct = Struct { a: 1, b: 2, c: 3, d: 4 };
const D3: &u32 = &42;
#[repr(C)]
struct Struct {
a: u8,
// _pad: [mem::MaybeUninit<u8>; 3]
b: u32,
c: u16,
d: u8,
// _pad: [mem::MaybeUninit<u8>; 1]
}
fn main() {}
|