From 8d3d08e814e2707773a6ff1622ffe92a34ab1076 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Tue, 4 Dec 2007 20:41:12 +0000 Subject: [PATCH] fix bug #21699 (segment leak in ooseq): add assert that all segment lists are empty in tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED state from LAST_ACK in tcp_process --- CHANGELOG | 6 ++++++ src/core/tcp.c | 11 ++++++++++- src/core/tcp_in.c | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index dd43bbf9..1eb48747 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -512,6 +512,12 @@ HISTORY ++ Bug fixes: + 2007-12-04 Simon Goldschmidt + * tcp.c, tcp_in.c: fix bug #21699 (segment leak in ooseq processing when last + data packet was lost): add assert that all segment lists are empty in + tcp_pcb_remove before setting pcb to CLOSED state; don't directly set CLOSED + state from LAST_ACK in tcp_process + 2007-12-02 Simon Goldschmidt * sockets.h: fix bug #21654: exclude definition of struct timeval from #ifndef FD_SET If including for system-struct timeval, LWIP_TIMEVAL_PRIVATE now diff --git a/src/core/tcp.c b/src/core/tcp.c index a794c685..40256d2e 100644 --- a/src/core/tcp.c +++ b/src/core/tcp.c @@ -1138,7 +1138,16 @@ tcp_pcb_remove(struct tcp_pcb **pcblist, struct tcp_pcb *pcb) pcb->flags & TF_ACK_DELAY) { pcb->flags |= TF_ACK_NOW; tcp_output(pcb); - } + } + + if (pcb->state != LISTEN) { + LWIP_ASSERT("unsent segments leaking", pcb->unsent == NULL); + LWIP_ASSERT("unacked segments leaking", pcb->unacked == NULL); +#if TCP_QUEUE_OOSEQ + LWIP_ASSERT("ooseq segments leaking", pcb->ooseq == NULL); +#endif /* TCP_QUEUE_OOSEQ */ + } + pcb->state = CLOSED; LWIP_ASSERT("tcp_pcb_remove: tcp_pcbs_sane()", tcp_pcbs_sane()); diff --git a/src/core/tcp_in.c b/src/core/tcp_in.c index 1fcb10a6..7eb1435c 100644 --- a/src/core/tcp_in.c +++ b/src/core/tcp_in.c @@ -651,7 +651,7 @@ tcp_process(struct tcp_pcb *pcb) tcp_receive(pcb); if (flags & TCP_ACK && ackno == pcb->snd_nxt) { LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest)); - pcb->state = CLOSED; + /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */ recv_flags = TF_CLOSED; } break;