Bad bug in gsequence



There is a bad bug in the version of EggSequence that nautilus is
using. Basically it will sometimes cast the data pointer you insert
into it to an EggSequence *, then attempt to read the first member.
If that read succeeds, it will then compare the data to the
end-iterator for the sequence. If they match, various bad things will
happen.

I believe for nautilus this is likely harmless as the dereferenced
memory is valid, and the items inserted are FileEntries whose first
member is a pointer to NautilusFile, which can never match the
end-iterator for the sequence. 

The attached patch, by James Livingston, fixes it. It should certainly
be applied to HEAD, and probably also stable.

This is bug http://bugzilla.gnome.org/show_bug.cgi?id=350579 against
libegg/sequence.


Søren

? seq-fix
Index: gsequence.c
===================================================================
RCS file: /cvs/gnome/nautilus/cut-n-paste-code/gsequence/gsequence.c,v
retrieving revision 1.4
diff -u -r1.4 gsequence.c
--- gsequence.c	25 Jul 2006 13:55:49 -0000	1.4
+++ gsequence.c	2 Dec 2006 21:36:32 -0000
@@ -51,6 +51,7 @@
 					    gint               pos);
 static GSequenceNode *node_find_closest  (GSequenceNode   *haystack,
 					    GSequenceNode   *needle,
+					    GSequenceNode   *end,
 					    GSequenceIterCompareFunc cmp,
 					    gpointer           user_data);
 static gint             node_get_length    (GSequenceNode   *node);
@@ -64,6 +65,7 @@
 static void             node_unlink        (GSequenceNode   *node);
 static void             node_insert_sorted (GSequenceNode   *node,
 					    GSequenceNode   *new,
+					    GSequenceNode   *end,
 					    GSequenceIterCompareFunc cmp_func,
 					    gpointer           cmp_data);
 
@@ -411,6 +413,7 @@
 {
     GCompareDataFunc    cmp_func;
     gpointer		cmp_data;
+    GSequenceNode	*end_node;
 } SortInfo;
 
 /* This function compares two iters using a normal compare
@@ -424,10 +427,10 @@
     const SortInfo *info = data;
     gint retval;
     
-    if (is_end (node1))
+    if (node1 == info->end_node)
 	return 1;
     
-    if (is_end (node2))
+    if (node2 == info->end_node)
 	return -1;
     
     retval = info->cmp_func (node1->data, node2->data, info->cmp_data);
@@ -452,7 +455,7 @@
 		   GCompareDataFunc  cmp_func,
 		   gpointer          cmp_data)
 {
-    SortInfo info = { cmp_func, cmp_data };
+    SortInfo info = { cmp_func, cmp_data, seq->end_node };
     
     check_seq_access (seq);
     
@@ -480,11 +483,12 @@
 			    GCompareDataFunc   cmp_func,
 			    gpointer           cmp_data)
 {
-    SortInfo info = { cmp_func, cmp_data };
+    SortInfo info = { cmp_func, cmp_data, NULL };
     
     g_return_val_if_fail (seq != NULL, NULL);
     g_return_val_if_fail (cmp_func != NULL, NULL);
     
+    info.end_node = seq->end_node;
     check_seq_access (seq);
     
     return g_sequence_insert_sorted_iter (seq, data, iter_compare, &info);
@@ -495,10 +499,11 @@
 			   GCompareDataFunc  cmp_func,
 			   gpointer          cmp_data)
 {
-    SortInfo info = { cmp_func, cmp_data };
+    SortInfo info = { cmp_func, cmp_data, NULL };
     
     g_return_if_fail (!is_end (iter));
     
+    info.end_node = get_sequence (iter)->end_node;
     check_iter_access (iter);
     
     g_sequence_sort_changed_iter (iter, iter_compare, &info);
@@ -533,7 +538,7 @@
 	
 	node_unlink (node);
 	
-	node_insert_sorted (seq->end_node, node, cmp_func, cmp_data);
+	node_insert_sorted (seq->end_node, node, seq->end_node, cmp_func, cmp_data);
     }
     
     tmp->access_prohibited = FALSE;
@@ -558,7 +563,7 @@
     seq->access_prohibited = TRUE;
     
     node_unlink (iter);
-    node_insert_sorted (seq->end_node, iter, iter_cmp, cmp_data);
+    node_insert_sorted (seq->end_node, iter, seq->end_node, iter_cmp, cmp_data);
     
     seq->access_prohibited = FALSE;
 }
@@ -574,7 +579,7 @@
     check_seq_access (seq);
     
     new_node = node_new (data);
-    node_insert_sorted (seq->end_node, new_node, iter_cmp, cmp_data);
+    node_insert_sorted (seq->end_node, new_node, seq->end_node, iter_cmp, cmp_data);
     return new_node;
 }
 
@@ -595,7 +600,7 @@
 
     dummy = node_new (data);
     
-    node = node_find_closest (seq->end_node, dummy, cmp_func, cmp_data);
+    node = node_find_closest (seq->end_node, dummy, seq->end_node, cmp_func, cmp_data);
 
     node_free (dummy, NULL);
     
@@ -624,10 +629,11 @@
 		     GCompareDataFunc  cmp_func,
 		     gpointer          cmp_data)
 {
-    SortInfo info = { cmp_func, cmp_data };
+    SortInfo info = { cmp_func, cmp_data, NULL };
     
     g_return_val_if_fail (seq != NULL, NULL);
     
+    info.end_node = seq->end_node;
     check_seq_access (seq);
     
     return g_sequence_search_iter (seq, data, iter_compare, &info);
@@ -1109,6 +1115,7 @@
 static GSequenceNode *
 node_find_closest (GSequenceNode	      *haystack,
 		   GSequenceNode	      *needle,
+		   GSequenceNode            *end,
 		   GSequenceIterCompareFunc  cmp_func,
 		   gpointer		       cmp_data)
 {
@@ -1123,7 +1130,7 @@
     {
 	best = haystack;
 	
-	if (is_end (haystack))
+	if (haystack == end)
 	    c = 1;
 	else
 	    c = cmp_func (haystack, needle, cmp_data);
@@ -1285,12 +1292,13 @@
 static void
 node_insert_sorted (GSequenceNode *node,
 		    GSequenceNode *new,
+		    GSequenceNode *end,
 		    GSequenceIterCompareFunc cmp_func,
 		    gpointer cmp_data)
 {
     GSequenceNode *closest;
     
-    closest = node_find_closest (node, new, cmp_func, cmp_data);
+    closest = node_find_closest (node, new, end, cmp_func, cmp_data);
     
     node_insert_before (closest, new);
 }
Index: gsequence.h
===================================================================
RCS file: /cvs/gnome/nautilus/cut-n-paste-code/gsequence/gsequence.h,v
retrieving revision 1.2
diff -u -r1.2 gsequence.h
--- gsequence.h	25 Jul 2006 13:55:49 -0000	1.2
+++ gsequence.h	2 Dec 2006 21:36:32 -0000
@@ -26,6 +26,7 @@
 typedef struct _GSequenceNode  GSequenceIter;
 
 
+
 typedef gint (* GSequenceIterCompareFunc) (GSequenceIter *a,
 					     GSequenceIter *b,
 					     gpointer	      data);
@@ -65,6 +66,8 @@
 						   gpointer                data);
 void		 g_sequence_move		  (GSequenceIter *	   src,
 						   GSequenceIter *	   dest);
+void		 g_sequence_swap                (GSequenceIter *       a,
+						   GSequenceIter *       b);
 GSequenceIter *g_sequence_insert_sorted        (GSequence            *seq,
 						   gpointer                data,
 						   GCompareDataFunc        cmp_func,
@@ -110,8 +113,6 @@
 GSequenceIter *g_sequence_iter_move            (GSequenceIter *        iter,
 						   gint                    leap);
 GSequence *   g_sequence_iter_get_sequence    (GSequenceIter *        iter);
-void         g_sequence_swap                  (GSequenceIter *a,
-					       GSequenceIter *b);
 
 
 /* search */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]