From fe89d7c701fab29ae69d3765861d935a33cce76b Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 1 Mar 2026 07:41:38 -1000 Subject: [PATCH] [socket] Free rx_buf_ in LWIPRawImpl destructor The destructor relies solely on tcp_abort() for cleanup, but LWIP considers ownership of pbufs transferred once the recv callback accepts them. If rx_buf_ is non-null when the socket is destroyed, those pbufs are leaked. Free them explicitly before the base class destructor calls tcp_abort(). --- esphome/components/socket/lwip_raw_tcp_impl.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 402ce86fd7..e0e8fec756 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -319,6 +319,13 @@ int LWIPRawCommon::ip2sockaddr_(ip_addr_t *ip, uint16_t port, struct sockaddr *n // ---- LWIPRawImpl methods ---- LWIPRawImpl::~LWIPRawImpl() { + // Free any received pbufs that LWIP transferred ownership of via recv_fn. + // tcp_abort() in the base destructor won't free these since LWIP considers + // ownership transferred once the recv callback accepts them. + if (this->rx_buf_ != nullptr) { + pbuf_free(this->rx_buf_); + this->rx_buf_ = nullptr; + } // Base class destructor handles pcb_ cleanup via tcp_abort }