QUIC tx record layer: use list.h
authorPauli <pauli@openssl.org>
Tue, 11 Oct 2022 08:59:24 +0000 (19:59 +1100)
committerPauli <pauli@openssl.org>
Wed, 16 Nov 2022 07:02:02 +0000 (18:02 +1100)
As opposed to implementing a linked list explicitly.

Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/19377)

ssl/quic/quic_record_tx.c

index 20a3a76381899537b1432e7fb3c0b5cfcf56dd80..24cae9a44e033aa3549756a1a5ed97d36ea4507f 100644 (file)
@@ -11,6 +11,7 @@
 #include "internal/bio_addr.h"
 #include "internal/common.h"
 #include "quic_record_shared.h"
+#include "internal/list.h"
 #include "../ssl_local.h"
 
 /*
@@ -22,7 +23,7 @@
 typedef struct txe_st TXE;
 
 struct txe_st {
-    TXE                *prev, *next;
+    OSSL_LIST_MEMBER(txe, TXE);
     size_t              data_len, alloc_len;
 
     /*
@@ -37,44 +38,14 @@ struct txe_st {
      */
 };
 
+DEFINE_LIST_OF(txe, TXE);
+typedef OSSL_LIST(txe) TXE_LIST;
+
 static ossl_inline unsigned char *txe_data(const TXE *e)
 {
     return (unsigned char *)(e + 1);
 }
 
-typedef struct txe_list_st {
-    TXE *head, *tail;
-} TXE_LIST;
-
-static void txe_remove(TXE_LIST *l, TXE *e)
-{
-    if (e->prev != NULL)
-        e->prev->next = e->next;
-    if (e->next != NULL)
-        e->next->prev = e->prev;
-
-    if (e == l->head)
-        l->head = e->next;
-    if (e == l->tail)
-        l->tail = e->prev;
-
-    e->next = e->prev = NULL;
-}
-
-static void txe_insert_tail(TXE_LIST *l, TXE *e)
-{
-    if (l->tail == NULL) {
-        l->head = l->tail = e;
-        e->next = e->prev = NULL;
-        return;
-    }
-
-    l->tail->next = e;
-    e->prev = l->tail;
-    e->next = NULL;
-    l->tail = e;
-}
-
 /*
  * QTX
  * ===
@@ -145,11 +116,11 @@ OSSL_QTX *ossl_qtx_new(const OSSL_QTX_ARGS *args)
 static void qtx_cleanup_txl(TXE_LIST *l)
 {
     TXE *e, *enext;
-    for (e = l->head; e != NULL; e = enext) {
-        enext = e->next;
+
+    for (e = ossl_list_txe_head(l); e != NULL; e = enext) {
+        enext = ossl_list_txe_next(e);
         OPENSSL_free(e);
     }
-    l->head = l->tail = NULL;
 }
 
 /* Frees the QTX. */
@@ -212,9 +183,9 @@ static TXE *qtx_alloc_txe(size_t alloc_len)
     if (txe == NULL)
         return NULL;
 
-    txe->prev = txe->next = NULL;
+    ossl_list_txe_init_elem(txe);
     txe->alloc_len = alloc_len;
-    txe->data_len  = 0;
+    txe->data_len = 0;
     return txe;
 }
 
@@ -229,14 +200,15 @@ static TXE *qtx_ensure_free_txe(OSSL_QTX *qtx, size_t alloc_len)
 {
     TXE *txe;
 
-    if (qtx->free.head != NULL)
-        return qtx->free.head;
+    txe = ossl_list_txe_head(&qtx->free);
+    if (txe != NULL)
+        return txe;
 
     txe = qtx_alloc_txe(alloc_len);
     if (txe == NULL)
         return NULL;
 
-    txe_insert_tail(&qtx->free, txe);
+    ossl_list_txe_insert_tail(&qtx->free, txe);
     return txe;
 }
 
@@ -247,7 +219,7 @@ static TXE *qtx_ensure_free_txe(OSSL_QTX *qtx, size_t alloc_len)
  */
 static TXE *qtx_resize_txe(OSSL_QTX *qtx, TXE_LIST *txl, TXE *txe, size_t n)
 {
-    TXE *txe2;
+    TXE *txe2, *p;
 
     /* Should never happen. */
     if (txe == NULL)
@@ -256,26 +228,28 @@ static TXE *qtx_resize_txe(OSSL_QTX *qtx, TXE_LIST *txl, TXE *txe, size_t n)
     if (n >= SIZE_MAX - sizeof(TXE))
         return NULL;
 
+    /* Remove the item from the list to avoid accessing freed memory */
+    p = ossl_list_txe_prev(txe);
+    ossl_list_txe_remove(txl, txe);
+
     /*
      * NOTE: We do not clear old memory, although it does contain decrypted
      * data.
      */
     txe2 = OPENSSL_realloc(txe, sizeof(TXE) + n);
-    if (txe2 == NULL)
-        /* original TXE is still in tact unchanged */
-        return NULL;
-
-    if (txl != NULL && txe != txe2) {
-        if (txl->head == txe)
-            txl->head = txe2;
-        if (txl->tail == txe)
-            txl->tail = txe2;
-        if (txe->prev != NULL)
-            txe->prev->next = txe2;
-        if (txe->next != NULL)
-            txe->next->prev = txe2;
+    if (txe2 == NULL || txe == txe2) {
+        if (p == NULL)
+            ossl_list_txe_insert_head(txl, txe);
+        else
+            ossl_list_txe_insert_after(txl, p, txe);
+        return txe2;
     }
 
+    if (p == NULL)
+        ossl_list_txe_insert_head(txl, txe2);
+    else
+        ossl_list_txe_insert_after(txl, p, txe2);
+
     if (qtx->cons == txe)
         qtx->cons = txe2;
 
@@ -299,19 +273,19 @@ static TXE *qtx_reserve_txe(OSSL_QTX *qtx, TXE_LIST *txl,
 /* Move a TXE from pending to free. */
 static void qtx_pending_to_free(OSSL_QTX *qtx)
 {
-    TXE *txe = qtx->pending.head;
+    TXE *txe = ossl_list_txe_head(&qtx->pending);
 
     assert(txe != NULL);
-    txe_remove(&qtx->pending, txe);
+    ossl_list_txe_remove(&qtx->pending, txe);
     --qtx->pending_count;
     qtx->pending_bytes -= txe->data_len;
-    txe_insert_tail(&qtx->free, txe);
+    ossl_list_txe_insert_tail(&qtx->free, txe);
 }
 
 /* Add a TXE not currently in any list to the pending list. */
 static void qtx_add_to_pending(OSSL_QTX *qtx, TXE *txe)
 {
-    txe_insert_tail(&qtx->pending, txe);
+    ossl_list_txe_insert_tail(&qtx->pending, txe);
     ++qtx->pending_count;
     qtx->pending_bytes += txe->data_len;
 }
@@ -649,7 +623,7 @@ static TXE *qtx_ensure_cons(OSSL_QTX *qtx)
     if (txe == NULL)
         return NULL;
 
-    txe_remove(&qtx->free, txe);
+    ossl_list_txe_remove(&qtx->free, txe);
     qtx->cons = txe;
     qtx->cons_count = 0;
     txe->data_len = 0;
@@ -780,7 +754,7 @@ void ossl_qtx_finish_dgram(OSSL_QTX *qtx)
          * If we did not put anything in the datagram, just move it back to the
          * free list.
          */
-        txe_insert_tail(&qtx->free, txe);
+        ossl_list_txe_insert_tail(&qtx->free, txe);
     else
         qtx_add_to_pending(qtx, txe);
 
@@ -811,9 +785,9 @@ void ossl_qtx_flush_net(OSSL_QTX *qtx)
         return;
 
     for (;;) {
-        for (txe = qtx->pending.head, i = 0;
+        for (txe = ossl_list_txe_head(&qtx->pending), i = 0;
              txe != NULL && i < OSSL_NELEM(msg);
-             txe = txe->next, ++i)
+             txe = ossl_list_txe_next(txe), ++i)
             txe_to_msg(txe, &msg[i]);
 
         if (!i)
@@ -837,7 +811,7 @@ void ossl_qtx_flush_net(OSSL_QTX *qtx)
 
 int ossl_qtx_pop_net(OSSL_QTX *qtx, BIO_MSG *msg)
 {
-    TXE *txe = qtx->pending.head;
+    TXE *txe = ossl_list_txe_head(&qtx->pending);
 
     if (txe == NULL)
         return 0;