mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-05 10:38:08 +01:00
GList: be more robust
We can detect list corruption in some cases. The new test case demonstrates a case where we can warn instead of silently corrupt the list. This was pointed out by Steve Grubb. Also, use the same auxiliary routine in all places where we unlink a list element.
This commit is contained in:
parent
6833267a07
commit
921593b022
69
glib/glist.c
69
glib/glist.c
@ -32,6 +32,7 @@
|
||||
|
||||
#include "glist.h"
|
||||
#include "gslice.h"
|
||||
#include "gmessages.h"
|
||||
|
||||
#include "gtestutils.h"
|
||||
|
||||
@ -420,6 +421,34 @@ g_list_concat (GList *list1, GList *list2)
|
||||
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
|
||||
@ -436,7 +465,7 @@ g_list_remove (GList *list,
|
||||
gconstpointer data)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
|
||||
tmp = list;
|
||||
while (tmp)
|
||||
{
|
||||
@ -444,16 +473,9 @@ g_list_remove (GList *list,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -465,9 +487,9 @@ g_list_remove (GList *list,
|
||||
* @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
|
||||
@ -500,27 +522,6 @@ g_list_remove_all (GList *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
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <glib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define SIZE 50
|
||||
#define NUMBER_MIN 0000
|
||||
@ -488,6 +489,31 @@ test_position (void)
|
||||
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[])
|
||||
{
|
||||
@ -516,6 +542,7 @@ 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 ();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user