Skip to content

Commit 76f9c96

Browse files
Make functions dependent only on shared root avoidance safe
1 parent 4e33a54 commit 76f9c96

File tree

3 files changed

+58
-58
lines changed

3 files changed

+58
-58
lines changed

src/liballoc/collections/btree/map.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1349,7 +1349,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
13491349
self.fix_top();
13501350
}
13511351

1352-
/// If the root node is the shared root node, allocate our own node.
1352+
/// If the root node is the empty (non-allocated) root node, allocate our
1353+
/// own node.
13531354
fn ensure_root_is_owned(&mut self) {
13541355
if self.root.is_none() {
13551356
self.root = Some(node::Root::new_leaf());
@@ -1509,7 +1510,6 @@ impl<K, V> Drop for IntoIter<K, V> {
15091510
// don't have to care about panics this time (they'll abort).
15101511
while let Some(_) = self.0.next() {}
15111512

1512-
// No need to avoid the shared root, because the tree was definitely not empty.
15131513
unsafe {
15141514
let mut node =
15151515
unwrap_unchecked(ptr::read(&self.0.front)).into_node().forget_type();

src/liballoc/collections/btree/node.rs

+54-53
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,9 @@ impl<K, V> BoxedNode<K, V> {
169169
}
170170
}
171171

172-
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor,
173-
/// and must be cleaned up manually if it is an owned tree.
172+
/// An owned tree.
173+
///
174+
/// Note that this does not have a destructor, and must be cleaned up manually.
174175
pub struct Root<K, V> {
175176
node: BoxedNode<K, V>,
176177
/// The number of levels below the root node.
@@ -278,10 +279,7 @@ impl<K, V> Root<K, V> {
278279
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
279280
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
280281
/// `NodeRef` could be pointing to either type of node.
281-
/// Note that in case of a leaf node, this might still be the shared root!
282-
/// Only turn this into a `LeafNode` reference if you know it is not the shared root!
283-
/// Shared references must be dereferenceable *for the entire size of their pointee*,
284-
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
282+
///
285283
/// Turning this into a `NodeHeader` reference is always safe.
286284
pub struct NodeRef<BorrowType, K, V, Type> {
287285
/// The number of levels below the node.
@@ -344,29 +342,28 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
344342
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
345343
}
346344

347-
/// Exposes the leaf "portion" of any leaf or internal node that is not the shared root.
345+
/// Exposes the leaf "portion" of any leaf or internal node.
348346
/// If the node is a leaf, this function simply opens up its data.
349347
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
350348
/// (header, keys and values), and this function exposes that.
351-
/// Unsafe because the node must not be the shared root. For more information,
352-
/// see the `NodeRef` comments.
353-
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
354-
self.node.as_ref()
349+
fn as_leaf(&self) -> &LeafNode<K, V> {
350+
// The node must be valid for at least the LeafNode portion.
351+
// This is not a reference in the NodeRef type because we don't know if
352+
// it should be unique or shared.
353+
unsafe { self.node.as_ref() }
355354
}
356355

357356
fn as_header(&self) -> &NodeHeader<K, V> {
358357
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
359358
}
360359

361360
/// Borrows a view into the keys stored in the node.
362-
/// Unsafe because the caller must ensure that the node is not the shared root.
363-
pub unsafe fn keys(&self) -> &[K] {
361+
pub fn keys(&self) -> &[K] {
364362
self.reborrow().into_key_slice()
365363
}
366364

367365
/// Borrows a view into the values stored in the node.
368-
/// Unsafe because the caller must ensure that the node is not the shared root.
369-
unsafe fn vals(&self) -> &[V] {
366+
fn vals(&self) -> &[V] {
370367
self.reborrow().into_val_slice()
371368
}
372369

@@ -470,39 +467,37 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
470467
/// (header, keys and values), and this function exposes that.
471468
///
472469
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
473-
/// This also implies you can invoke this member on the shared root, but the resulting pointer
474-
/// might not be properly aligned and definitely would not allow accessing keys and values.
475470
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
476471
self.node.as_ptr()
477472
}
478473

479-
/// Unsafe because the caller must ensure that the node is not the shared root.
480-
unsafe fn keys_mut(&mut self) -> &mut [K] {
481-
self.reborrow_mut().into_key_slice_mut()
474+
fn keys_mut(&mut self) -> &mut [K] {
475+
// SAFETY: the caller will not be able to call further methods on self
476+
// until the key slice reference is dropped, as we have unique access
477+
// for the lifetime of the borrow.
478+
unsafe { self.reborrow_mut().into_key_slice_mut() }
482479
}
483480

484-
/// Unsafe because the caller must ensure that the node is not the shared root.
485-
unsafe fn vals_mut(&mut self) -> &mut [V] {
486-
self.reborrow_mut().into_val_slice_mut()
481+
fn vals_mut(&mut self) -> &mut [V] {
482+
// SAFETY: the caller will not be able to call further methods on self
483+
// until the value slice reference is dropped, as we have unique access
484+
// for the lifetime of the borrow.
485+
unsafe { self.reborrow_mut().into_val_slice_mut() }
487486
}
488487
}
489488

490489
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
491-
/// Unsafe because the caller must ensure that the node is not the shared root.
492-
unsafe fn into_key_slice(self) -> &'a [K] {
493-
// We cannot be the shared root, so `as_leaf` is okay.
494-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
490+
fn into_key_slice(self) -> &'a [K] {
491+
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) }
495492
}
496493

497-
/// Unsafe because the caller must ensure that the node is not the shared root.
498-
unsafe fn into_val_slice(self) -> &'a [V] {
499-
// We cannot be the shared root, so `as_leaf` is okay.
500-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len())
494+
fn into_val_slice(self) -> &'a [V] {
495+
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
501496
}
502497

503-
/// Unsafe because the caller must ensure that the node is not the shared root.
504-
unsafe fn into_slices(self) -> (&'a [K], &'a [V]) {
505-
let k = ptr::read(&self);
498+
fn into_slices(self) -> (&'a [K], &'a [V]) {
499+
// SAFETY: equivalent to reborrow() except not requiring Type: 'a
500+
let k = unsafe { ptr::read(&self) };
506501
(k.into_key_slice(), self.into_val_slice())
507502
}
508503
}
@@ -514,34 +509,41 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
514509
unsafe { &mut *(self.root as *mut Root<K, V>) }
515510
}
516511

517-
/// Unsafe because the caller must ensure that the node is not the shared root.
518-
unsafe fn into_key_slice_mut(mut self) -> &'a mut [K] {
519-
// We cannot be the shared root, so `as_leaf_mut` is okay.
520-
slice::from_raw_parts_mut(
521-
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
522-
self.len(),
523-
)
512+
fn into_key_slice_mut(mut self) -> &'a mut [K] {
513+
// SAFETY: The keys of a node must always be initialized up to length.
514+
unsafe {
515+
slice::from_raw_parts_mut(
516+
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
517+
self.len(),
518+
)
519+
}
524520
}
525521

526-
/// Unsafe because the caller must ensure that the node is not the shared root.
527-
unsafe fn into_val_slice_mut(mut self) -> &'a mut [V] {
528-
slice::from_raw_parts_mut(
529-
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
530-
self.len(),
531-
)
522+
fn into_val_slice_mut(mut self) -> &'a mut [V] {
523+
// SAFETY: The values of a node must always be initialized up to length.
524+
unsafe {
525+
slice::from_raw_parts_mut(
526+
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
527+
self.len(),
528+
)
529+
}
532530
}
533531

534-
/// Unsafe because the caller must ensure that the node is not the shared root.
535-
unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
532+
fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
536533
// We cannot use the getters here, because calling the second one
537534
// invalidates the reference returned by the first.
538535
// More precisely, it is the call to `len` that is the culprit,
539536
// because that creates a shared reference to the header, which *can*
540537
// overlap with the keys (and even the values, for ZST keys).
541538
let len = self.len();
542539
let leaf = self.as_leaf_mut();
543-
let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len);
544-
let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len);
540+
// SAFETY: The keys and values of a node must always be initialized up to length.
541+
let keys = unsafe {
542+
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len)
543+
};
544+
let vals = unsafe {
545+
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len)
546+
};
545547
(keys, vals)
546548
}
547549
}
@@ -698,8 +700,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
698700
}
699701
}
700702

701-
/// Unsafe because the caller must ensure that the node is not the shared root.
702-
unsafe fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
703+
fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
703704
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
704705
}
705706
}

src/liballoc/collections/btree/search.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,12 @@ where
6767
Q: Ord,
6868
K: Borrow<Q>,
6969
{
70-
// This function is defined over all borrow types (immutable, mutable, owned),
71-
// and may be called on the shared root in each case.
70+
// This function is defined over all borrow types (immutable, mutable, owned).
7271
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
7372
// is an index -- not a reference.
7473
let len = node.len();
7574
if len > 0 {
76-
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
75+
let keys = node.keys();
7776
for (i, k) in keys.iter().enumerate() {
7877
match key.cmp(k.borrow()) {
7978
Ordering::Greater => {}

0 commit comments

Comments
 (0)