detect recursive throw_resource_error and panic instead of causing a segmentation fault
This commit is contained in:
@@ -778,9 +778,47 @@ impl MachineState {
|
|||||||
|
|
||||||
// throw an error pre-allocated in the heap
|
// throw an error pre-allocated in the heap
|
||||||
pub(super) fn throw_resource_error(&mut self, err: AllocError) {
|
pub(super) fn throw_resource_error(&mut self, err: AllocError) {
|
||||||
self.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut self.heap));
|
struct RecursionGuard<'state> {
|
||||||
self.set_ball();
|
machine_state: &'state mut MachineState,
|
||||||
self.unwind_stack();
|
}
|
||||||
|
|
||||||
|
impl<'state> RecursionGuard<'state> {
|
||||||
|
fn new(machine_state: &'state mut MachineState) -> Self {
|
||||||
|
if machine_state.throwing_resource_error {
|
||||||
|
panic!("attempted to throw `error(resource_error(memory), [])` while attempting to throw `error(resource_error(memory), [])`");
|
||||||
|
}
|
||||||
|
machine_state.throwing_resource_error = true;
|
||||||
|
Self { machine_state }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for RecursionGuard<'_> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.machine_state.throwing_resource_error = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::Deref for RecursionGuard<'_> {
|
||||||
|
type Target = MachineState;
|
||||||
|
|
||||||
|
fn deref(&self) -> &MachineState {
|
||||||
|
self.machine_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::DerefMut for RecursionGuard<'_> {
|
||||||
|
fn deref_mut(&mut self) -> &mut MachineState {
|
||||||
|
self.machine_state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut guard = RecursionGuard::new(self);
|
||||||
|
|
||||||
|
let state = &mut *guard;
|
||||||
|
|
||||||
|
state.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut state.heap));
|
||||||
|
state.set_ball();
|
||||||
|
state.unwind_stack();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
pub(super) fn throw_exception(&mut self, err: MachineStub) {
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ pub struct MachineState {
|
|||||||
pub(super) cp: usize,
|
pub(super) cp: usize,
|
||||||
pub(super) attr_var_init: AttrVarInitializer,
|
pub(super) attr_var_init: AttrVarInitializer,
|
||||||
pub(super) fail: bool,
|
pub(super) fail: bool,
|
||||||
|
pub throwing_resource_error: bool,
|
||||||
pub heap: Heap,
|
pub heap: Heap,
|
||||||
pub(super) mode: MachineMode,
|
pub(super) mode: MachineMode,
|
||||||
pub(crate) stack: Stack,
|
pub(crate) stack: Stack,
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ impl MachineState {
|
|||||||
unify_fn: MachineState::unify,
|
unify_fn: MachineState::unify,
|
||||||
bind_fn: MachineState::bind,
|
bind_fn: MachineState::bind,
|
||||||
run_cleaners_fn: |_| false,
|
run_cleaners_fn: |_| false,
|
||||||
|
throwing_resource_error: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user