From 0993525acb335356238da340ca6ae5bd5a43b241 Mon Sep 17 00:00:00 2001 From: Troy Hinckley Date: Mon, 1 May 2023 17:30:18 -0500 Subject: [PATCH] Fix unsoundness bug in rebind! found by @Alan-Chen99 See #26 --- src/core/gc/context.rs | 12 ++++++------ src/core/object/tagged.rs | 15 +++++++++------ src/interpreter.rs | 17 +++++++++++------ 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/core/gc/context.rs b/src/core/gc/context.rs index 4ad3ae2a..bffb9db8 100644 --- a/src/core/gc/context.rs +++ b/src/core/gc/context.rs @@ -1,7 +1,7 @@ use super::OwnedObject; use super::Trace; use crate::core::env::UninternedSymbolMap; -use crate::core::object::{Gc, GcObj, IntoObject, RawInto, WithLifetime}; +use crate::core::object::{Gc, GcObj, IntoObject, FromRaw, WithLifetime}; use std::cell::{Cell, RefCell}; use std::fmt::Debug; use std::ops::Deref; @@ -161,9 +161,9 @@ impl<'ob, 'rt> Context<'rt> { pub(crate) unsafe fn rebind_raw_ptr(&'ob self, raw: T) -> U where - T: RawInto, + T: FromRaw<'ob, Out = U>, { - raw.raw_into() + raw.from_raw() } pub(crate) fn get_root_set(&'ob self) -> &'rt RootSet { @@ -311,9 +311,9 @@ mod test { #[test] fn test_reborrow() { let roots = &RootSet::default(); - let mut cx = Context::new(roots); - let obj = rebind!(bind_to_mut(&mut cx)); - _ = "foo".into_obj(&cx); + let cx = &mut Context::new(roots); + let obj = rebind!(bind_to_mut(cx)); + _ = "foo".into_obj(cx); assert_eq!(obj, "invariant"); } diff --git a/src/core/object/tagged.rs b/src/core/object/tagged.rs index ca4b9ce7..d47927a6 100755 --- a/src/core/object/tagged.rs +++ b/src/core/object/tagged.rs @@ -168,18 +168,21 @@ impl<'new, 'old, T: GcManaged + 'new> WithLifetime<'new> for &'old T { } } -pub(crate) trait RawInto { - unsafe fn raw_into(self) -> T; +pub(crate) trait FromRaw<'ob> { + type Out: 'ob; + unsafe fn from_raw(self) -> Self::Out; } -impl<'ob> RawInto> for RawObj { - unsafe fn raw_into(self) -> GcObj<'ob> { +impl<'ob> FromRaw<'ob> for RawObj { + type Out = GcObj<'ob>; + unsafe fn from_raw(self) -> GcObj<'ob> { GcObj::new(self.ptr) } } -impl<'ob> RawInto<&'ob Cons> for *const Cons { - unsafe fn raw_into(self) -> &'ob Cons { +impl<'ob> FromRaw<'ob> for *const Cons { + type Out = &'ob Cons; + unsafe fn from_raw(self) -> &'ob Cons { &*self } } diff --git a/src/interpreter.rs b/src/interpreter.rs index 74b57339..cc114916 100755 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -505,12 +505,17 @@ impl Interpreter<'_> { fn unwind_protect<'ob>(&mut self, obj: &Rt, cx: &'ob mut Context) -> EvalResult<'ob> { rooted_iter!(forms, obj, cx); let Some(body) = forms.next() else {bail_err!(ArgError::new(1, 0, "unwind-protect"))}; - let result = match self.eval_form(body, cx) { - Ok(x) => Ok(rebind!(x, cx)), - Err(e) => Err(e), - }; - self.implicit_progn(forms, cx)?; - result + match self.eval_form(body, cx) { + Ok(x) => { + root!(x, cx); + self.implicit_progn(forms, cx)?; + Ok(x.bind(cx)) + } + Err(e) => { + self.implicit_progn(forms, cx)?; + Err(e) + } + } } fn condition_case<'ob>(&mut self, form: &Rt, cx: &'ob mut Context) -> EvalResult<'ob> {