diff options
| author | Ralf Jung <post@ralfj.de> | 2019-08-27 12:54:46 +0200 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2019-08-30 07:44:51 +0200 |
| commit | 0f3e596c1d34b74c79133f3996d2c655a2cf8e66 (patch) | |
| tree | a31d3b8ec616499fc6976ec713fdcf91c5ce0e18 | |
| parent | 72b2abfd65ba024e12d7fe51852a309419f494d8 (diff) | |
| download | rust-0f3e596c1d34b74c79133f3996d2c655a2cf8e66.tar.gz rust-0f3e596c1d34b74c79133f3996d2c655a2cf8e66.zip | |
miri: detect too large dynamically sized objects
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 27 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/traits.rs | 7 |
2 files changed, 21 insertions, 13 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index ac01d436bdc..054b65f0e1a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -442,27 +442,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Issue #27023: must add any necessary padding to `size` // (to make it a multiple of `align`) before returning it. - // - // Namely, the returned size should be, in C notation: - // - // `size + ((size & (align-1)) ? align : 0)` - // - // emulated via the semi-standard fast bit trick: - // - // `(size + (align-1)) & -align` - - Ok(Some((size.align_to(align), align))) + let size = size.align_to(align); + + // Check if this brought us over the size limit. + if size.bytes() >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("wide pointer metadata contains invalid information: \ + total size is bigger than largest supported object"); + } + Ok(Some((size, align))) } ty::Dynamic(..) => { let vtable = metadata.expect("dyn trait fat ptr must have vtable"); - // the second entry in the vtable is the dynamic size of the object. + // Read size and align from vtable (already checks size). Ok(Some(self.read_size_and_align_from_vtable(vtable)?)) } ty::Slice(_) | ty::Str => { let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?; let elem = layout.field(self, 0)?; - Ok(Some((elem.size * len, elem.align.abi))) + + // Make sure the slice is not too big. + let size = elem.size.checked_mul(len, &*self.tcx) + .ok_or_else(|| err_ub_format!("invalid slice: \ + total size is bigger than largest supported object"))?; + Ok(Some((size, elem.align.abi))) } ty::Foreign(_) => { diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs index 34a10de7de7..10b767ebba1 100644 --- a/src/librustc_mir/interpret/traits.rs +++ b/src/librustc_mir/interpret/traits.rs @@ -1,5 +1,5 @@ use rustc::ty::{self, Ty, Instance, TypeFoldable}; -use rustc::ty::layout::{Size, Align, LayoutOf}; +use rustc::ty::layout::{Size, Align, LayoutOf, HasDataLayout}; use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,}; use super::{InterpCx, Machine, MemoryKind, FnVal}; @@ -151,6 +151,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { vtable.offset(pointer_size * 2, self)?, )?.not_undef()?; let align = self.force_bits(align, pointer_size)? as u64; + + if size >= self.tcx.data_layout().obj_size_bound() { + throw_ub_format!("invalid vtable: \ + size is bigger than largest supported object"); + } Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap())) } } |
