From 88d98998e1cfdfce8ce7e02a020cc9d19f318bd7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jul 2016 13:17:40 +0200 Subject: [PATCH] add execution time limit --- src/bin/miri.rs | 4 +++- src/error.rs | 7 +++++-- src/interpreter/mod.rs | 8 +++++--- tests/compile-fail/timeout.rs | 9 +++++++++ 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 tests/compile-fail/timeout.rs diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 087da20ac8be..6997bbd011df 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -39,6 +39,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { let krate = state.hir_crate.as_ref().unwrap(); let mut memory_size = 100*1024*1024; // 100MB + let mut step_limit = 1000_000; fn extract_str(lit: &syntax::ast::Lit) -> syntax::parse::token::InternedString { match lit.node { syntax::ast::LitKind::Str(ref s, _) => s.clone(), @@ -53,6 +54,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { MetaItemKind::NameValue(ref name, ref value) => { match &**name { "memory_size" => memory_size = extract_str(value).parse::().expect("not a number"), + "step_limit" => step_limit = extract_str(value).parse::().expect("not a number"), _ => state.session.span_err(item.span, "unknown miri attribute"), } } @@ -65,7 +67,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { let mut mir_map = MirMap { map: mir_map.map.clone() }; run_mir_passes(tcx, &mut mir_map); - eval_main(tcx, &mir_map, node_id, memory_size); + eval_main(tcx, &mir_map, node_id, memory_size, step_limit); state.session.abort_if_errors(); }); diff --git a/src/error.rs b/src/error.rs index 4467347b49bc..5c2410ed840a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -33,7 +33,8 @@ pub enum EvalError<'tcx> { allocation_size: u64, memory_size: u64, memory_usage: u64, - } + }, + ExecutionTimeLimitReached, } pub type EvalResult<'tcx, T> = Result>; @@ -75,7 +76,9 @@ impl<'tcx> Error for EvalError<'tcx> { EvalError::InvalidChar(..) => "tried to interpret an invalid 32-bit value as a char", EvalError::OutOfMemory{..} => - "could not allocate more memory" + "could not allocate more memory", + EvalError::ExecutionTimeLimitReached => + "reached the configured maximum execution time", } } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index ea1f82f5f62a..5b8947ec7353 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -929,6 +929,7 @@ pub fn eval_main<'a, 'tcx: 'a>( mir_map: &'a MirMap<'tcx>, node_id: ast::NodeId, memory_size: u64, + step_limit: u64, ) { let mir = mir_map.map.get(&node_id).expect("no mir for main function"); let def_id = tcx.map.local_def_id(node_id); @@ -952,17 +953,18 @@ pub fn eval_main<'a, 'tcx: 'a>( ecx.frame_mut().locals[1] = args; } - loop { + for _ in 0..step_limit { match ecx.step() { Ok(true) => {} - Ok(false) => break, + Ok(false) => return, // FIXME: diverging functions can end up here in some future miri Err(e) => { report(tcx, &ecx, e); - break; + return; } } } + report(tcx, &ecx, EvalError::ExecutionTimeLimitReached); } fn report(tcx: TyCtxt, ecx: &EvalContext, e: EvalError) { diff --git a/tests/compile-fail/timeout.rs b/tests/compile-fail/timeout.rs new file mode 100644 index 000000000000..bcb6c993089a --- /dev/null +++ b/tests/compile-fail/timeout.rs @@ -0,0 +1,9 @@ +//error-pattern: reached the configured maximum execution time +#![feature(custom_attribute)] +#![miri(step_limit="1000")] + +fn main() { + for i in 0..1000000 { + assert!(i < 1000); + } +}