From 8a36d12d3664ab0e882ce98bacd6f7f95000f6a2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 29 Nov 2019 10:16:03 +0100 Subject: [PATCH] implement proper panicking for failed index check --- src/lib.rs | 3 ++- src/machine.rs | 10 ++++++++++ src/shims/panic.rs | 40 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 05234e880f5..abed7ab9dfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,6 +38,7 @@ pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt}; pub use crate::shims::env::{EnvVars, EvalContextExt as EnvEvalContextExt}; pub use crate::shims::fs::{FileHandler, EvalContextExt as FileEvalContextExt}; pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as PanicEvalContextExt}; + pub use crate::operator::EvalContextExt as OperatorEvalContextExt; pub use crate::range_map::RangeMap; pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt}; @@ -45,7 +46,7 @@ pub use crate::mono_hash_map::MonoHashMap; pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item}; pub use crate::machine::{ PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS, - MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt, + MemoryExtra, AllocExtra, FrameData, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt, }; pub use crate::eval::{eval_main, create_ecx, MiriConfig, TerminationInfo}; diff --git a/src/machine.rs b/src/machine.rs index 94ddee6fc09..07864ac4ee4 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -215,6 +215,16 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { ecx.call_intrinsic(span, instance, args, ret, unwind) } + #[inline(always)] + fn assert_panic( + ecx: &mut InterpCx<'mir, 'tcx, Self>, + span: Span, + msg: &AssertMessage<'tcx>, + unwind: Option, + ) -> InterpResult<'tcx> { + ecx.assert_panic(span, msg, unwind) + } + #[inline(always)] fn binary_ptr_op( ecx: &rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>, diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 6cc9f176c8f..4b9cb6b4195 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -11,11 +11,12 @@ //! gets popped *during unwinding*, we take the panic payload and store it according to the extra //! metadata we remembered when pushing said frame. +use syntax::source_map::Span; use rustc::mir; -use crate::*; -use super::machine::FrameData; +use rustc::ty::{self, layout::LayoutOf}; use rustc_target::spec::PanicStrategy; -use crate::rustc_target::abi::LayoutOf; + +use crate::*; /// Holds all of the relevant data for a call to /// `__rust_maybe_catch_panic`. @@ -150,4 +151,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.memory.extra.stacked_borrows.borrow_mut().end_call(extra.call_id); Ok(res) } + + fn assert_panic( + &mut self, + span: Span, + msg: &AssertMessage<'tcx>, + unwind: Option, + ) -> InterpResult<'tcx> { + use rustc::mir::interpret::PanicInfo::*; + let this = self.eval_context_mut(); + + match msg { + BoundsCheck { ref index, ref len } => { + // First arg: Caller location. + let location = this.alloc_caller_location_for_span(span)?; + // Second arg: index. + let index = this.read_scalar(this.eval_operand(index, None)?)?; + // Third arg: len. + let len = this.read_scalar(this.eval_operand(len, None)?)?; + + // Call the lang item. + let panic_bounds_check = this.tcx.lang_items().panic_bounds_check_fn().unwrap(); + let panic_bounds_check = ty::Instance::mono(this.tcx.tcx, panic_bounds_check); + this.call_function( + panic_bounds_check, + &[location.ptr, index.not_undef()?, len.not_undef()?], + None, + StackPopCleanup::Goto { ret: None, unwind }, + )?; + } + _ => unimplemented!() + } + Ok(()) + } }