Skip to content

Commit 26b9462

Browse files
committed
BTreeMap: tougher checks on most uses of copy_nonoverlapping
1 parent 8fec6c7 commit 26b9462

File tree

1 file changed

+32
-26
lines changed
  • library/alloc/src/collections/btree

1 file changed

+32
-26
lines changed

library/alloc/src/collections/btree/node.rs

+32-26
Original file line numberDiff line numberDiff line change
@@ -1124,21 +1124,20 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
11241124
/// by taking care of leaf data.
11251125
fn split_leaf_data(&mut self, new_node: &mut LeafNode<K, V>) -> (K, V) {
11261126
debug_assert!(self.idx < self.node.len());
1127-
let new_len = self.node.len() - self.idx - 1;
1127+
let old_len = self.node.len();
1128+
let new_len = old_len - self.idx - 1;
11281129
new_node.len = new_len as u16;
11291130
unsafe {
11301131
let k = self.node.key_area_mut(self.idx).assume_init_read();
11311132
let v = self.node.val_area_mut(self.idx).assume_init_read();
11321133

1133-
ptr::copy_nonoverlapping(
1134-
self.node.key_area_mut(self.idx + 1..).as_ptr(),
1135-
new_node.keys.as_mut_ptr(),
1136-
new_len,
1134+
move_to_slice(
1135+
self.node.key_area_mut(self.idx + 1..old_len),
1136+
&mut new_node.keys[..new_len],
11371137
);
1138-
ptr::copy_nonoverlapping(
1139-
self.node.val_area_mut(self.idx + 1..).as_ptr(),
1140-
new_node.vals.as_mut_ptr(),
1141-
new_len,
1138+
move_to_slice(
1139+
self.node.val_area_mut(self.idx + 1..old_len),
1140+
&mut new_node.vals[..new_len],
11421141
);
11431142

11441143
*self.node.len_mut() = self.idx as u16;
@@ -1190,20 +1189,20 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>,
11901189
/// - All the edges and key-value pairs to the right of this handle are put into
11911190
/// a newly allocated node.
11921191
pub fn split(mut self) -> SplitResult<'a, K, V, marker::Internal> {
1192+
let old_len = self.node.len();
11931193
unsafe {
11941194
let mut new_node = Box::new(InternalNode::new());
11951195
let kv = self.split_leaf_data(&mut new_node.data);
11961196
let new_len = usize::from(new_node.data.len);
1197-
ptr::copy_nonoverlapping(
1198-
self.node.edge_area_mut(self.idx + 1..).as_ptr(),
1199-
new_node.edges.as_mut_ptr(),
1200-
new_len + 1,
1197+
move_to_slice(
1198+
self.node.edge_area_mut(self.idx + 1..old_len + 1),
1199+
&mut new_node.edges[..new_len + 1],
12011200
);
12021201

12031202
let height = self.node.height;
12041203
let mut right = NodeRef::from_new_internal(new_node, height);
12051204

1206-
right.borrow_mut().correct_childrens_parent_links(0..=new_len);
1205+
right.borrow_mut().correct_childrens_parent_links(0..new_len + 1);
12071206

12081207
SplitResult { left: self.node, kv, right }
12091208
}
@@ -1323,18 +1322,16 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
13231322

13241323
let parent_key = slice_remove(parent_node.key_area_mut(..old_parent_len), parent_idx);
13251324
left_node.key_area_mut(old_left_len).write(parent_key);
1326-
ptr::copy_nonoverlapping(
1327-
right_node.key_area_mut(..).as_ptr(),
1328-
left_node.key_area_mut(old_left_len + 1..).as_mut_ptr(),
1329-
right_len,
1325+
move_to_slice(
1326+
right_node.key_area_mut(..right_len),
1327+
left_node.key_area_mut(old_left_len + 1..new_left_len),
13301328
);
13311329

13321330
let parent_val = slice_remove(parent_node.val_area_mut(..old_parent_len), parent_idx);
13331331
left_node.val_area_mut(old_left_len).write(parent_val);
1334-
ptr::copy_nonoverlapping(
1335-
right_node.val_area_mut(..).as_ptr(),
1336-
left_node.val_area_mut(old_left_len + 1..).as_mut_ptr(),
1337-
right_len,
1332+
move_to_slice(
1333+
right_node.val_area_mut(..right_len),
1334+
left_node.val_area_mut(old_left_len + 1..new_left_len),
13381335
);
13391336

13401337
slice_remove(&mut parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1);
@@ -1346,10 +1343,9 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> {
13461343
// of the node of this edge, thus above zero, so they are internal.
13471344
let mut left_node = left_node.reborrow_mut().cast_to_internal_unchecked();
13481345
let mut right_node = right_node.cast_to_internal_unchecked();
1349-
ptr::copy_nonoverlapping(
1350-
right_node.edge_area_mut(..).as_ptr(),
1351-
left_node.edge_area_mut(old_left_len + 1..).as_mut_ptr(),
1352-
right_len + 1,
1346+
move_to_slice(
1347+
right_node.edge_area_mut(..right_len + 1),
1348+
left_node.edge_area_mut(old_left_len + 1..new_left_len + 1),
13531349
);
13541350

13551351
left_node.correct_childrens_parent_links(old_left_len + 1..new_left_len + 1);
@@ -1741,5 +1737,15 @@ unsafe fn slice_remove<T>(slice: &mut [MaybeUninit<T>], idx: usize) -> T {
17411737
}
17421738
}
17431739

1740+
/// Moves all values from a slice of initialized elements to a slice
1741+
/// of uninitialized elements, leaving behind `src` as all uninitialized.
1742+
/// Works like `dst.copy_from_slice(src)` but does not require `T` to be `Copy`.
1743+
fn move_to_slice<T>(src: &mut [MaybeUninit<T>], dst: &mut [MaybeUninit<T>]) {
1744+
assert!(src.len() == dst.len());
1745+
unsafe {
1746+
ptr::copy_nonoverlapping(src.as_ptr(), dst.as_mut_ptr(), src.len());
1747+
}
1748+
}
1749+
17441750
#[cfg(test)]
17451751
mod tests;

0 commit comments

Comments
 (0)