Skip to content

Commit 7da1750

Browse files
committed
Fixed soundness hole that was allowing multiple mutable borrows of the same node
1 parent ba82400 commit 7da1750

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

src/map.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,10 @@ impl<K: Ord, V> BSTMap<K, V> {
301301
Q: Ord + ?Sized,
302302
{
303303
let mut current = self.root_mut();
304-
while let Some(mut node) = current.take() {
304+
while let Some(node) = current.take() {
305305
match key.cmp(node.key().borrow()) {
306-
Ordering::Less => current = node.left(),
307-
Ordering::Greater => current = node.right(),
306+
Ordering::Less => current = node.into_left(),
307+
Ordering::Greater => current = node.into_right(),
308308
Ordering::Equal => return Some(node.into_value_mut()),
309309
}
310310
}
@@ -374,10 +374,10 @@ impl<K: Ord, V> BSTMap<K, V> {
374374
Q: Ord + ?Sized,
375375
{
376376
let mut current = self.root_mut();
377-
while let Some(mut node) = current {
377+
while let Some(node) = current {
378378
match key.cmp(node.key().borrow()) {
379-
Ordering::Less => current = node.left(),
380-
Ordering::Greater => current = node.right(),
379+
Ordering::Less => current = node.into_left(),
380+
Ordering::Greater => current = node.into_right(),
381381
Ordering::Equal => return Some(node.into_entry_mut()),
382382
}
383383
}
@@ -422,7 +422,7 @@ impl<K: Ord, V> BSTMap<K, V> {
422422
node.push_left(key, value);
423423
break;
424424
}
425-
current = node.left();
425+
current = node.into_left();
426426
},
427427

428428
Ordering::Greater => {
@@ -431,7 +431,7 @@ impl<K: Ord, V> BSTMap<K, V> {
431431
node.push_right(key, value);
432432
break;
433433
}
434-
current = node.right();
434+
current = node.into_right();
435435
},
436436

437437
Ordering::Equal => {

src/map/node.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,31 @@ impl<'a, K, V> NodeMut<'a, K, V> {
192192
}
193193

194194
/// Returns the left child node (subtree) of this node, if any
195-
pub fn left(&mut self) -> Option<Self> {
195+
pub fn left(&'a mut self) -> Option<Self> {
196196
// Safety: Nodes only contain pointers to other nodes within `self.nodes`
197197
// Importantly, those pointers are to other *distinct* nodes, so there will never be any
198198
// overlap (we know they are distinct because trees have no cycles by definition)
199199
self.node.left.map(move |ptr| unsafe { Self::new(self.nodes, ptr) })
200200
}
201201

202202
/// Returns the right child node (subtree) of this node, if any
203-
pub fn right(&mut self) -> Option<Self> {
203+
pub fn right(&'a mut self) -> Option<Self> {
204+
// Safety: Nodes only contain pointers to other nodes within `self.nodes`
205+
// Importantly, those pointers are to other *distinct* nodes, so there will never be any
206+
// overlap (we know they are distinct because trees have no cycles by definition)
207+
self.node.right.map(move |ptr| unsafe { Self::new(self.nodes, ptr) })
208+
}
209+
210+
/// Returns the left child node (subtree) of this node, if any
211+
pub fn into_left(self) -> Option<Self> {
212+
// Safety: Nodes only contain pointers to other nodes within `self.nodes`
213+
// Importantly, those pointers are to other *distinct* nodes, so there will never be any
214+
// overlap (we know they are distinct because trees have no cycles by definition)
215+
self.node.left.map(move |ptr| unsafe { Self::new(self.nodes, ptr) })
216+
}
217+
218+
/// Returns the right child node (subtree) of this node, if any
219+
pub fn into_right(self) -> Option<Self> {
204220
// Safety: Nodes only contain pointers to other nodes within `self.nodes`
205221
// Importantly, those pointers are to other *distinct* nodes, so there will never be any
206222
// overlap (we know they are distinct because trees have no cycles by definition)

0 commit comments

Comments
 (0)