[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-devel] [bug #61666] A memory leak BUG in function tcp_input().
From: |
xuyao hong |
Subject: |
[lwip-devel] [bug #61666] A memory leak BUG in function tcp_input(). |
Date: |
Mon, 13 Dec 2021 07:40:06 -0500 (EST) |
User-agent: |
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.93 Safari/537.36 Edg/96.0.1054.53 |
Follow-up Comment #4, bug #61666 (project lwip):
If TCP application code like this, very similar to httpd example:
static err_t app_cb_accept(void* arg, struct tcp_pcb* pcb, err_t err)
{
...
tcp_sent(pcb, app_cb_sent);
...
}
static err_t app_cb_sent(void* arg, struct tcp_pcb* pcb, u16_t len)
{
...
tcp_close(pcb);
...
return ERR_OK;
}
Now, if tcp_input(struct pbuf *p) received a packet has PSH+ACK flags, the
flow like below:
tcp_input(struct pbuf *p)
{
if (pcb != NULL) {
...
inseg.p = p;
recv_data = NULL;
recv_acked = 0;
...
tcp_process(pcb);
if (err != ERR_ABRT) {
if (recv_flags & TF_RESET) {
...
} else {
...
if (recv_acked > 0) {
...
// here, recv_data mybe p,and inseg.p is NULL.
TCP_EVENT_SENT(pcb, (u16_t)acked16, err); /* call app_cb_sent() */
// if in function app_cb_sent() do any thing like below:
// [1] call tcp_close() and return ERR_OK,
// [2] call tcp_abort() and return ERR_ABRT.
if (err == ERR_ABRT) {
// need to free recv_data if (recv_data != NULL)
goto aborted; // ERROR POINT (1)
}
...
}
if (tcp_input_delayed_close(pcb)) {
// need to free recv_data if (recv_data != NULL)
goto aborted; // ERROR POINT (2)
}
...
}
}
aborted:
tcp_input_pcb = NULL;
recv_data = NULL;
if (inseg.p != NULL) {
pbuf_free(inseg.p);
inseg.p = NULL;
}
}
...
}
My final solution:
tcp_input(struct pbuf *p)
{
...
if (recv_acked > 0) {
u16_t acked16;
#if LWIP_WND_SCALE
/* recv_acked is u32_t but the sent callback only takes a u16_t,
so we might have to call it multiple times. */
u32_t acked = recv_acked;
while (acked > 0) {
acked16 = (u16_t)LWIP_MIN(acked, 0xffffu);
acked -= acked16;
#else
{
acked16 = recv_acked;
#endif
TCP_EVENT_SENT(pcb, (u16_t)acked16, err);
if (err == ERR_ABRT) {
// need to free recv_data if (recv_data != NULL)
if (recv_data != NULL) {
pbuf_free(recv_data);
}
goto aborted;
}
}
recv_acked = 0;
}
if (tcp_input_delayed_close(pcb)) {
// need to free recv_data if (recv_data != NULL)
if (recv_data != NULL) {
pbuf_free(recv_data);
}
goto aborted;
}
...
}
_______________________________________________________
Reply to this item at:
<https://savannah.nongnu.org/bugs/?61666>
_______________________________________________
Message sent via Savannah
https://savannah.nongnu.org/