Skip to content

Commit

Permalink
Fix unsoundness bug in rebind! found by @Alan-Chen99
Browse files Browse the repository at this point in the history
See #26
  • Loading branch information
CeleritasCelery committed May 1, 2023
1 parent 5f10c29 commit 0993525
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 18 deletions.
12 changes: 6 additions & 6 deletions src/core/gc/context.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -161,9 +161,9 @@ impl<'ob, 'rt> Context<'rt> {

pub(crate) unsafe fn rebind_raw_ptr<T, U>(&'ob self, raw: T) -> U
where
T: RawInto<U>,
T: FromRaw<'ob, Out = U>,
{
raw.raw_into()
raw.from_raw()
}

pub(crate) fn get_root_set(&'ob self) -> &'rt RootSet {
Expand Down Expand Up @@ -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");
}

Expand Down
15 changes: 9 additions & 6 deletions src/core/object/tagged.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,18 +168,21 @@ impl<'new, 'old, T: GcManaged + 'new> WithLifetime<'new> for &'old T {
}
}

pub(crate) trait RawInto<T> {
unsafe fn raw_into(self) -> T;
pub(crate) trait FromRaw<'ob> {
type Out: 'ob;
unsafe fn from_raw(self) -> Self::Out;
}

impl<'ob> RawInto<GcObj<'ob>> 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
}
}
Expand Down
17 changes: 11 additions & 6 deletions src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,17 @@ impl Interpreter<'_> {
fn unwind_protect<'ob>(&mut self, obj: &Rt<GcObj>, 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<GcObj>, cx: &'ob mut Context) -> EvalResult<'ob> {
Expand Down

0 comments on commit 0993525

Please sign in to comment.