feat(vm): add call stack depth guard to MirInterpreter
This commit is contained in:
@ -13,6 +13,23 @@ impl MirInterpreter {
|
|||||||
func: &MirFunction,
|
func: &MirFunction,
|
||||||
arg_vals: Option<&[VMValue]>,
|
arg_vals: Option<&[VMValue]>,
|
||||||
) -> Result<VMValue, VMError> {
|
) -> Result<VMValue, VMError> {
|
||||||
|
// Safety valve: cap nested exec_function_inner depth to avoid Rust stack overflow
|
||||||
|
// on accidental infinite recursion in MIR (e.g., self-recursive call chains).
|
||||||
|
const MAX_CALL_DEPTH: usize = 1024;
|
||||||
|
self.call_depth = self.call_depth.saturating_add(1);
|
||||||
|
if self.call_depth > MAX_CALL_DEPTH {
|
||||||
|
eprintln!(
|
||||||
|
"[vm-call-depth] exceeded {} in fn={} (depth={})",
|
||||||
|
MAX_CALL_DEPTH,
|
||||||
|
func.signature.name,
|
||||||
|
self.call_depth
|
||||||
|
);
|
||||||
|
self.call_depth = self.call_depth.saturating_sub(1);
|
||||||
|
return Err(VMError::InvalidInstruction(format!(
|
||||||
|
"vm call stack depth exceeded (max_depth={}, fn={})",
|
||||||
|
MAX_CALL_DEPTH, func.signature.name
|
||||||
|
)));
|
||||||
|
}
|
||||||
// Phase 1: delegate cross-class reroute / narrow fallbacks to method_router
|
// Phase 1: delegate cross-class reroute / narrow fallbacks to method_router
|
||||||
if let Some(r) = super::method_router::pre_exec_reroute(self, func, arg_vals) { return r; }
|
if let Some(r) = super::method_router::pre_exec_reroute(self, func, arg_vals) { return r; }
|
||||||
let saved_regs = mem::take(&mut self.regs);
|
let saved_regs = mem::take(&mut self.regs);
|
||||||
@ -96,6 +113,7 @@ impl MirInterpreter {
|
|||||||
BlockOutcome::Return(result) => {
|
BlockOutcome::Return(result) => {
|
||||||
self.cur_fn = saved_fn;
|
self.cur_fn = saved_fn;
|
||||||
self.regs = saved_regs;
|
self.regs = saved_regs;
|
||||||
|
self.call_depth = self.call_depth.saturating_sub(1);
|
||||||
return Ok(result);
|
return Ok(result);
|
||||||
}
|
}
|
||||||
BlockOutcome::Next {
|
BlockOutcome::Next {
|
||||||
|
|||||||
@ -41,6 +41,9 @@ pub struct MirInterpreter {
|
|||||||
pub(super) inst_count: u64,
|
pub(super) inst_count: u64,
|
||||||
pub(super) branch_count: u64,
|
pub(super) branch_count: u64,
|
||||||
pub(super) compare_count: u64,
|
pub(super) compare_count: u64,
|
||||||
|
/// Call stack depth (exec_function_inner nesting). Used as a safety valve
|
||||||
|
/// to prevent Rust stack overflow on accidental infinite recursion in MIR.
|
||||||
|
pub(super) call_depth: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MirInterpreter {
|
impl MirInterpreter {
|
||||||
@ -58,6 +61,7 @@ impl MirInterpreter {
|
|||||||
inst_count: 0,
|
inst_count: 0,
|
||||||
branch_count: 0,
|
branch_count: 0,
|
||||||
compare_count: 0,
|
compare_count: 0,
|
||||||
|
call_depth: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user