summaryrefslogtreecommitdiff
path: root/gtk/gtkrbtree.c
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2011-11-21 21:13:53 +0100
committerBenjamin Otte <otte@redhat.com>2011-11-21 22:33:46 +0100
commit647c441e2672e35ef92d697dabd90c372d2402cb (patch)
tree08c87b24b76fb55005ec7ef40f3da6c770bf7e35 /gtk/gtkrbtree.c
parentf4fe921a174897844ec7f2896597f60b0a206903 (diff)
downloadgtk+-647c441e2672e35ef92d697dabd90c372d2402cb.tar.gz
rbtree: Don't write to nil node
The code used to set nil->parent, which could cause segfaults. Don't do that. We also need to pass the parent explicitly to the fixup code, because the node during fixup may be the nil node.
Diffstat (limited to 'gtk/gtkrbtree.c')
-rw-r--r--gtk/gtkrbtree.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/gtk/gtkrbtree.c b/gtk/gtkrbtree.c
index 1b6f0298be..c9ad44585c 100644
--- a/gtk/gtkrbtree.c
+++ b/gtk/gtkrbtree.c
@@ -31,7 +31,8 @@ static void _gtk_rbnode_rotate_right (GtkRBTree *tree,
static void _gtk_rbtree_insert_fixup (GtkRBTree *tree,
GtkRBNode *node);
static void _gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
- GtkRBNode *node);
+ GtkRBNode *node,
+ GtkRBNode *parent);
static inline void _fixup_validation (GtkRBTree *tree,
GtkRBNode *node);
static inline void _fixup_total_count (GtkRBTree *tree,
@@ -264,10 +265,9 @@ _gtk_rbtree_insert_fixup (GtkRBTree *tree,
static void
_gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
- GtkRBNode *node)
+ GtkRBNode *node,
+ GtkRBNode *parent)
{
- GtkRBNode *parent = node->parent;
-
while (node != tree->root && GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
{
if (node == parent->left)
@@ -1184,7 +1184,8 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
x = y->right;
/* remove y from the parent chain */
- x->parent = y->parent;
+ if (x != tree->nil)
+ x->parent = y->parent;
if (y->parent != tree->nil)
{
if (y == y->parent->left)
@@ -1201,6 +1202,9 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
*/
gtk_rbnode_adjust (tree, y, -1, - y_total_count, - y_height);
+ if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
+ _gtk_rbtree_remove_node_fixup (tree, x, y->parent);
+
if (y != node)
{
gint node_height, node_total_count;
@@ -1215,10 +1219,7 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
/* Move the node over */
if (GTK_RBNODE_GET_COLOR (node) != GTK_RBNODE_GET_COLOR (y))
- {
- node->flags ^= (GTK_RBNODE_BLACK | GTK_RBNODE_RED);
- y->flags ^= (GTK_RBNODE_BLACK | GTK_RBNODE_RED);
- }
+ y->flags ^= (GTK_RBNODE_BLACK | GTK_RBNODE_RED);
y->left = node->left;
if (y->left != tree->nil)
@@ -1248,8 +1249,6 @@ _gtk_rbtree_remove_node (GtkRBTree *tree,
y_height - node_height);
}
- if (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
- _gtk_rbtree_remove_node_fixup (tree, x);
_gtk_rbnode_free (node);
#ifdef G_ENABLE_DEBUG