Skip to content

Commit

Permalink
sys/net/gnrc/pkt: fix gnrc_pkt_delete()
Browse files Browse the repository at this point in the history
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.

(cherry picked from commit 0d5bde0)
  • Loading branch information
maribu committed Nov 11, 2022
1 parent ca32dfb commit 30caf76
Showing 1 changed file with 19 additions and 3 deletions.
22 changes: 19 additions & 3 deletions sys/include/net/gnrc/pkt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/* Removing nothing is a no-op, the new head is the old one */
if (snip == NULL) {
return pkt;
}

list_remove(&list, (list_node_t *)snip);
return (gnrc_pktsnip_t *)list.next;
/* 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;
}

/**
Expand Down

0 comments on commit 30caf76

Please sign in to comment.