Skip to content

Commit 3efaff6

Browse files
committed
Deprecate out-of-bounds access possibility in safe code.
With the `id` and `tree` fields of `NodeRef` and `NodeMut` being public, it was possible to assign to them. For example, it was possible to build a `NodeMut` for large ID/index in a small tree/Vec. Since some APIs use unchecked indexing, this would let users of this library cause out-of-bounds access in a `Vec` without writing `unsafe` code themselves. This deprecates the fields, and instead providing read-only access via accessor methods. This lets dependent crates realize that there is a problem they might need to fix.
1 parent 3f6b678 commit 3efaff6

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ego-tree"
3-
version = "0.5.0"
3+
version = "0.5.1"
44
description = "Vec-backed ID-tree"
55
keywords = ["tree", "vec", "id", "index"]
66
authors = ["Curtis McEnroe <[email protected]>"]

src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,11 @@ impl<T> Node<T> {
7676
#[derive(Debug)]
7777
pub struct NodeRef<'a, T: 'a> {
7878
/// Node ID.
79+
#[deprecated(since = "0.5.1", note = "use the id() method instead and upgrade to 0.6")]
7980
pub id: NodeId,
8081

8182
/// Tree containing the node.
83+
#[deprecated(since = "0.5.1", note = "use the tree() method instead and upgrade to 0.6")]
8284
pub tree: &'a Tree<T>,
8385

8486
node: &'a Node<T>,
@@ -88,9 +90,11 @@ pub struct NodeRef<'a, T: 'a> {
8890
#[derive(Debug)]
8991
pub struct NodeMut<'a, T: 'a> {
9092
/// Node ID.
93+
#[deprecated(since = "0.5.1", note = "use the id() method instead and upgrade to 0.6")]
9194
pub id: NodeId,
9295

9396
/// Tree containing the node.
97+
#[deprecated(since = "0.5.1", note = "use the tree() method instead and upgrade to 0.6")]
9498
pub tree: &'a mut Tree<T>,
9599
}
96100

@@ -103,13 +107,15 @@ impl<'a, T: 'a> Clone for NodeRef<'a, T> {
103107

104108
impl<'a, T: 'a> Eq for NodeRef<'a, T> { }
105109
impl<'a, T: 'a> PartialEq for NodeRef<'a, T> {
110+
#[allow(deprecated)]
106111
fn eq(&self, other: &Self) -> bool {
107112
self.id == other.id
108113
&& self.tree as *const _ == other.tree as *const _
109114
&& self.node as *const _ == other.node as *const _
110115
}
111116
}
112117

118+
#[allow(deprecated)]
113119
impl<T> Tree<T> {
114120
/// Creates a tree with a root node.
115121
pub fn new(root: T) -> Self {
@@ -170,7 +176,18 @@ impl<T> Tree<T> {
170176
}
171177
}
172178

179+
#[allow(deprecated)]
173180
impl<'a, T: 'a> NodeRef<'a, T> {
181+
/// Returns the ID of this node.
182+
pub fn id(&self) -> NodeId {
183+
self.id
184+
}
185+
186+
/// Returns the tree owning this node.
187+
pub fn tree(&self) -> &'a Tree<T> {
188+
self.tree
189+
}
190+
174191
/// Returns the value of this node.
175192
pub fn value(&self) -> &'a T {
176193
&self.node.value
@@ -212,7 +229,18 @@ impl<'a, T: 'a> NodeRef<'a, T> {
212229
}
213230
}
214231

232+
#[allow(deprecated)]
215233
impl<'a, T: 'a> NodeMut<'a, T> {
234+
/// Returns the ID of this node.
235+
pub fn id(&self) -> NodeId {
236+
self.id
237+
}
238+
239+
/// Returns the tree owning this node.
240+
pub fn tree(&mut self) -> &mut Tree<T> {
241+
self.tree
242+
}
243+
216244
fn node(&mut self) -> &mut Node<T> {
217245
unsafe { self.tree.node_mut(self.id) }
218246
}
@@ -520,6 +548,7 @@ impl<'a, T: 'a> NodeMut<'a, T> {
520548
}
521549
}
522550

551+
#[allow(deprecated)]
523552
impl<'a, T: 'a> From<NodeMut<'a, T>> for NodeRef<'a, T> {
524553
fn from(node: NodeMut<'a, T>) -> Self {
525554
unsafe { node.tree.get_unchecked(node.id) }

tests/node_mut.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ fn reparent_from_id_append() {
298298
'e' => { 'f', 'g' },
299299
}
300300
};
301-
let e_id = tree.root().last_child().unwrap().id;
301+
let e_id = tree.root().last_child().unwrap().id();
302302
tree.root_mut().first_child().unwrap().reparent_from_id_append(e_id);
303303

304304
let b = tree.root().first_child().unwrap();
@@ -322,7 +322,7 @@ fn reparent_from_id_prepend() {
322322
'e' => { 'c', 'd' },
323323
}
324324
};
325-
let e_id = tree.root().last_child().unwrap().id;
325+
let e_id = tree.root().last_child().unwrap().id();
326326
tree.root_mut().first_child().unwrap().reparent_from_id_prepend(e_id);
327327

328328
let b = tree.root().first_child().unwrap();

tests/tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@ fn orphan() {
3737
#[test]
3838
fn get() {
3939
let tree = Tree::new('a');
40-
let id = tree.root().id;
40+
let id = tree.root().id();
4141
assert_eq!(Some(tree.root()), tree.get(id));
4242
}
4343

4444
#[test]
4545
fn get_mut() {
4646
let mut tree = Tree::new('a');
47-
let id = tree.root().id;
47+
let id = tree.root().id();
4848
assert_eq!(Some('a'), tree.get_mut(id).map(|mut n| *n.value()));
4949
}
5050

0 commit comments

Comments
 (0)