From: Skgland Date: Sun, 7 Dec 2025 20:08:17 +0000 (+0100) Subject: detect recursive throw_resource_error and panic instead of causing a segmentation... X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=193cfabc667a0ec6c0914d5f6fc3a105960cc6d3;p=scryer-prolog.git detect recursive throw_resource_error and panic instead of causing a segmentation fault --- diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index fa6822d0..ead28cd9 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -778,9 +778,47 @@ impl MachineState { // throw an error pre-allocated in the heap pub(super) fn throw_resource_error(&mut self, err: AllocError) { - self.registers[1] = str_loc_as_cell!(err.resource_error_offset(&mut self.heap)); - self.set_ball(); - self.unwind_stack(); + struct RecursionGuard<'state> { + machine_state: &'state mut MachineState, + } + + 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) { diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 452debb2..732678da 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -74,6 +74,7 @@ pub struct MachineState { pub(super) cp: usize, pub(super) attr_var_init: AttrVarInitializer, pub(super) fail: bool, + pub throwing_resource_error: bool, pub heap: Heap, pub(super) mode: MachineMode, pub(crate) stack: Stack, diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index ee8a130b..7b777ae6 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -67,6 +67,7 @@ impl MachineState { unify_fn: MachineState::unify, bind_fn: MachineState::bind, run_cleaners_fn: |_| false, + throwing_resource_error: false, } }