Plumb error code from HpackDecoder to HpackDecoderAdapter, add two error codes that are detected in HpackDecoderAdapter.
gfe-relnote: n/a (no functional change)
PiperOrigin-RevId: 293813721
Change-Id: I3ea4a72daab3e676a131ff8c05e18fa3d0b86d6e
diff --git a/http2/hpack/decoder/hpack_decoding_error.cc b/http2/hpack/decoder/hpack_decoding_error.cc
index 56eec6c..3e231b5 100644
--- a/http2/hpack/decoder/hpack_decoding_error.cc
+++ b/http2/hpack/decoder/hpack_decoding_error.cc
@@ -40,6 +40,10 @@
return "Dynamic table size update is above acknowledged setting";
case HpackDecodingError::kTruncatedBlock:
return "Block ends in the middle of an instruction";
+ case HpackDecodingError::kFragmentTooLong:
+ return "Incoming data fragment exceeds buffer limit";
+ case HpackDecodingError::kCompressedHeaderSizeExceedsLimit:
+ return "Total compressed HPACK data size exceeds limit";
}
return "invalid HpackDecodingError value";
}
diff --git a/http2/hpack/decoder/hpack_decoding_error.h b/http2/hpack/decoder/hpack_decoding_error.h
index 98df064..e346549 100644
--- a/http2/hpack/decoder/hpack_decoding_error.h
+++ b/http2/hpack/decoder/hpack_decoding_error.h
@@ -37,6 +37,10 @@
kDynamicTableSizeUpdateIsAboveAcknowledgedSetting,
// HPACK block ends in the middle of an instruction.
kTruncatedBlock,
+ // Incoming data fragment exceeds buffer limit.
+ kFragmentTooLong,
+ // Total compressed HPACK data size exceeds limit.
+ kCompressedHeaderSizeExceedsLimit,
};
QUICHE_EXPORT_PRIVATE quiche::QuicheStringPiece HpackDecodingErrorToString(
diff --git a/spdy/core/hpack/hpack_decoder_adapter.cc b/spdy/core/hpack/hpack_decoder_adapter.cc
index fe9577d..8a4e17a 100644
--- a/spdy/core/hpack/hpack_decoder_adapter.cc
+++ b/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -22,7 +22,8 @@
: hpack_decoder_(&listener_adapter_, kMaxDecodeBufferSizeBytes),
max_decode_buffer_size_bytes_(kMaxDecodeBufferSizeBytes),
max_header_block_bytes_(0),
- header_block_started_(false) {}
+ header_block_started_(false),
+ error_(http2::HpackDecodingError::kOk) {}
HpackDecoderAdapter::~HpackDecoderAdapter() = default;
@@ -50,6 +51,7 @@
if (!hpack_decoder_.StartDecodingBlock()) {
header_block_started_ = false;
SPDY_CODE_COUNT_N(decompress_failure_2, 1, 5);
+ error_ = hpack_decoder_.error();
return false;
}
}
@@ -64,12 +66,14 @@
<< max_decode_buffer_size_bytes_ << " < "
<< headers_data_length;
SPDY_CODE_COUNT_N(decompress_failure_2, 2, 5);
+ error_ = http2::HpackDecodingError::kFragmentTooLong;
return false;
}
listener_adapter_.AddToTotalHpackBytes(headers_data_length);
if (max_header_block_bytes_ != 0 &&
listener_adapter_.total_hpack_bytes() > max_header_block_bytes_) {
SPDY_CODE_COUNT_N(decompress_failure, 3, 5);
+ error_ = http2::HpackDecodingError::kCompressedHeaderSizeExceedsLimit;
return false;
}
http2::DecodeBuffer db(headers_data, headers_data_length);
@@ -77,6 +81,7 @@
DCHECK(!ok || db.Empty()) << "Remaining=" << db.Remaining();
if (!ok) {
SPDY_CODE_COUNT_N(decompress_failure_2, 4, 5);
+ error_ = hpack_decoder_.error();
}
return ok;
}
@@ -92,6 +97,7 @@
if (!hpack_decoder_.EndDecodingBlock()) {
SPDY_DVLOG(3) << "EndDecodingBlock returned false";
SPDY_CODE_COUNT_N(decompress_failure_2, 5, 5);
+ error_ = hpack_decoder_.error();
return false;
}
header_block_started_ = false;
diff --git a/spdy/core/hpack/hpack_decoder_adapter.h b/spdy/core/hpack/hpack_decoder_adapter.h
index 429d3b1..3ff3b4b 100644
--- a/spdy/core/hpack/hpack_decoder_adapter.h
+++ b/spdy/core/hpack/hpack_decoder_adapter.h
@@ -85,6 +85,9 @@
size_t EstimateMemoryUsage() const;
+ // Error code if an error has occurred, Error::kOk otherwise.
+ http2::HpackDecodingError error() const { return error_; }
+
private:
class QUICHE_EXPORT_PRIVATE ListenerAdapter
: public http2::HpackDecoderListener,
@@ -158,6 +161,9 @@
// moment because HandleControlFrameHeadersStart won't be called if a handler
// is not being provided by the caller.
bool header_block_started_;
+
+ // Error code if an error has occurred, Error::kOk otherwise.
+ http2::HpackDecodingError error_;
};
} // namespace spdy