#include "glist.h"
#include "gslice.h"
+#include "gmessages.h"
#include "gtestutils.h"
return list1;
}
+static inline GList*
+_g_list_remove_link (GList *list,
+ GList *link)
+{
+ if (link->prev)
+ {
+ if (link->prev->next == link)
+ link->prev->next = link->next;
+ else
+ g_warning ("corrupted double-linked list detected");
+ }
+ if (link->next)
+ {
+ if (link->next->prev == link)
+ link->next->prev = link->prev;
+ else
+ g_warning ("corrupted double-linked list detected");
+ }
+
+ if (link == list)
+ list = list->next;
+
+ link->next = NULL;
+ link->prev = NULL;
+
+ return list;
+}
+
/**
* g_list_remove:
* @list: a #GList
gconstpointer data)
{
GList *tmp;
-
+
tmp = list;
while (tmp)
{
tmp = tmp->next;
else
{
- if (tmp->prev)
- tmp->prev->next = tmp->next;
- if (tmp->next)
- tmp->next->prev = tmp->prev;
-
- if (list == tmp)
- list = list->next;
-
+ list = _g_list_remove_link (list, tmp);
_g_list_free1 (tmp);
-
+
break;
}
}
* @list: a #GList
* @data: data to remove
*
- * Removes all list nodes with data equal to @data.
- * Returns the new head of the list. Contrast with
- * g_list_remove() which removes only the first node
+ * Removes all list nodes with data equal to @data.
+ * Returns the new head of the list. Contrast with
+ * g_list_remove() which removes only the first node
* matching the given data.
*
* Returns: new head of @list
return list;
}
-static inline GList*
-_g_list_remove_link (GList *list,
- GList *link)
-{
- if (link)
- {
- if (link->prev)
- link->prev->next = link->next;
- if (link->next)
- link->next->prev = link->prev;
-
- if (link == list)
- list = list->next;
-
- link->next = NULL;
- link->prev = NULL;
- }
-
- return list;
-}
-
/**
* g_list_remove_link:
* @list: a #GList
#include <glib.h>
+#include <stdlib.h>
#define SIZE 50
#define NUMBER_MIN 0000
g_list_free (ll);
}
+static void
+test_double_free (void)
+{
+ if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDERR))
+ {
+ GList *list, *link;
+ GList intruder = { NULL, (gpointer)0xDEADBEEF, (gpointer)0xDEADBEEF };
+
+ list = NULL;
+ list = g_list_append (list, "a");
+ link = list = g_list_append (list, "b");
+ list = g_list_append (list, "c");
+
+ list = g_list_remove_link (list, link);
+ link->prev = list;
+ link->next = &intruder;
+ list = g_list_remove_link (list, link);
+
+ g_list_free (list);
+ exit (0);
+ }
+ g_test_trap_assert_failed ();
+ g_test_trap_assert_stderr ("*corrupted double-linked list detected*");
+}
+
int
main (int argc, char *argv[])
{
g_test_add_func ("/list/delete-link", test_delete_link);
g_test_add_func ("/list/prepend", test_prepend);
g_test_add_func ("/list/position", test_position);
+ g_test_add_func ("/list/double-free", test_double_free);
return g_test_run ();
}