diff --git a/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc b/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc index df2960ad1..bf22acd07 100644 --- a/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc +++ b/quiche/http2/hpack/huffman/hpack_huffman_encoder.cc @@ -4,6 +4,8 @@ #include "quiche/http2/hpack/huffman/hpack_huffman_encoder.h" +#include +#include #include #include "quiche/http2/hpack/huffman/huffman_spec_tables.h" @@ -12,11 +14,20 @@ namespace http2 { size_t HuffmanSize(absl::string_view plain) { - size_t bits = 0; + // Accumulate in 64 bits regardless of size_t width: the longest code is 30 + // bits, so a ~143 MiB input overflows a 32-bit accumulator and would cause + // HuffmanEncode() to undersize its output buffer and write out of bounds. + uint64_t bits = 0; for (const uint8_t c : plain) { bits += HuffmanSpecTables::kCodeLengths[c]; } - return (bits + 7) / 8; + const uint64_t bytes = (bits + 7) / 8; + // Saturate on the (32-bit-only) edge where the byte count itself does not + // fit in size_t; callers treat a value >= plain.size() as "do not Huffman". + if (bytes > std::numeric_limits::max()) { + return std::numeric_limits::max(); + } + return static_cast(bytes); } void HuffmanEncode(absl::string_view input, size_t encoded_size,