From e32fc5ad0ea1a2d69f12d9208f2de489f7ee9737 Mon Sep 17 00:00:00 2001 From: Pauli Date: Tue, 11 Oct 2022 19:59:24 +1100 Subject: QUIC tx record layer: use list.h As opposed to implementing a linked list explicitly. Reviewed-by: Tim Hudson Reviewed-by: Shane Lontis (Merged from https://github.com/openssl/openssl/pull/19377) --- ssl/quic/quic_record_tx.c | 104 +++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 65 deletions(-) diff --git a/ssl/quic/quic_record_tx.c b/ssl/quic/quic_record_tx.c index 20a3a76381..24cae9a44e 100644 --- a/ssl/quic/quic_record_tx.c +++ b/ssl/quic/quic_record_tx.c @@ -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; -- cgit v1.2.3