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.
pull/827/head
Lin 2026-09-09 01:37:02 +08:00
parent a5fe135a76
commit f318b76a4c
2 changed files with 8 additions and 22 deletions

View File

@ -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).

View File

@ -202,7 +202,7 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
bool use_fastopen_ = false;
std::optional<size_t> preamble_index_;
bool read_headers_pending_ = false;
std::optional<bool> read_headers_pending_;
const NetLogWithSource net_log_;
const NetLogSource source_dependency_;