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