Skip to content

Commit

Permalink
fix: fix soundness bug allowing you to extend borrows of atomic resou…
Browse files Browse the repository at this point in the history
…rces past its guard. (#247)
  • Loading branch information
zicklag authored Oct 23, 2023
1 parent 4a70333 commit f8b046f
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
14 changes: 12 additions & 2 deletions framework_crates/bones_ecs/src/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ impl UntypedAtomicResource {
pub fn borrow(&self) -> AtomicSchemaRef {
let (reference, borrow) = Ref::into_split(self.cell.borrow());
// SOUND: we keep the borrow along with the reference so that the pointer remains valid.
let schema_ref = unsafe { reference.as_ref() }.as_ref();
let schema_ref = NoClone(unsafe { reference.as_ref() }.as_ref());
AtomicSchemaRef { schema_ref, borrow }
}

Expand All @@ -77,11 +77,21 @@ impl UntypedAtomicResource {
}
}

/// Wrapper type that prevents cloning or copying the inner type.
#[derive(Deref, DerefMut)]
pub struct NoClone<T>(T);

/// An atomic borrow of a [`SchemaRef`].
#[derive(Deref)]
pub struct AtomicSchemaRef<'a> {
/// This is wrappwed in a [`NoClone`] because of the limitations of the deref trait.
/// We would prefer to have deref return a [`SchemaRef`] with an appropriate lifetime,
/// that indicates it borrows from the [`AtomicSchemaRef`], but since deref must return
/// a normal reference, instead we return a reference to the `SchemaRef` wrapped inside
/// a [`NoClone`] to prevent copying the [`SchemaRef`] out of dereference with a lifetime
/// that outlives the atomicborrow.
#[deref]
schema_ref: SchemaRef<'a>,
schema_ref: NoClone<SchemaRef<'a>>,
borrow: AtomicBorrow<'a>,
}

Expand Down
2 changes: 1 addition & 1 deletion framework_crates/bones_schema/src/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use bones_utils::{parking_lot::RwLock, prelude::*};

/// An untyped reference that knows the [`Schema`] of the pointee and that can be cast to a matching
/// type.
#[derive(Clone)]
#[derive(Clone, Copy)]
pub struct SchemaRef<'pointer> {
ptr: Ptr<'pointer>,
schema: &'static Schema,
Expand Down

0 comments on commit f8b046f

Please sign in to comment.