Skip to content

Commit 0f3e596

Browse files
committed
miri: detect too large dynamically sized objects
1 parent 72b2abf commit 0f3e596

File tree

2 files changed

+21
-13
lines changed

2 files changed

+21
-13
lines changed

src/librustc_mir/interpret/eval_context.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -442,27 +442,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
442442

443443
// Issue #27023: must add any necessary padding to `size`
444444
// (to make it a multiple of `align`) before returning it.
445-
//
446-
// Namely, the returned size should be, in C notation:
447-
//
448-
// `size + ((size & (align-1)) ? align : 0)`
449-
//
450-
// emulated via the semi-standard fast bit trick:
451-
//
452-
// `(size + (align-1)) & -align`
453-
454-
Ok(Some((size.align_to(align), align)))
445+
let size = size.align_to(align);
446+
447+
// Check if this brought us over the size limit.
448+
if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
449+
throw_ub_format!("wide pointer metadata contains invalid information: \
450+
total size is bigger than largest supported object");
451+
}
452+
Ok(Some((size, align)))
455453
}
456454
ty::Dynamic(..) => {
457455
let vtable = metadata.expect("dyn trait fat ptr must have vtable");
458-
// the second entry in the vtable is the dynamic size of the object.
456+
// Read size and align from vtable (already checks size).
459457
Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
460458
}
461459

462460
ty::Slice(_) | ty::Str => {
463461
let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?;
464462
let elem = layout.field(self, 0)?;
465-
Ok(Some((elem.size * len, elem.align.abi)))
463+
464+
// Make sure the slice is not too big.
465+
let size = elem.size.checked_mul(len, &*self.tcx)
466+
.ok_or_else(|| err_ub_format!("invalid slice: \
467+
total size is bigger than largest supported object"))?;
468+
Ok(Some((size, elem.align.abi)))
466469
}
467470

468471
ty::Foreign(_) => {

src/librustc_mir/interpret/traits.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rustc::ty::{self, Ty, Instance, TypeFoldable};
2-
use rustc::ty::layout::{Size, Align, LayoutOf};
2+
use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout};
33
use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,};
44

55
use super::{InterpCx, Machine, MemoryKind, FnVal};
@@ -151,6 +151,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
151151
vtable.offset(pointer_size * 2, self)?,
152152
)?.not_undef()?;
153153
let align = self.force_bits(align, pointer_size)? as u64;
154+
155+
if size >= self.tcx.data_layout().obj_size_bound() {
156+
throw_ub_format!("invalid vtable: \
157+
size is bigger than largest supported object");
158+
}
154159
Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
155160
}
156161
}

0 commit comments

Comments
 (0)