Skip to content

Commit cdf178f

Browse files
authored
Rollup merge of #95388 - RalfJung:rust-val-limit, r=oli-obk
interpret: make isize::MAX the limit for dynamic value sizes We are currently enforcing `data_layout.obj_size_bound()` as the maximal dynamic size of a Rust value (including for `size_of_val_raw`), but that does not match the docs. In particular, Miri currently falsely says that this code has UB: ```rust #![feature(layout_for_ptr)] fn main() { let size = isize::MAX as usize; // Creating a raw slice of size isize::MAX and asking for its size is okay. let s = std::ptr::slice_from_raw_parts(1usize as *const u8, size); assert_eq!(size, unsafe { std::mem::size_of_val_raw(s) }); } ```
2 parents 40be7d3 + cb0d15b commit cdf178f

File tree

8 files changed

+95
-52
lines changed

8 files changed

+95
-52
lines changed

compiler/rustc_const_eval/src/interpret/eval_context.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayou
2323

2424
use super::{
2525
AllocCheck, AllocId, GlobalId, Immediate, InterpErrorInfo, InterpResult, MPlaceTy, Machine,
26-
MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer, Provenance,
27-
Scalar, ScalarMaybeUninit, StackPopJump,
26+
MemPlace, MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, Pointer,
27+
PointerArithmetic, Provenance, Scalar, ScalarMaybeUninit, StackPopJump,
2828
};
2929
use crate::transform::validate::equal_up_to_regions;
3030

@@ -678,7 +678,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
678678
let size = size.align_to(align);
679679

680680
// Check if this brought us over the size limit.
681-
if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
681+
if size > self.max_size_of_val() {
682682
throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
683683
}
684684
Ok(Some((size, align)))
@@ -694,9 +694,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
694694
let elem = layout.field(self, 0);
695695

696696
// Make sure the slice is not too big.
697-
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
698-
err_ub!(InvalidMeta("slice is bigger than largest supported object"))
699-
})?;
697+
let size = elem.size.bytes().saturating_mul(len); // we rely on `max_size_of_val` being smaller than `u64::MAX`.
698+
let size = Size::from_bytes(size);
699+
if size > self.max_size_of_val() {
700+
throw_ub!(InvalidMeta("slice is bigger than largest supported object"));
701+
}
700702
Ok(Some((size, elem.align.abi)))
701703
}
702704

compiler/rustc_const_eval/src/interpret/intrinsics.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
531531
) -> InterpResult<'tcx, Pointer<Option<M::PointerTag>>> {
532532
// We cannot overflow i64 as a type's size must be <= isize::MAX.
533533
let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
534-
// The computed offset, in bytes, cannot overflow an isize.
534+
// The computed offset, in bytes, must not overflow an isize.
535+
// `checked_mul` enforces a too small bound, but no actual allocation can be big enough for
536+
// the difference to be noticeable.
535537
let offset_bytes =
536538
offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
537539
// The offset being in bounds cannot rely on "wrapping around" the address space.
@@ -563,6 +565,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
563565
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
564566
let layout = self.layout_of(src.layout.ty.builtin_deref(true).unwrap().ty)?;
565567
let (size, align) = (layout.size, layout.align.abi);
568+
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
569+
// but no actual allocation can be big enough for the difference to be noticeable.
566570
let size = size.checked_mul(count, self).ok_or_else(|| {
567571
err_ub_format!(
568572
"overflow computing total size of `{}`",
@@ -588,6 +592,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
588592
let byte = self.read_scalar(&byte)?.to_u8()?;
589593
let count = self.read_scalar(&count)?.to_machine_usize(self)?;
590594

595+
// `checked_mul` enforces a too small bound (the correct one would probably be machine_isize_max),
596+
// but no actual allocation can be big enough for the difference to be noticeable.
591597
let len = layout
592598
.size
593599
.checked_mul(count, self)

compiler/rustc_const_eval/src/interpret/traits.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
110110
.read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_SIZE).unwrap())?
111111
.check_init()?;
112112
let size = size.to_machine_usize(self)?;
113+
let size = Size::from_bytes(size);
113114
let align = vtable
114115
.read_ptr_sized(pointer_size * u64::try_from(COMMON_VTABLE_ENTRIES_ALIGN).unwrap())?
115116
.check_init()?;
116117
let align = align.to_machine_usize(self)?;
117118
let align = Align::from_bytes(align).map_err(|e| err_ub!(InvalidVtableAlignment(e)))?;
118119

119-
if size >= self.tcx.data_layout.obj_size_bound() {
120+
if size > self.max_size_of_val() {
120121
throw_ub!(InvalidVtableSize);
121122
}
122-
Ok((Size::from_bytes(size), align))
123+
Ok((size, align))
123124
}
124125

125126
pub fn read_new_vtable_after_trait_upcasting_from_vtable(

compiler/rustc_middle/src/mir/interpret/pointer.rs

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ pub trait PointerArithmetic: HasDataLayout {
1818
self.data_layout().pointer_size
1919
}
2020

21+
#[inline(always)]
22+
fn max_size_of_val(&self) -> Size {
23+
Size::from_bytes(self.machine_isize_max())
24+
}
25+
2126
#[inline]
2227
fn machine_usize_max(&self) -> u64 {
2328
self.pointer_size().unsigned_int_max().try_into().unwrap()

src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr

+32-21
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,17 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) };
104104
error[E0080]: it is undefined behavior to use this value
105105
--> $DIR/ub-wide-ptr.rs:71:1
106106
|
107+
LL | const SLICE_TOO_LONG_OVERFLOW: &[u32] = unsafe { mem::transmute((&42u32, isize::MAX)) };
108+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object
109+
|
110+
= 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.
111+
= note: the raw bytes of the constant (size: 8, align: 4) {
112+
╾─allocN─╼ ff ff ff 7f │ ╾──╼....
113+
}
114+
115+
error[E0080]: it is undefined behavior to use this value
116+
--> $DIR/ub-wide-ptr.rs:74:1
117+
|
107118
LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
108119
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
109120
|
@@ -113,7 +124,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) };
113124
}
114125

115126
error[E0080]: it is undefined behavior to use this value
116-
--> $DIR/ub-wide-ptr.rs:74:1
127+
--> $DIR/ub-wide-ptr.rs:77:1
117128
|
118129
LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) };
119130
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (going beyond the bounds of its allocation)
@@ -124,7 +135,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us
124135
}
125136

126137
error[E0080]: it is undefined behavior to use this value
127-
--> $DIR/ub-wide-ptr.rs:77:1
138+
--> $DIR/ub-wide-ptr.rs:80:1
128139
|
129140
LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) };
130141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer
@@ -135,7 +146,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)
135146
}
136147

137148
error[E0080]: it is undefined behavior to use this value
138-
--> $DIR/ub-wide-ptr.rs:81:1
149+
--> $DIR/ub-wide-ptr.rs:84:1
139150
|
140151
LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
141152
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>[0]: encountered 0x03, but expected a boolean
@@ -146,29 +157,29 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }];
146157
}
147158

148159
error[E0080]: it is undefined behavior to use this value
149-
--> $DIR/ub-wide-ptr.rs:87:1
160+
--> $DIR/ub-wide-ptr.rs:90:1
150161
|
151162
LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]);
152163
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.0: encountered 0x03, but expected a boolean
153164
|
154165
= 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.
155166
= note: the raw bytes of the constant (size: 4, align: 4) {
156-
allocN─╼ │ ╾──╼
167+
╾allocN─╼ │ ╾──╼
157168
}
158169

159170
error[E0080]: it is undefined behavior to use this value
160-
--> $DIR/ub-wide-ptr.rs:90:1
171+
--> $DIR/ub-wide-ptr.rs:93:1
161172
|
162173
LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]);
163174
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.1[0]: encountered 0x03, but expected a boolean
164175
|
165176
= 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.
166177
= note: the raw bytes of the constant (size: 4, align: 4) {
167-
allocN─╼ │ ╾──╼
178+
╾allocN─╼ │ ╾──╼
168179
}
169180

170181
error[E0080]: it is undefined behavior to use this value
171-
--> $DIR/ub-wide-ptr.rs:97:1
182+
--> $DIR/ub-wide-ptr.rs:100:1
172183
|
173184
LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe {
174185
LL | |
@@ -183,7 +194,7 @@ LL | | };
183194
}
184195

185196
error[E0080]: it is undefined behavior to use this value
186-
--> $DIR/ub-wide-ptr.rs:105:1
197+
--> $DIR/ub-wide-ptr.rs:108:1
187198
|
188199
LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u8))) };
189200
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -194,7 +205,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: W<&dyn Trait> = unsafe { mem::transmute(W((
194205
}
195206

196207
error[E0080]: it is undefined behavior to use this value
197-
--> $DIR/ub-wide-ptr.rs:108:1
208+
--> $DIR/ub-wide-ptr.rs:111:1
198209
|
199210
LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &3u64))) };
200211
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered too small vtable
@@ -205,7 +216,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: W<&dyn Trait> = unsafe { mem::transmute(W((
205216
}
206217

207218
error[E0080]: it is undefined behavior to use this value
208-
--> $DIR/ub-wide-ptr.rs:111:1
219+
--> $DIR/ub-wide-ptr.rs:114:1
209220
|
210221
LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, 4usize))) };
211222
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered dangling vtable pointer in wide pointer
@@ -216,7 +227,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: W<&dyn Trait> = unsafe { mem::transmute(W((&92u
216227
}
217228

218229
error[E0080]: it is undefined behavior to use this value
219-
--> $DIR/ub-wide-ptr.rs:113:1
230+
--> $DIR/ub-wide-ptr.rs:116:1
220231
|
221232
LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) };
222233
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer
@@ -227,7 +238,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92
227238
}
228239

229240
error[E0080]: it is undefined behavior to use this value
230-
--> $DIR/ub-wide-ptr.rs:115:1
241+
--> $DIR/ub-wide-ptr.rs:118:1
231242
|
232243
LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) };
233244
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -238,7 +249,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92
238249
}
239250

240251
error[E0080]: it is undefined behavior to use this value
241-
--> $DIR/ub-wide-ptr.rs:117:1
252+
--> $DIR/ub-wide-ptr.rs:120:1
242253
|
243254
LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) };
244255
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -249,7 +260,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u
249260
}
250261

251262
error[E0080]: it is undefined behavior to use this value
252-
--> $DIR/ub-wide-ptr.rs:119:1
263+
--> $DIR/ub-wide-ptr.rs:122:1
253264
|
254265
LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::transmute(W((&92u8, &[&42u8; 8]))) };
255266
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .0: encountered invalid drop function pointer in vtable (not pointing to a function)
@@ -260,7 +271,7 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: W<&dyn Trait> = unsafe { mem::trans
260271
}
261272

262273
error[E0080]: it is undefined behavior to use this value
263-
--> $DIR/ub-wide-ptr.rs:123:1
274+
--> $DIR/ub-wide-ptr.rs:126:1
264275
|
265276
LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) };
266277
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed at .<deref>.<dyn-downcast>: encountered 0x03, but expected a boolean
@@ -271,7 +282,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
271282
}
272283

273284
error[E0080]: it is undefined behavior to use this value
274-
--> $DIR/ub-wide-ptr.rs:127:1
285+
--> $DIR/ub-wide-ptr.rs:130:1
275286
|
276287
LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
277288
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer
@@ -282,7 +293,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute
282293
}
283294

284295
error[E0080]: it is undefined behavior to use this value
285-
--> $DIR/ub-wide-ptr.rs:129:1
296+
--> $DIR/ub-wide-ptr.rs:132:1
286297
|
287298
LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
288299
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable
@@ -293,17 +304,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm
293304
}
294305

295306
error[E0080]: could not evaluate static initializer
296-
--> $DIR/ub-wide-ptr.rs:135:5
307+
--> $DIR/ub-wide-ptr.rs:138:5
297308
|
298309
LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
299310
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is not a valid pointer
300311

301312
error[E0080]: could not evaluate static initializer
302-
--> $DIR/ub-wide-ptr.rs:139:5
313+
--> $DIR/ub-wide-ptr.rs:142:5
303314
|
304315
LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
305316
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: allocN has size N, so pointer to 12 bytes starting at offset N is out-of-bounds
306317

307-
error: aborting due to 28 previous errors
318+
error: aborting due to 29 previous errors
308319

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

0 commit comments

Comments
 (0)