From 0d5bde0ce2d93241877e1c1caed8752115938670 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Thu, 10 Nov 2022 17:17:07 +0100 Subject: [PATCH] sys/net/gnrc/pkt: fix gnrc_pkt_delete() The previous implementation used creative construct for impedance mismatching between the core list API (which returns a ptr to the removed element if found) and the GNRC pkt list API (which returns a ptr to the new list head) that creates a temporary list head on the stack. I'm not entirely sure if the previous implementation is containing undefined behavior that is used against us with GCC >= 12.x, or if this is a compiler bug. In either case, not reusing the core list API here and just having a textbook linked list delete function here is not much less readable and fixes the issue for our users. --- sys/include/net/gnrc/pkt.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/sys/include/net/gnrc/pkt.h b/sys/include/net/gnrc/pkt.h index 88043f218d..7467f0bdc5 100644 --- a/sys/include/net/gnrc/pkt.h +++ b/sys/include/net/gnrc/pkt.h @@ -210,10 +210,26 @@ static inline gnrc_pktsnip_t *gnrc_pkt_prepend(gnrc_pktsnip_t *pkt, static inline gnrc_pktsnip_t *gnrc_pkt_delete(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t *snip) { - list_node_t list = { (list_node_t *)pkt }; + /* Removing head is a no-op. The new head is the next in the list. */ + if (pkt == snip) { + return pkt->next; + } - list_remove(&list, (list_node_t *)snip); - return (gnrc_pktsnip_t *)list.next; + /* Removing nothing is a no-op, the new head is the old one */ + if (snip == NULL) { + return pkt; + } + + /* Iterate over the list and remove the given snip from it, if found. + * The new head is the old head. */ + for (gnrc_pktsnip_t *i = pkt; i != NULL; i = i->next) { + if (i->next == snip) { + i->next = snip->next; + return pkt; + } + } + + return pkt; } /**