]> Repositorios git - scryer-prolog.git/commitdiff
detect recursive throw_resource_error and panic instead of causing a segmentation...
authorSkgland <[email protected]>
Sun, 7 Dec 2025 20:08:17 +0000 (21:08 +0100)
committerBennet Bleßmann <[email protected]>
Sun, 7 Dec 2025 20:08:17 +0000 (21:08 +0100)
src/machine/machine_errors.rs
src/machine/machine_state.rs
src/machine/machine_state_impl.rs

index fa6822d0af5d7967622ac6348ac4cf1f3a07cea7..ead28cd9b30e6b6704ad4655af70586a087b36bb 100644 (file)
@@ -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) {
index 452debb2ed5b0fa85398df007efe8e7fb2fee97d..732678da8cb8679169ed87037f919ddcb8813ad7 100644 (file)
@@ -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,
index ee8a130b98825818deb1111024a3c0ce2c26f666..7b777ae63f828679f88b699462601784fd55ae24 100644 (file)
@@ -67,6 +67,7 @@ impl MachineState {
             unify_fn: MachineState::unify,
             bind_fn: MachineState::bind,
             run_cleaners_fn: |_| false,
+            throwing_resource_error: false,
         }
     }