From d19376985d84e54e452c8b26548d0f239dce9cc0 Mon Sep 17 00:00:00 2001 From: Smitty Date: Sun, 4 Jul 2021 09:59:55 -0400 Subject: [PATCH] Make work after mir-alloc-oom --- rust-version | 2 +- src/eval.rs | 14 ++++++++------ src/helpers.rs | 2 +- src/machine.rs | 6 ++++-- src/shims/backtrace.rs | 3 ++- src/shims/env.rs | 10 +++++----- src/shims/foreign_items.rs | 23 ++++++++++++++--------- src/shims/os_str.rs | 12 ++++++------ src/shims/posix/foreign_items.rs | 2 +- src/shims/posix/thread.rs | 2 +- src/shims/windows/foreign_items.rs | 2 +- 11 files changed, 44 insertions(+), 34 deletions(-) diff --git a/rust-version b/rust-version index 9890818ee9..23819ebc24 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -46ae6ee65df19c6a3fb683499c1203e749975e60 +39e20f1ae5f13451eb35247808d6a2527cb7d060 diff --git a/src/eval.rs b/src/eval.rs index 95cdcb1b5a..f728248c3a 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -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 = 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, diff --git a/src/helpers.rs b/src/helpers.rs index d53b2969fb..a6e66c3dbd 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -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) diff --git a/src/machine.rs b/src/machine.rs index 7ec510d050..999e21796d 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -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 = 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 diff --git a/src/shims/backtrace.rs b/src/shims/backtrace.rs index 4ea374344c..ec29fef636 100644 --- a/src/shims/backtrace.rs +++ b/src/shims/backtrace.rs @@ -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)?; diff --git a/src/shims/env.rs b/src/shims/env.rs index 0c42daa244..d99ffb31b5 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -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())?; diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 5b241a2fb3..5d46f3c05c 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -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 { + fn malloc( + &mut self, + size: u64, + zero_init: bool, + kind: MiriMemoryKind, + ) -> InterpResult<'tcx, Scalar> { 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)?; diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index 8a3f567770..ea99921c0b 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -161,14 +161,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx &mut self, os_str: &OsStr, memkind: MemoryKind, - ) -> Pointer { + ) -> InterpResult<'tcx, Pointer> { 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, - ) -> Pointer { + ) -> InterpResult<'tcx, Pointer> { 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. diff --git a/src/shims/posix/foreign_items.rs b/src/shims/posix/foreign_items.rs index 4035deff63..1cfc3f0a4e 100644 --- a/src/shims/posix/foreign_items.rs +++ b/src/shims/posix/foreign_items.rs @@ -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)?; diff --git a/src/shims/posix/thread.rs b/src/shims/posix/thread.rs index 1e45978489..ce1c817cf3 100644 --- a/src/shims/posix/thread.rs +++ b/src/shims/posix/thread.rs @@ -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, diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 1921af3594..b532457627 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -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" => {