Fix call stack limits.

This commit is contained in:
Stephen Chung
2020-12-29 12:29:45 +08:00
parent 41c6f985f5
commit 13f5cec291
8 changed files with 70 additions and 55 deletions

View File

@@ -405,11 +405,11 @@ impl Engine {
mods.extend(fn_def.mods.iter_raw().map(|(n, m)| (n.clone(), m.clone())));
}
// Evaluate the function at one higher level of call depth
// Evaluate the function
let stmt = &fn_def.body;
let result = self
.eval_stmt(scope, mods, state, unified_lib, this_ptr, stmt, level + 1)
.eval_stmt(scope, mods, state, unified_lib, this_ptr, stmt, level)
.or_else(|err| match *err {
// Convert return statement to return value
EvalAltResult::Return(x, _) => Ok(x),
@@ -586,6 +586,8 @@ impl Engine {
mem::swap(&mut state.source, &mut source);
let level = _level + 1;
let result = self.call_script_fn(
scope,
mods,
@@ -595,7 +597,7 @@ impl Engine {
func,
rest,
pos,
_level,
level,
);
// Restore the original source
@@ -610,8 +612,10 @@ impl Engine {
mem::swap(&mut state.source, &mut source);
let level = _level + 1;
let result = self.call_script_fn(
scope, mods, state, lib, &mut None, func, args, pos, _level,
scope, mods, state, lib, &mut None, func, args, pos, level,
);
// Restore the original source
@@ -667,11 +671,12 @@ impl Engine {
state: &mut State,
statements: impl IntoIterator<Item = &'a Stmt>,
lib: &[&Module],
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
statements
.into_iter()
.try_fold(().into(), |_, stmt| {
self.eval_stmt(scope, mods, state, lib, &mut None, stmt, 0)
self.eval_stmt(scope, mods, state, lib, &mut None, stmt, level)
})
.or_else(|err| match *err {
EvalAltResult::Return(out, _) => Ok(out),
@@ -691,7 +696,7 @@ impl Engine {
lib: &[&Module],
script: &str,
pos: Position,
_level: usize,
level: usize,
) -> Result<Dynamic, Box<EvalAltResult>> {
self.inc_operations(state, pos)?;
@@ -700,13 +705,6 @@ impl Engine {
return Ok(Dynamic::UNIT);
}
// Check for stack overflow
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "unchecked"))]
if _level > self.max_call_levels() {
return Err(Box::new(EvalAltResult::ErrorStackOverflow(pos)));
}
// Compile the script text
// No optimizations because we only run it once
let ast = self.compile_with_scope_and_optimization_level(
@@ -727,7 +725,8 @@ impl Engine {
..Default::default()
};
let result = self.eval_statements_raw(scope, mods, &mut new_state, ast.statements(), lib);
let result =
self.eval_statements_raw(scope, mods, &mut new_state, ast.statements(), lib, level);
state.operations = new_state.operations;
result
@@ -1208,6 +1207,8 @@ impl Engine {
let mut source = module.id_raw().clone();
mem::swap(&mut state.source, &mut source);
let level = level + 1;
let result = self.call_script_fn(
new_scope, mods, state, lib, &mut None, &fn_def, args, pos, level,
);