add attribute to limit the stack size
This commit is contained in:
parent
88d98998e1
commit
4781a6ba54
@ -40,6 +40,7 @@ fn build_controller(
|
||||
let krate = state.hir_crate.as_ref().unwrap();
|
||||
let mut memory_size = 100*1024*1024; // 100MB
|
||||
let mut step_limit = 1000_000;
|
||||
let mut stack_limit = 100;
|
||||
fn extract_str(lit: &syntax::ast::Lit) -> syntax::parse::token::InternedString {
|
||||
match lit.node {
|
||||
syntax::ast::LitKind::Str(ref s, _) => s.clone(),
|
||||
@ -55,6 +56,7 @@ fn extract_str(lit: &syntax::ast::Lit) -> syntax::parse::token::InternedString {
|
||||
match &**name {
|
||||
"memory_size" => memory_size = extract_str(value).parse::<u64>().expect("not a number"),
|
||||
"step_limit" => step_limit = extract_str(value).parse::<u64>().expect("not a number"),
|
||||
"stack_limit" => stack_limit = extract_str(value).parse::<u64>().expect("not a number"),
|
||||
_ => state.session.span_err(item.span, "unknown miri attribute"),
|
||||
}
|
||||
}
|
||||
@ -67,7 +69,7 @@ fn extract_str(lit: &syntax::ast::Lit) -> syntax::parse::token::InternedString {
|
||||
|
||||
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, step_limit);
|
||||
eval_main(tcx, &mir_map, node_id, memory_size, step_limit, stack_limit);
|
||||
|
||||
state.session.abort_if_errors();
|
||||
});
|
||||
|
@ -35,6 +35,7 @@ pub enum EvalError<'tcx> {
|
||||
memory_usage: u64,
|
||||
},
|
||||
ExecutionTimeLimitReached,
|
||||
StackFrameLimitReached,
|
||||
}
|
||||
|
||||
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
|
||||
@ -79,6 +80,8 @@ fn description(&self) -> &str {
|
||||
"could not allocate more memory",
|
||||
EvalError::ExecutionTimeLimitReached =>
|
||||
"reached the configured maximum execution time",
|
||||
EvalError::StackFrameLimitReached =>
|
||||
"reached the configured maximum number of stack frames",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,9 @@ pub struct EvalContext<'a, 'tcx: 'a> {
|
||||
|
||||
/// The virtual call stack.
|
||||
stack: Vec<Frame<'a, 'tcx>>,
|
||||
|
||||
/// The maximum number of stack frames allowed
|
||||
stack_limit: usize,
|
||||
}
|
||||
|
||||
/// A stack frame.
|
||||
@ -133,7 +136,8 @@ enum ConstantKind {
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, memory_size: u64) -> Self {
|
||||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, memory_size: u64, stack_limit: u64) -> Self {
|
||||
assert_eq!(stack_limit as usize as u64, stack_limit);
|
||||
EvalContext {
|
||||
tcx: tcx,
|
||||
mir_map: mir_map,
|
||||
@ -141,6 +145,7 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, memory_size:
|
||||
memory: Memory::new(&tcx.data_layout, memory_size),
|
||||
statics: HashMap::new(),
|
||||
stack: Vec::new(),
|
||||
stack_limit: stack_limit as usize,
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,7 +321,11 @@ pub fn push_stack_frame(
|
||||
substs: substs,
|
||||
stmt: 0,
|
||||
});
|
||||
Ok(())
|
||||
if self.stack.len() > self.stack_limit {
|
||||
Err(EvalError::StackFrameLimitReached)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn pop_stack_frame(&mut self) {
|
||||
@ -930,10 +939,11 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
||||
node_id: ast::NodeId,
|
||||
memory_size: u64,
|
||||
step_limit: u64,
|
||||
stack_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);
|
||||
let mut ecx = EvalContext::new(tcx, mir_map, memory_size);
|
||||
let mut ecx = EvalContext::new(tcx, mir_map, memory_size, stack_limit);
|
||||
let substs = tcx.mk_substs(subst::Substs::empty());
|
||||
let return_ptr = ecx.alloc_ret_ptr(mir.return_ty, substs)
|
||||
.expect("should at least be able to allocate space for the main function's return value")
|
||||
|
20
tests/compile-fail/stack_limit.rs
Normal file
20
tests/compile-fail/stack_limit.rs
Normal file
@ -0,0 +1,20 @@
|
||||
#![feature(custom_attribute)]
|
||||
#![miri(stack_limit="2")]
|
||||
|
||||
fn bar() {
|
||||
foo();
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
cake(); //~ ERROR reached the configured maximum number of stack frames
|
||||
}
|
||||
|
||||
fn cake() {
|
||||
flubber();
|
||||
}
|
||||
|
||||
fn flubber() {}
|
||||
|
||||
fn main() {
|
||||
bar();
|
||||
}
|
Loading…
Reference in New Issue
Block a user