miri: detect too large dynamically sized objects
This commit is contained in:
parent
72b2abfd65
commit
0f3e596c1d
2 changed files with 20 additions and 12 deletions
|
@ -442,27 +442,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
|
|
||||||
// Issue #27023: must add any necessary padding to `size`
|
// Issue #27023: must add any necessary padding to `size`
|
||||||
// (to make it a multiple of `align`) before returning it.
|
// (to make it a multiple of `align`) before returning it.
|
||||||
//
|
let size = size.align_to(align);
|
||||||
// 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)))
|
// 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(..) => {
|
ty::Dynamic(..) => {
|
||||||
let vtable = metadata.expect("dyn trait fat ptr must have vtable");
|
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)?))
|
Ok(Some(self.read_size_and_align_from_vtable(vtable)?))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::Slice(_) | ty::Str => {
|
ty::Slice(_) | ty::Str => {
|
||||||
let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?;
|
let len = metadata.expect("slice fat ptr must have vtable").to_usize(self)?;
|
||||||
let elem = layout.field(self, 0)?;
|
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(_) => {
|
ty::Foreign(_) => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc::ty::{self, Ty, Instance, TypeFoldable};
|
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 rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic,};
|
||||||
|
|
||||||
use super::{InterpCx, Machine, MemoryKind, FnVal};
|
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)?,
|
vtable.offset(pointer_size * 2, self)?,
|
||||||
)?.not_undef()?;
|
)?.not_undef()?;
|
||||||
let align = self.force_bits(align, pointer_size)? as u64;
|
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()))
|
Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue