Skip to content

Commit 4e030f7

Browse files
committed
Prevent usage of self ID in modifiers working on bare ID
This allows the construction of otherwise nonsensical trees which might lead to unexpected panics further down the road.
1 parent 95aaf8b commit 4e030f7

File tree

3 files changed

+73
-11
lines changed

3 files changed

+73
-11
lines changed

src/lib.rs

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
494494
///
495495
/// Panics if `new_child_id` is not valid.
496496
pub fn append_id(&mut self, new_child_id: NodeId) -> NodeMut<T> {
497+
assert_ne!(
498+
self.id(),
499+
new_child_id,
500+
"Cannot append node as a child to itself"
501+
);
502+
497503
let last_child_id = self.node().children.map(|(_, id)| id);
498504
{
499505
let mut new_child = self.tree.get_mut(new_child_id).unwrap();
@@ -509,11 +515,10 @@ impl<'a, T: 'a> NodeMut<'a, T> {
509515
}
510516

511517
{
512-
if let Some((first_child_id, _)) = self.node().children {
513-
self.node().children = Some((first_child_id, new_child_id));
514-
} else {
515-
self.node().children = Some((new_child_id, new_child_id));
516-
}
518+
self.node().children = match self.node().children {
519+
Some((first_child_id, _)) => Some((first_child_id, new_child_id)),
520+
None => Some((new_child_id, new_child_id)),
521+
};
517522
}
518523

519524
unsafe { self.tree.get_unchecked_mut(new_child_id) }
@@ -525,6 +530,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
525530
///
526531
/// Panics if `new_child_id` is not valid.
527532
pub fn prepend_id(&mut self, new_child_id: NodeId) -> NodeMut<T> {
533+
assert_ne!(
534+
self.id(),
535+
new_child_id,
536+
"Cannot prepend node as a child to itself"
537+
);
538+
528539
let first_child_id = self.node().children.map(|(id, _)| id);
529540
{
530541
let mut new_child = self.tree.get_mut(new_child_id).unwrap();
@@ -540,11 +551,10 @@ impl<'a, T: 'a> NodeMut<'a, T> {
540551
}
541552

542553
{
543-
if let Some((_, last_child_id)) = self.node().children {
544-
self.node().children = Some((new_child_id, last_child_id));
545-
} else {
546-
self.node().children = Some((new_child_id, new_child_id));
547-
}
554+
self.node().children = match self.node().children {
555+
Some((_, last_child_id)) => Some((new_child_id, last_child_id)),
556+
None => Some((new_child_id, new_child_id)),
557+
};
548558
}
549559

550560
unsafe { self.tree.get_unchecked_mut(new_child_id) }
@@ -557,6 +567,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
557567
/// - Panics if `new_sibling_id` is not valid.
558568
/// - Panics if this node is an orphan.
559569
pub fn insert_id_before(&mut self, new_sibling_id: NodeId) -> NodeMut<T> {
570+
assert_ne!(
571+
self.id(),
572+
new_sibling_id,
573+
"Cannot insert node as a sibling of itself"
574+
);
575+
560576
let parent_id = self.node().parent.unwrap();
561577
let prev_sibling_id = self.node().prev_sibling;
562578

@@ -594,6 +610,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
594610
/// - Panics if `new_sibling_id` is not valid.
595611
/// - Panics if this node is an orphan.
596612
pub fn insert_id_after(&mut self, new_sibling_id: NodeId) -> NodeMut<T> {
613+
assert_ne!(
614+
self.id(),
615+
new_sibling_id,
616+
"Cannot insert node as a sibling of itself"
617+
);
618+
597619
let parent_id = self.node().parent.unwrap();
598620
let next_sibling_id = self.node().next_sibling;
599621

@@ -630,6 +652,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
630652
///
631653
/// Panics if `from_id` is not valid.
632654
pub fn reparent_from_id_append(&mut self, from_id: NodeId) {
655+
assert_ne!(
656+
self.id(),
657+
from_id,
658+
"Cannot reparent node's children to itself"
659+
);
660+
633661
let new_child_ids = {
634662
let mut from = self.tree.get_mut(from_id).unwrap();
635663
match from.node().children.take() {
@@ -663,6 +691,12 @@ impl<'a, T: 'a> NodeMut<'a, T> {
663691
///
664692
/// Panics if `from_id` is not valid.
665693
pub fn reparent_from_id_prepend(&mut self, from_id: NodeId) {
694+
assert_ne!(
695+
self.id(),
696+
from_id,
697+
"Cannot reparent node's children to itself"
698+
);
699+
666700
let new_child_ids = {
667701
let mut from = self.tree.get_mut(from_id).unwrap();
668702
match from.node().children.take() {

src/serde.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl<'a, T> From<NodeRef<'a, T>> for SerNode<'a, T> {
2828
}
2929
}
3030

31-
impl<'a, T: Serialize> Serialize for SerNode<'a, T> {
31+
impl<T: Serialize> Serialize for SerNode<'_, T> {
3232
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3333
where
3434
S: serde::Serializer,

tests/node_mut.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,34 @@ fn detach() {
311311
assert!(c.next_sibling().is_none());
312312
}
313313

314+
#[test]
315+
#[should_panic(expected = "Cannot append node as a child to itself")]
316+
fn append_id_itself() {
317+
let mut tree = tree! {
318+
'a' => {
319+
'b' => { 'c', 'd' },
320+
'e' => { 'f', 'g' },
321+
}
322+
};
323+
let mut a = tree.root_mut();
324+
let mut e = a.last_child().unwrap();
325+
e.append_id(e.id());
326+
}
327+
328+
#[test]
329+
#[should_panic(expected = "Cannot prepend node as a child to itself")]
330+
fn prepend_id_itself() {
331+
let mut tree = tree! {
332+
'a' => {
333+
'b' => { 'c', 'd' },
334+
'e' => { 'f', 'g' },
335+
}
336+
};
337+
let mut a = tree.root_mut();
338+
let mut e = a.last_child().unwrap();
339+
e.prepend_id(e.id());
340+
}
341+
314342
#[test]
315343
fn reparent_from_id_append() {
316344
let mut tree = tree! {

0 commit comments

Comments
 (0)