From f318b76a4cc994e24174d9fc5f824bcf67c9be0b Mon Sep 17 00:00:00 2001 From: Lin Date: Wed, 9 Sep 2026 01:37:02 +0800 Subject: [PATCH] net/spdy: propagate CONNECT response header conversion result OnHeadersReceived() discarded the SpdyHeadersToHttpResponse() result, so a conversion failure (e.g. multiple distinct location headers) left response_.headers unassigned for DoReadReplyComplete() to dereference. Propagate the result to OnIOComplete() so the existing "result < 0" short-circuit in DoReadReplyComplete() handles the failure with the actual error code. For proxy Fast Open, where Connect() has already completed early, only complete a pending application read and transition to STATE_DISCONNECTED on failure. --- src/net/spdy/spdy_proxy_client_socket.cc | 28 ++++++------------------ src/net/spdy/spdy_proxy_client_socket.h | 2 +- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/net/spdy/spdy_proxy_client_socket.cc b/src/net/spdy/spdy_proxy_client_socket.cc index 1c21ca0586..9ee770ee55 100644 --- a/src/net/spdy/spdy_proxy_client_socket.cc +++ b/src/net/spdy/spdy_proxy_client_socket.cc @@ -321,6 +321,11 @@ void SpdyProxyClientSocket::OnIOComplete(int result) { DCHECK_NE(STATE_DISCONNECTED, next_state_); int rv = DoLoop(result); if (rv != ERR_IO_PENDING) { + if (use_fastopen_ && read_headers_pending_ == false) { + if (rv < 0) + next_state_ = STATE_DISCONNECTED; + if (!read_callback_ || rv == OK) return; + } std::move(read_callback_).Run(rv); } } @@ -394,20 +399,6 @@ int SpdyProxyClientSocket::DoLoop(int last_io_result) { case STATE_PROCESS_RESPONSE_CODE: DCHECK_EQ(OK, rv); rv = DoProcessResponseCode(); - if (use_fastopen_ && read_headers_pending_) { - read_headers_pending_ = false; - if (rv < 0) { - // read_callback_ cannot be called. - if (!read_callback_) - rv = ERR_IO_PENDING; - // read_callback_ will be called with this error and be reset. - // Further data after that will be ignored. - next_state_ = STATE_DISCONNECTED; - } else { - // Does not call read_callback_ from here if headers are OK. - rv = ERR_IO_PENDING; - } - } break; default: NOTREACHED() << "bad state"; @@ -554,12 +545,6 @@ int SpdyProxyClientSocket::DoReadReplyComplete(int result) { if (result < 0) return result; - // SpdyHeadersToHttpResponse() may have failed to convert the response - // headers (e.g. duplicate location values), in which case - // response_.headers is null and must not be dereferenced. - if (!response_.headers) - return ERR_TUNNEL_CONNECTION_FAILED; - // Require the "HTTP/1.x" status line for SSL CONNECT. if (response_.headers->GetHttpVersion() < HttpVersion(1, 0)) return ERR_TUNNEL_CONNECTION_FAILED; @@ -639,6 +624,7 @@ void SpdyProxyClientSocket::OnEarlyHintsReceived( void SpdyProxyClientSocket::OnHeadersReceived( const quiche::HttpHeaderBlock& response_headers) { if (use_fastopen_ && read_headers_pending_ && next_state_ == STATE_OPEN) { + read_headers_pending_ = false; next_state_ = STATE_READ_REPLY_COMPLETE; } @@ -652,7 +638,7 @@ void SpdyProxyClientSocket::OnHeadersReceived( const int rv = SpdyHeadersToHttpResponse(response_headers, &response_); DCHECK_NE(rv, ERR_INCOMPLETE_HTTP2_HEADERS); - OnIOComplete(OK); + OnIOComplete(rv); } // Called when data is received or on EOF (if `buffer is nullptr). diff --git a/src/net/spdy/spdy_proxy_client_socket.h b/src/net/spdy/spdy_proxy_client_socket.h index cd3c408529..90ffed4274 100644 --- a/src/net/spdy/spdy_proxy_client_socket.h +++ b/src/net/spdy/spdy_proxy_client_socket.h @@ -202,7 +202,7 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket, bool use_fastopen_ = false; std::optional preamble_index_; - bool read_headers_pending_ = false; + std::optional read_headers_pending_; const NetLogWithSource net_log_; const NetLogSource source_dependency_;