[socket] Fix pre-existing bugs found during socket devirtualization review (#14404)

This commit is contained in:
J. Nick Koston
2026-03-02 08:54:54 -10:00
committed by GitHub
parent b9b1af1c3d
commit 2fa244715d
3 changed files with 21 additions and 4 deletions

View File

@@ -83,7 +83,7 @@ class BSDSocketImpl {
return ::write(this->fd_, buf, len);
#endif
}
ssize_t send(void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); }
ssize_t send(const void *buf, size_t len, int flags) { return ::send(this->fd_, buf, len, flags); }
ssize_t writev(const struct iovec *iov, int iovcnt) {
#if defined(USE_ESP32)
return ::lwip_writev(this->fd_, iov, iovcnt);

View File

@@ -68,7 +68,7 @@ int LWIPRawCommon::bind(const struct sockaddr *name, socklen_t addrlen) {
}
if (name == nullptr) {
errno = EINVAL;
return 0;
return -1;
}
ip_addr_t ip;
in_port_t port;
@@ -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
}
@@ -545,7 +552,14 @@ ssize_t LWIPRawImpl::writev(const struct iovec *iov, int iovcnt) {
// ---- LWIPRawListenImpl methods ----
LWIPRawListenImpl::~LWIPRawListenImpl() {
// Base class destructor handles pcb_ cleanup via tcp_abort
// Listen PCBs must use tcp_close(), not tcp_abort().
// tcp_abandon() asserts pcb->state != LISTEN and would access
// fields that don't exist in the smaller tcp_pcb_listen struct.
// Close here and null pcb_ so the base destructor skips tcp_abort.
if (this->pcb_ != nullptr) {
tcp_close(this->pcb_);
this->pcb_ = nullptr;
}
}
void LWIPRawListenImpl::init() {
@@ -609,6 +623,9 @@ int LWIPRawListenImpl::listen(int backlog) {
LWIP_LOG("tcp_arg(%p)", this->pcb_);
tcp_arg(this->pcb_, this);
tcp_accept(this->pcb_, LWIPRawListenImpl::s_accept_fn);
// Note: tcp_err() is NOT re-registered here. tcp_listen_with_backlog() converts the
// full tcp_pcb to a smaller tcp_pcb_listen struct that lacks the errf field.
// Calling tcp_err() on a listen PCB writes past the struct boundary (undefined behavior).
return 0;
}

View File

@@ -57,7 +57,7 @@ class LwIPSocketImpl {
}
ssize_t readv(const struct iovec *iov, int iovcnt) { return lwip_readv(this->fd_, iov, iovcnt); }
ssize_t write(const void *buf, size_t len) { return lwip_write(this->fd_, buf, len); }
ssize_t send(void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); }
ssize_t send(const void *buf, size_t len, int flags) { return lwip_send(this->fd_, buf, len, flags); }
ssize_t writev(const struct iovec *iov, int iovcnt) { return lwip_writev(this->fd_, iov, iovcnt); }
ssize_t sendto(const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
return lwip_sendto(this->fd_, buf, len, flags, to, tolen);