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