Fix use-after-free of TLS session in WebSocketClient::shutdown_and_close()

shutdown_and_close() freed the TLS session before ws_->close() sent the
WebSocket close frame. The WebSocket's SSLSocketStream keeps a raw pointer
to that session, so sending the close frame then read/wrote a freed SSL
object. Reorder so ws_->close()/ws_.reset() run while the session is still
alive, then free the session (GHSA-w7p7-f35j-mw7q).
This commit is contained in:
yhirose committed 2026-07-11 21:20:36 -04:00
1 parent ed97a6edba
commit 2f986fd5e5
2 files changed
+63 -2

No files matched your search

+5 -2
View File
@@ -20539,6 +20539,11 @@ inline WebSocketClient::~WebSocketClient() {
inline bool WebSocketClient::is_valid() const { return is_valid_; }
inline void WebSocketClient::shutdown_and_close() {
// Send the close frame while the TLS session is still alive: ws_ holds an
// SSLSocketStream that keeps a raw pointer to tls_session_, so the session
// must outlive ws_->close() and ws_.reset() to avoid a use-after-free.
if (ws_ && ws_->is_open()) { ws_->close(); }
ws_.reset();
#ifdef CPPHTTPLIB_SSL_ENABLED
if (is_ssl_) {
if (tls_session_) {
@@ -20548,8 +20553,6 @@ inline void WebSocketClient::shutdown_and_close() {
}
}
#endif
if (ws_ && ws_->is_open()) { ws_->close(); }
ws_.reset();
if (sock_ != INVALID_SOCKET) {
detail::shutdown_socket(sock_);
detail::close_socket(sock_);