[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] [bug #57377] Assertion "pbuf_free: p->ref > 0" failed

From: Erik Ekman
Subject: [lwip-devel] [bug #57377] Assertion "pbuf_free: p->ref > 0" failed
Date: Fri, 19 Jun 2020 08:55:35 -0400 (EDT)
User-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36

Follow-up Comment #3, bug #57377 (project lwip):

I agree that this looks like a double free.

tcp_slowtmr: processing active pcb
pbuf_alloc(length=1) == 0x43d816
tcp_create_segment: no memory.
pbuf_free: deallocating 0x43d816
tcp_split_unsent_seg: could not create new TCP segment
Assertion "pbuf_free: p->ref > 0" failed at line 753 in ../../src/core/pbuf.c

tcp_create_segment() frees the pbuf pointer, but this is not noticed by the
caller since the pbuf was sent as a normal pointer (not pointer to pointer):

static struct tcp_seg *
tcp_create_segment(const struct tcp_pcb *pcb, struct pbuf *p, u8_t hdrflags,
u32_t seqno, u8_t optflags);

Callers to tcp_create_segment:

tcp_write() line 666:
- Does not free the pbuf on error

tcp_split_unsent_seg() line 914:
- Does free pbuf on error (the case found in this bug)

tcp_enqueue_flags() line 1085:
- Does not free the pbuf on error

It seems the standard is to expect that the pbuf is freed, and
tcp_split_unsent_seg() should be updated to not try to free it again.

My proposed fix would be:

diff --git a/src/core/tcp_out.c b/src/core/tcp_out.c
index bfb033b1..d9d1b57b 100644
--- a/src/core/tcp_out.c
+++ b/src/core/tcp_out.c
@@ -913,6 +913,7 @@ tcp_split_unsent_seg(struct tcp_pcb *pcb, u16_t split)
   seg = tcp_create_segment(pcb, p, remainder_flags,
lwip_ntohl(useg->tcphdr->seqno) + split, optflags);
   if (seg == NULL) {
+    p = NULL; /* Freed by tcp_create_segment */
                 ("tcp_split_unsent_seg: could not create new TCP
     goto memerr;

which removes the double free, and makes the test input not crash.

Supplying a pointer to pointer to tcp_create_segment is more work, and there
are many ways the pbuf can be freed (like via tcp_seg_free, so it would be
easy to miss resetting the pbuf pointer).


Reply to this item at:


  Message sent via Savannah

reply via email to

[Prev in Thread] Current Thread [Next in Thread]