Do not call HttpDecoder::ProcessInput after error.
This CL changes API contract and call sites. Without the change to the call
sites, //gfe/gfe2/test_tools/fuzzing:gfe_quic_fuzzer would crash on the new
DCHECK_NE(QUIC_NO_ERROR, error_). This is because even if Visitor::OnError()
closes the connection, the sequencer might have more data that QuicSpdyStream is
eager to read and feed to HttpDecoder::ProcessInput().
Currently HttpDecoder::ProcessInput() ignores input upon error. However, I'm
going to modify the call sites to use PeekRegion() instead of
PrefetchNextRegion() and spin until decoding is paused by a visitor method or no
new region is there to peek at. Since HttpDecoder::ProcessInput() returns 0
if called after an error, this would just result in PeekRegion() being called
with the same offset, returning true, and the cycle spinning in an infinite
loop.
gfe-relnote: n/a, change to QUIC v99-only code path.
PiperOrigin-RevId: 255168809
Change-Id: I6b6f0b0986f2f6bec0a8eedb695dc91943d57bf2
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index 1bcbfaa..ffd5c74 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -45,10 +45,17 @@
HttpDecoder::~HttpDecoder() {}
QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
+ DCHECK_EQ(QUIC_NO_ERROR, error_);
+ DCHECK_NE(STATE_ERROR, state_);
+
QuicDataReader reader(data, len);
bool continue_processing = true;
- while (continue_processing && error_ == QUIC_NO_ERROR &&
+ while (continue_processing &&
(reader.BytesRemaining() != 0 || state_ == STATE_FINISH_PARSING)) {
+ // |continue_processing| must have been set to false upon error.
+ DCHECK_EQ(QUIC_NO_ERROR, error_);
+ DCHECK_NE(STATE_ERROR, state_);
+
switch (state_) {
case STATE_READING_FRAME_TYPE:
ReadFrameType(&reader);