From bc1c501a4219f0d4da289152db27dd9acdcc7456 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E5=AD=99=E6=98=A5=E9=98=B3?= Date: Tue, 6 Jan 2026 18:31:57 +0800 Subject: [PATCH] =?utf8?q?=E4=BC=98=E5=8C=96lwip=20tcp=E5=8F=91=E9=80=81?= =?utf8?q?=EF=BC=8C=E9=99=8D=E4=BD=8E=E6=97=A0=E7=BD=91=E7=BB=9C=E5=8F=91?= =?utf8?q?=E9=80=81=E4=BD=A0=E6=95=B0=E6=8D=AE=E9=80=A0=E6=88=90=E7=9A=84?= =?utf8?q?=E6=AD=BB=E6=9C=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .../lwip/lwip_v2.1.3/src/api/api_msg.c | 78 ++++++++++++++----- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/code/sdk/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/api/api_msg.c b/code/sdk/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/api/api_msg.c index 8bef06c78..6f7216ccd 100644 --- a/code/sdk/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/api/api_msg.c +++ b/code/sdk/open_source/openharmony/third_party/lwip/lwip_v2.1.3/src/api/api_msg.c @@ -364,7 +364,7 @@ poll_tcp(void *arg, struct tcp_pcb *pcb) /* Fundamental fix: Check if connection is still valid before processing any state. * If pcb is NULL, it means err_tcp was called and the connection is closed. * This can happen if poll_tcp was scheduled before err_tcp but executed after. */ - if (conn->pcb.tcp == NULL) { + if (conn->pcb.tcp == NULL || conn->state == NETCONN_NONE) { /* Connection was closed by err_tcp. Nothing to do. */ return ERR_OK; } @@ -372,7 +372,8 @@ poll_tcp(void *arg, struct tcp_pcb *pcb) if (conn->state == NETCONN_WRITE) { /* Only proceed if current_msg is valid. If it's NULL, the write operation * was already completed or aborted, but state wasn't reset yet. */ - if (conn->current_msg != NULL) { + /* Re-check state and current_msg before calling lwip_netconn_do_writemore */ + if (conn->current_msg != NULL && conn->state == NETCONN_WRITE && conn->pcb.tcp != NULL) { lwip_netconn_do_writemore(conn WRITE_DELAYED); } } else if (conn->state == NETCONN_CLOSE) { @@ -434,7 +435,8 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len) if (conn->state == NETCONN_WRITE) { /* Only proceed if current_msg is valid. If it's NULL, the write operation * was already completed or aborted, but state wasn't reset yet. */ - if (conn->current_msg != NULL) { + /* Re-check state and current_msg before calling lwip_netconn_do_writemore */ + if (conn->current_msg != NULL && conn->state == NETCONN_WRITE && conn->pcb.tcp != NULL) { lwip_netconn_do_writemore(conn WRITE_DELAYED); } } else if (conn->state == NETCONN_CLOSE) { @@ -1737,26 +1739,45 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) return ERR_CONN; } + /* Re-check before accessing current_msg members (err_tcp may have cleared it) */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + return ERR_CONN; + } + LWIP_ASSERT("conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len", conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len); LWIP_ASSERT("conn->current_msg->msg.w.vector_cnt > 0", conn->current_msg->msg.w.vector_cnt > 0); + /* Save apiflags immediately after check to minimize race window */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + return ERR_CONN; + } apiflags = conn->current_msg->msg.w.apiflags; dontblock = netconn_is_nonblocking(conn) || (apiflags & NETCONN_DONTBLOCK); #if LWIP_SO_SNDTIMEO /* Re-check current_msg validity before accessing timeout fields */ - if (conn->current_msg != NULL && (conn->send_timeout != 0) && - ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { - write_finished = 1; - if (conn->current_msg->msg.w.offset == 0) { - /* nothing has been written */ - err = ERR_WOULDBLOCK; - } else { - /* partial write */ - err = ERR_OK; + if (conn->current_msg != NULL && conn->state == NETCONN_WRITE && (conn->send_timeout != 0)) { + /* Re-check again before accessing time_started (err_tcp may have cleared current_msg) */ + if (conn->current_msg != NULL && conn->state == NETCONN_WRITE && + ((s32_t)(sys_now() - conn->current_msg->msg.w.time_started) >= conn->send_timeout)) { + write_finished = 1; + /* Re-check before accessing offset */ + if (conn->current_msg != NULL && conn->state == NETCONN_WRITE) { + if (conn->current_msg->msg.w.offset == 0) { + /* nothing has been written */ + err = ERR_WOULDBLOCK; + } else { + /* partial write */ + err = ERR_OK; + } + } else { + err = ERR_CONN; + write_finished = 1; + } } - } else + } + if (!write_finished) #endif /* LWIP_SO_SNDTIMEO */ { do { @@ -1806,7 +1827,7 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) } } /* Re-check current_msg and vector validity before accessing them */ - if (conn->current_msg == NULL || conn->current_msg->msg.w.vector == NULL) { + if (conn->current_msg == NULL || conn->current_msg->msg.w.vector == NULL || conn->state != NETCONN_WRITE) { err = ERR_CONN; write_finished = 1; break; @@ -1817,6 +1838,12 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) 1) We couldn't finish the current vector because of 16-bit size limitations. tcp_write() and tcp_sndbuf() both are limited to 16-bit sizes 2) We are sending the remainder of the current vector and have more */ + /* Re-check before accessing vector_cnt */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + err = ERR_CONN; + write_finished = 1; + break; + } if ((len == 0xffff && diff > 0xffffUL) || (len == (u16_t)diff && conn->current_msg->msg.w.vector_cnt > 1)) { write_more = 1; @@ -1833,7 +1860,7 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) err = tcp_write(conn->pcb.tcp, dataptr, len, apiflags); if (err == ERR_OK) { /* Re-check current_msg validity after tcp_write (err_tcp may have been called) */ - if (conn->current_msg == NULL) { + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { err = ERR_CONN; write_finished = 1; break; @@ -1842,15 +1869,27 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) conn->current_msg->msg.w.vector_off += len; /* check if current vector is finished */ /* Re-check current_msg and vector validity before accessing vector->len */ - if (conn->current_msg == NULL || conn->current_msg->msg.w.vector == NULL) { + if (conn->current_msg == NULL || conn->current_msg->msg.w.vector == NULL || conn->state != NETCONN_WRITE) { err = ERR_CONN; write_finished = 1; break; } if (conn->current_msg->msg.w.vector_off == conn->current_msg->msg.w.vector->len) { + /* Re-check before modifying vector_cnt (err_tcp may have cleared current_msg) */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + err = ERR_CONN; + write_finished = 1; + break; + } conn->current_msg->msg.w.vector_cnt--; /* if we have additional vectors, move on to them */ if (conn->current_msg->msg.w.vector_cnt > 0) { + /* Re-check before modifying vector pointer (err_tcp may have cleared current_msg) */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + err = ERR_CONN; + write_finished = 1; + break; + } conn->current_msg->msg.w.vector++; conn->current_msg->msg.w.vector_off = 0; } @@ -1861,8 +1900,11 @@ lwip_netconn_do_writemore(struct netconn *conn WRITE_DELAYED_PARAM) if ((err == ERR_OK) || (err == ERR_MEM)) { err_mem: /* Re-check validity before accessing current_msg and pcb */ - if (conn->current_msg != NULL && conn->pcb.tcp != NULL) { - if (dontblock && (conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len)) { + if (conn->current_msg != NULL && conn->pcb.tcp != NULL && conn->state == NETCONN_WRITE) { + /* Re-check again before accessing current_msg members */ + if (conn->current_msg == NULL || conn->state != NETCONN_WRITE) { + /* Skip this block if current_msg was cleared */ + } else if (dontblock && (conn->current_msg->msg.w.offset < conn->current_msg->msg.w.len)) { /* non-blocking write did not write everything: mark the pcb non-writable and let poll_tcp check writable space to mark the pcb writable again */ API_EVENT(conn, NETCONN_EVT_SENDMINUS, 0); -- 2.17.1