lwip-devel
[Top][All Lists]
Advanced

[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/




reply via email to

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