From 99db244124eee806240afe78dc396d9ffa82a5e0 Mon Sep 17 00:00:00 2001 From: goldsimon Date: Mon, 14 Jul 2008 20:12:36 +0000 Subject: [PATCH] fixed bug #23847: do_close_internal references freed memory --- CHANGELOG | 4 ++++ src/api/api_msg.c | 21 +++++++++++++++------ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index c953f3f0..a8f1c43a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,10 @@ HISTORY ++ Bugfixes: + 2008-08-14 Simon Goldschmidt + * api_msg.c: fixed bug #23847: do_close_internal references freed memory (when + tcp_close returns != ERR_OK) + 2008-07-08 Frédéric Bernon * stats.h: Fix some build bugs introduced with patch #6483 (missing some parameters in macros, mainly if MEM_STATS=0 and MEMP_STATS=0). diff --git a/src/api/api_msg.c b/src/api/api_msg.c index 04646a54..7cc8a8e2 100644 --- a/src/api/api_msg.c +++ b/src/api/api_msg.c @@ -598,11 +598,17 @@ do_close_internal(struct netconn *conn) LWIP_ASSERT("pcb already closed", (conn->pcb.tcp != NULL)); /* Set back some callback pointers */ + tcp_arg(conn->pcb.tcp, NULL); if (conn->pcb.tcp->state == LISTEN) { - tcp_arg(conn->pcb.tcp, NULL); tcp_accept(conn->pcb.tcp, NULL); } else { tcp_recv(conn->pcb.tcp, NULL); + tcp_connect(conn->pcb.tcp, NULL); + tcp_accept(conn->pcb.tcp, NULL); + /* some callbacks have to be reset if tcp_close is not successful */ + tcp_sent(conn->pcb.tcp, NULL); + tcp_poll(conn->pcb.tcp, NULL, 4); + tcp_err(conn->pcb.tcp, NULL); } /* Try to close the connection */ err = tcp_close(conn->pcb.tcp); @@ -610,11 +616,6 @@ do_close_internal(struct netconn *conn) /* Closing succeeded */ conn->state = NETCONN_NONE; /* Set back some callback pointers as conn is going away */ - tcp_err(conn->pcb.tcp, NULL); - tcp_poll(conn->pcb.tcp, NULL, 4); - tcp_sent(conn->pcb.tcp, NULL); - tcp_recv(conn->pcb.tcp, NULL); - tcp_arg(conn->pcb.tcp, NULL); conn->pcb.tcp = NULL; conn->err = ERR_OK; /* Trigger select() in socket layer. This send should something else so the @@ -623,6 +624,14 @@ do_close_internal(struct netconn *conn) API_EVENT(conn, NETCONN_EVT_SENDPLUS, 0); /* wake up the application task */ sys_sem_signal(conn->op_completed); + } else { + /* Closing failed, restore some of the callbacks */ + /* Closing of listen pcb will never fail! */ + LWIP_ASSERT("Closing a listen pcb may not fail!", (conn->pcb.tcp->state != LISTEN)); + tcp_sent(conn->pcb.tcp, sent_tcp); + tcp_poll(conn->pcb.tcp, poll_tcp, 4); + tcp_err(conn->pcb.tcp, err_tcp); + tcp_arg(conn->pcb.tcp, conn); } /* If closing didn't succeed, we get called again either from poll_tcp or from sent_tcp */