]> git.ipfire.org Git - thirdparty/knot-dns.git/commitdiff
ucw lists: fix overlapping structures causing a problems at arm architectures
authorJan Hak <jan.hak@nic.cz>
Fri, 30 Jul 2021 14:49:52 +0000 (16:49 +0200)
committerDaniel Salzman <daniel.salzman@nic.cz>
Thu, 5 Aug 2021 06:14:46 +0000 (08:14 +0200)
src/contrib/ucw/lists.c
src/contrib/ucw/lists.h

index 84c6eaa839e946c85e6b9fbeed5491e3ecb6baec..6e6650a7e0a0e821a38b20da059098dd8bc0d370 100644 (file)
@@ -2,7 +2,7 @@
  *     BIRD Library -- Linked Lists
  *
  *     (c) 1998 Martin Mares <mj@ucw.cz>
- *     (c) 2015, 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+ *     (c) 2015, 2020-2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
  * similar to that used in the &fib structure.
  */
 
+#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
+
 #include "contrib/ucw/lists.h"
 #include "contrib/mempattern.h"
 
 void
 add_tail(list_t *l, node_t *n)
 {
-  node_t *z = l->tail;
+  node_t *z = &l->tail;
 
-  n->next = (node_t *) &l->null;
-  n->prev = z;
-  z->next = n;
-  l->tail = n;
+  n->next = z;
+  n->prev = z->prev;
+  z->prev->next = n;
+  z->prev = n;
+  assert(z->next == NULL);
 }
 
 /**
@@ -58,12 +61,13 @@ add_tail(list_t *l, node_t *n)
 void
 add_head(list_t *l, node_t *n)
 {
-  node_t *z = l->head;
+  node_t *z = &l->head;
 
-  n->next = z;
-  n->prev = (node_t *) &l->head;
-  z->prev = n;
-  l->head = n;
+  n->next = z->next;
+  n->prev = z;
+  z->next->prev = n;
+  z->next = n;
+  assert(z->prev == NULL);
 }
 
 /**
@@ -113,9 +117,10 @@ rem_node(node_t *n)
 void
 init_list(list_t *l)
 {
-  l->head = (node_t *) &l->null;
-  l->null = NULL;
-  l->tail = (node_t *) &l->head;
+  l->head.next = &l->tail;
+  l->head.prev = NULL;
+  l->tail.next = NULL;
+  l->tail.prev = &l->head;
 }
 
 /**
@@ -129,14 +134,12 @@ init_list(list_t *l)
 void
 add_tail_list(list_t *to, list_t *l)
 {
-  node_t *p = to->tail;
-  node_t *q = l->head;
+  node_t *p = to->tail.prev;
+  node_t *q = l->head.next;
 
   p->next = q;
   q->prev = p;
-  q = l->tail;
-  q->next = (node_t *) &to->null;
-  to->tail = q;
+  to->tail.prev = l->tail.prev;
 }
 
 /**
index 305806ad33e965bc06af192aadb759f61ad8e7f9..ee06e7d15efc4b5fb413e03d2a46c0f5b6ac9e13 100644 (file)
@@ -2,26 +2,13 @@
  *     BIRD Library -- Linked Lists
  *
  *     (c) 1998 Martin Mares <mj@ucw.cz>
- *     (c) 2015, 2020 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
+ *     (c) 2015, 2020-2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
 #pragma once
 
-/*
- * I admit the list structure is very tricky and also somewhat awkward,
- * but it's both efficient and easy to manipulate once one understands the
- * basic trick: The list head always contains two synthetic nodes which are
- * always present in the list: the head and the tail. But as the `next'
- * entry of the tail and the `prev' entry of the head are both NULL, the
- * nodes can overlap each other:
- *
- *     head    head_node.next
- *     null    head_node.prev  tail_node.next
- *     tail                    tail_node.prev
- */
-
 #include <string.h>
 #include "libknot/mm_ctx.h"
 
@@ -29,13 +16,13 @@ typedef struct node {
   struct node *next, *prev;
 } node_t;
 
-typedef struct list {                  /* In fact two overlayed nodes */
-  struct node *head, *null, *tail;
+typedef struct list {
+  node_t head, tail;
 } list_t;
 
 #define NODE (node_t *)
-#define HEAD(list) ((void *)((list).head))
-#define TAIL(list) ((void *)((list).tail))
+#define HEAD(list) ((void *)((list).head.next))
+#define TAIL(list) ((void *)((list).tail.prev))
 #define WALK_LIST(n,list) for(n=HEAD(list);(NODE (n))->next; \
                                n=(void *)((NODE (n))->next))
 #define WALK_LIST_DELSAFE(n,nxt,list) \
@@ -48,7 +35,7 @@ typedef struct list {                 /* In fact two overlayed nodes */
 #define WALK_LIST_BACKWARDS_DELSAFE(n,prv,list) \
      for(n=TAIL(list); prv=(void *)((NODE (n))->prev); n=(void *) prv)
 
-#define EMPTY_LIST(list) (!(list).head->next)
+#define EMPTY_LIST(list) (!(NODE HEAD(list))->next)
 
 /*! \brief Free every node in the list. */
 #define WALK_LIST_FREE(list) \