Auto merge of #1845 - Smittyvb:fix-after-mir-alloc-oom, r=RalfJung

Make work with latest rustc

Cc https://github.com/rust-lang/rust/issues/86863, which was caused by PR https://github.com/rust-lang/rust/pull/86255.
This commit is contained in:
bors 2021-07-04 20:35:34 +00:00
commit 15e81a94b1
11 changed files with 44 additions and 34 deletions

View File

@ -1 +1 @@
46ae6ee65df19c6a3fb683499c1203e749975e60
39e20f1ae5f13451eb35247808d6a2527cb7d060

View File

@ -169,7 +169,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
// Make space for `0` terminator.
let size = u64::try_from(arg.len()).unwrap().checked_add(1).unwrap();
let arg_type = tcx.mk_array(tcx.types.u8, size);
let arg_place = ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Machine.into());
let arg_place =
ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Machine.into())?;
ecx.write_os_str_to_c_str(OsStr::new(arg), arg_place.ptr, size)?;
argvs.push(arg_place.ptr);
}
@ -177,7 +178,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
let argvs_layout = ecx.layout_of(
tcx.mk_array(tcx.mk_imm_ptr(tcx.types.u8), u64::try_from(argvs.len()).unwrap()),
)?;
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into());
let argvs_place = ecx.allocate(argvs_layout, MiriMemoryKind::Machine.into())?;
for (idx, arg) in argvs.into_iter().enumerate() {
let place = ecx.mplace_field(&argvs_place, idx)?;
ecx.write_scalar(arg, &place.into())?;
@ -188,14 +189,14 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
// Store `argc` and `argv` for macOS `_NSGetArg{c,v}`.
{
let argc_place =
ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into());
ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into())?;
ecx.write_scalar(argc, &argc_place.into())?;
ecx.machine.argc = Some(argc_place.ptr);
let argv_place = ecx.allocate(
ecx.layout_of(tcx.mk_imm_ptr(tcx.types.unit))?,
MiriMemoryKind::Machine.into(),
);
)?;
ecx.write_scalar(argv, &argv_place.into())?;
ecx.machine.argv = Some(argv_place.ptr);
}
@ -214,7 +215,8 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
let cmd_utf16: Vec<u16> = cmd.encode_utf16().collect();
let cmd_type = tcx.mk_array(tcx.types.u16, u64::try_from(cmd_utf16.len()).unwrap());
let cmd_place = ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into());
let cmd_place =
ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Machine.into())?;
ecx.machine.cmd_line = Some(cmd_place.ptr);
// Store the UTF-16 string. We just allocated so we know the bounds are fine.
for (idx, &c) in cmd_utf16.iter().enumerate() {
@ -226,7 +228,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
};
// Return place (in static memory so that it does not count as leak).
let ret_place = ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into());
let ret_place = ecx.allocate(ecx.machine.layouts.isize, MiriMemoryKind::Machine.into())?;
// Call start function.
ecx.call_function(
start_instance,

View File

@ -440,7 +440,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
} else {
// Allocate new place, set initial value to 0.
let errno_layout = this.machine.layouts.u32;
let errno_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into());
let errno_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
this.write_scalar(Scalar::from_u32(0), &errno_place.into())?;
this.active_thread_mut().last_error = Some(errno_place);
Ok(errno_place)

View File

@ -199,7 +199,7 @@ impl MemoryExtra {
// "__cxa_thread_atexit_impl"
// This should be all-zero, pointer-sized.
let layout = this.machine.layouts.usize;
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into());
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
this.write_scalar(Scalar::from_machine_usize(0, this), &place.into())?;
Self::add_extern_static(this, "__cxa_thread_atexit_impl", place.ptr);
// "environ"
@ -213,7 +213,7 @@ impl MemoryExtra {
// "_tls_used"
// This is some obscure hack that is part of the Windows TLS story. It's a `u8`.
let layout = this.machine.layouts.u8;
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into());
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
this.write_scalar(Scalar::from_u8(0), &place.into())?;
Self::add_extern_static(this, "_tls_used", place.ptr);
}
@ -377,6 +377,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
const PANIC_ON_ALLOC_FAIL: bool = false;
#[inline(always)]
fn enforce_alignment(memory_extra: &MemoryExtra) -> bool {
memory_extra.check_alignment != AlignmentCheck::None

View File

@ -57,7 +57,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let array_ty = tcx.mk_array(ptr_ty, ptrs.len().try_into().unwrap());
// Write pointers into array
let alloc = this.allocate(this.layout_of(array_ty).unwrap(), MiriMemoryKind::Rust.into());
let alloc =
this.allocate(this.layout_of(array_ty).unwrap(), MiriMemoryKind::Rust.into())?;
for (i, ptr) in ptrs.into_iter().enumerate() {
let place = this.mplace_index(&alloc, i as u64)?;
this.write_immediate_to_mplace(ptr.into(), &place)?;

View File

@ -88,7 +88,7 @@ fn alloc_env_var_as_c_str<'mir, 'tcx>(
let mut name_osstring = name.to_os_string();
name_osstring.push("=");
name_osstring.push(value);
Ok(ecx.alloc_os_str_as_c_str(name_osstring.as_os_str(), MiriMemoryKind::Env.into()))
ecx.alloc_os_str_as_c_str(name_osstring.as_os_str(), MiriMemoryKind::Env.into())
}
fn alloc_env_var_as_wide_str<'mir, 'tcx>(
@ -99,7 +99,7 @@ fn alloc_env_var_as_wide_str<'mir, 'tcx>(
let mut name_osstring = name.to_os_string();
name_osstring.push("=");
name_osstring.push(value);
Ok(ecx.alloc_os_str_as_wide_str(name_osstring.as_os_str(), MiriMemoryKind::Env.into()))
ecx.alloc_os_str_as_wide_str(name_osstring.as_os_str(), MiriMemoryKind::Env.into())
}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@ -179,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
}
// Allocate environment block & Store environment variables to environment block.
// Final null terminator(block terminator) is added by `alloc_os_str_to_wide_str`.
let envblock_ptr = this.alloc_os_str_as_wide_str(&env_vars, MiriMemoryKind::Env.into());
let envblock_ptr = this.alloc_os_str_as_wide_str(&env_vars, MiriMemoryKind::Env.into())?;
// If the function succeeds, the return value is a pointer to the environment block of the current process.
Ok(envblock_ptr.into())
}
@ -442,7 +442,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// No `environ` allocated yet, let's do that.
// This is memory backing an extern static, hence `ExternStatic`, not `Env`.
let layout = this.machine.layouts.usize;
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into());
let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?;
this.machine.env_vars.environ = Some(place);
}
@ -455,7 +455,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let tcx = this.tcx;
let vars_layout =
this.layout_of(tcx.mk_array(tcx.types.usize, u64::try_from(vars.len()).unwrap()))?;
let vars_place = this.allocate(vars_layout, MiriMemoryKind::Env.into());
let vars_place = this.allocate(vars_layout, MiriMemoryKind::Env.into())?;
for (idx, var) in vars.into_iter().enumerate() {
let place = this.mplace_field(&vars_place, idx)?;
this.write_scalar(var, &place.into())?;

View File

@ -67,18 +67,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Align::from_bytes(prev_power_of_two(size)).unwrap()
}
fn malloc(&mut self, size: u64, zero_init: bool, kind: MiriMemoryKind) -> Scalar<Tag> {
fn malloc(
&mut self,
size: u64,
zero_init: bool,
kind: MiriMemoryKind,
) -> InterpResult<'tcx, Scalar<Tag>> {
let this = self.eval_context_mut();
if size == 0 {
Scalar::null_ptr(this)
Ok(Scalar::null_ptr(this))
} else {
let align = this.min_align(size, kind);
let ptr = this.memory.allocate(Size::from_bytes(size), align, kind.into());
let ptr = this.memory.allocate(Size::from_bytes(size), align, kind.into())?;
if zero_init {
// We just allocated this, the access is definitely in-bounds.
this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(size as usize)).unwrap();
}
Scalar::Ptr(ptr)
Ok(Scalar::Ptr(ptr))
}
}
@ -104,7 +109,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Ok(Scalar::null_ptr(this))
} else {
let new_ptr =
this.memory.allocate(Size::from_bytes(new_size), new_align, kind.into());
this.memory.allocate(Size::from_bytes(new_size), new_align, kind.into())?;
Ok(Scalar::Ptr(new_ptr))
}
} else {
@ -331,7 +336,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
"malloc" => {
let &[ref size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
let size = this.read_scalar(size)?.to_machine_usize(this)?;
let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C);
let res = this.malloc(size, /*zero_init:*/ false, MiriMemoryKind::C)?;
this.write_scalar(res, dest)?;
}
"calloc" => {
@ -340,7 +345,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let len = this.read_scalar(len)?.to_machine_usize(this)?;
let size =
items.checked_mul(len).ok_or_else(|| err_ub_format!("overflow during calloc size computation"))?;
let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C);
let res = this.malloc(size, /*zero_init:*/ true, MiriMemoryKind::C)?;
this.write_scalar(res, dest)?;
}
"free" => {
@ -368,7 +373,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into(),
);
)?;
this.write_scalar(ptr, dest)?;
}
"__rust_alloc_zeroed" => {
@ -380,7 +385,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::Rust.into(),
);
)?;
// We just allocated this, the access is definitely in-bounds.
this.memory.write_bytes(ptr.into(), iter::repeat(0u8).take(usize::try_from(size).unwrap())).unwrap();
this.write_scalar(ptr, dest)?;

View File

@ -161,14 +161,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
&mut self,
os_str: &OsStr,
memkind: MemoryKind<MiriMemoryKind>,
) -> Pointer<Tag> {
) -> InterpResult<'tcx, Pointer<Tag>> {
let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
let this = self.eval_context_mut();
let arg_type = this.tcx.mk_array(this.tcx.types.u8, size);
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
assert!(self.write_os_str_to_c_str(os_str, arg_place.ptr, size).unwrap().0);
arg_place.ptr.assert_ptr()
Ok(arg_place.ptr.assert_ptr())
}
/// Allocate enough memory to store the given `OsStr` as a null-terminated sequence of `u16`.
@ -176,14 +176,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
&mut self,
os_str: &OsStr,
memkind: MemoryKind<MiriMemoryKind>,
) -> Pointer<Tag> {
) -> InterpResult<'tcx, Pointer<Tag>> {
let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
let this = self.eval_context_mut();
let arg_type = this.tcx.mk_array(this.tcx.types.u16, size);
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind);
let arg_place = this.allocate(this.layout_of(arg_type).unwrap(), memkind)?;
assert!(self.write_os_str_to_wide_str(os_str, arg_place.ptr, size).unwrap().0);
arg_place.ptr.assert_ptr()
Ok(arg_place.ptr.assert_ptr())
}
/// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.

View File

@ -159,7 +159,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
);
)?;
this.write_scalar(ptr, &ret.into())?;
}
this.write_null(dest)?;

View File

@ -47,7 +47,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
// pthread_join below) because the Rust standard library does not use
// it.
let ret_place =
this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into());
this.allocate(this.layout_of(this.tcx.types.usize)?, MiriMemoryKind::Machine.into())?;
this.call_function(
instance,

View File

@ -115,7 +115,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let flags = this.read_scalar(flags)?.to_u32()?;
let size = this.read_scalar(size)?.to_machine_usize(this)?;
let zero_init = (flags & 0x00000008) != 0; // HEAP_ZERO_MEMORY
let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap);
let res = this.malloc(size, zero_init, MiriMemoryKind::WinHeap)?;
this.write_scalar(res, dest)?;
}
"HeapFree" => {