//tcp_appcode.c 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; } //tcp_in.c //当tcp_input()接收到同时包含PSH+ACK标志的TCP报文,那么将会执行以下流程: 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) { ... // 到这里,大概率是recv_data==p,并且inseg.p==NULL。 TCP_EVENT_SENT(pcb, (u16_t)acked16, err); /* 回调app_cb_sent() */ // 只要在app_cb_sent()中执行下面其中一种逻辑,即可触发pbuf泄露: // [1] call tcp_close() and return ERR_OK, // [2] call tcp_abort() and return ERR_ABRT. if (err == ERR_ABRT) { // 此时如果(recv_data != NULL)那么p泄露。 goto aborted; // ERROR POINT (1) } ... } if (tcp_input_delayed_close(pcb)) { // 此时如果(recv_data != NULL)那么p泄露。 goto aborted; // ERROR POINT (2) } ... } } aborted: tcp_input_pcb = NULL; recv_data = NULL; if (inseg.p != NULL) { pbuf_free(inseg.p); inseg.p = NULL; } } ... }