Skip to content

Commit

Permalink
Avoid invalidating provenance of outstanding references in `alloc_ext…
Browse files Browse the repository at this point in the history
…end`. Fixes #55
  • Loading branch information
thomcc committed Jan 9, 2023
1 parent 84f08cc commit 7cf5741
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,16 @@ impl<T> Arena<T> {
i += 1;
}
}
let new_slice_ref = &mut chunks.current[next_item_index..];

// Extend the lifetime from that of `chunks_borrow` to that of `self`.
// This is OK because we’re careful to never move items
// by never pushing to inner `Vec`s beyond their initial capacity.
// The returned reference is unique (`&mut`):
// the `Arena` never gives away references to existing items.
unsafe { mem::transmute::<&mut [T], &mut [T]>(new_slice_ref) }
unsafe {
let new_len = chunks.current.len() - next_item_index;
slice::from_raw_parts_mut(chunks.current.as_mut_ptr().add(next_item_index), new_len)
}
}

/// Allocates space for a given number of values, but doesn't initialize it.
Expand Down
11 changes: 11 additions & 0 deletions src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,17 @@ fn size_hint() {
}
}

// Ensure that `alloc_extend` doesn't violate provenance of
// existing references. (Note: This test is pointless except
// under miri).
#[test]
fn check_extend_provenance() {
let arena = Arena::new();
let a = arena.alloc(0);
arena.alloc_extend([0]);
*a = 1;
}

#[test]
fn size_hint_low_initial_capacities() {
#[derive(Debug, PartialEq, Eq)]
Expand Down

0 comments on commit 7cf5741

Please sign in to comment.