xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/http2/hpack/decoder/hpack_whole_entry_buffer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/http2/hpack/decoder/hpack_whole_entry_buffer.h"
6 
7 #include "absl/strings/str_cat.h"
8 #include "quiche/common/platform/api/quiche_flag_utils.h"
9 #include "quiche/common/platform/api/quiche_logging.h"
10 #include "quiche/common/quiche_text_utils.h"
11 
12 namespace http2 {
13 
HpackWholeEntryBuffer(HpackWholeEntryListener * listener,size_t max_string_size_bytes)14 HpackWholeEntryBuffer::HpackWholeEntryBuffer(HpackWholeEntryListener* listener,
15                                              size_t max_string_size_bytes)
16     : max_string_size_bytes_(max_string_size_bytes) {
17   set_listener(listener);
18 }
19 HpackWholeEntryBuffer::~HpackWholeEntryBuffer() = default;
20 
set_listener(HpackWholeEntryListener * listener)21 void HpackWholeEntryBuffer::set_listener(HpackWholeEntryListener* listener) {
22   QUICHE_CHECK(listener);
23   listener_ = listener;
24 }
25 
set_max_string_size_bytes(size_t max_string_size_bytes)26 void HpackWholeEntryBuffer::set_max_string_size_bytes(
27     size_t max_string_size_bytes) {
28   max_string_size_bytes_ = max_string_size_bytes;
29 }
30 
BufferStringsIfUnbuffered()31 void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() {
32   name_.BufferStringIfUnbuffered();
33   value_.BufferStringIfUnbuffered();
34 }
35 
OnIndexedHeader(size_t index)36 void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) {
37   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index;
38   listener_->OnIndexedHeader(index);
39 }
40 
OnStartLiteralHeader(HpackEntryType entry_type,size_t maybe_name_index)41 void HpackWholeEntryBuffer::OnStartLiteralHeader(HpackEntryType entry_type,
42                                                  size_t maybe_name_index) {
43   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnStartLiteralHeader: entry_type="
44                   << entry_type << ",  maybe_name_index=" << maybe_name_index;
45   entry_type_ = entry_type;
46   maybe_name_index_ = maybe_name_index;
47 }
48 
OnNameStart(bool huffman_encoded,size_t len)49 void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) {
50   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnNameStart: huffman_encoded="
51                   << (huffman_encoded ? "true" : "false") << ",  len=" << len;
52   QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
53   if (!error_detected_) {
54     if (len > max_string_size_bytes_) {
55       QUICHE_DVLOG(1) << "Name length (" << len
56                       << ") is longer than permitted ("
57                       << max_string_size_bytes_ << ")";
58       ReportError(HpackDecodingError::kNameTooLong);
59       QUICHE_CODE_COUNT_N(decompress_failure_3, 18, 23);
60       return;
61     }
62     name_.OnStart(huffman_encoded, len);
63   }
64 }
65 
OnNameData(const char * data,size_t len)66 void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) {
67   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len
68                   << " data:\n"
69                   << quiche::QuicheTextUtils::HexDump(
70                          absl::string_view(data, len));
71   QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
72   if (!error_detected_ && !name_.OnData(data, len)) {
73     ReportError(HpackDecodingError::kNameHuffmanError);
74     QUICHE_CODE_COUNT_N(decompress_failure_3, 19, 23);
75   }
76 }
77 
OnNameEnd()78 void HpackWholeEntryBuffer::OnNameEnd() {
79   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnNameEnd";
80   QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
81   if (!error_detected_ && !name_.OnEnd()) {
82     ReportError(HpackDecodingError::kNameHuffmanError);
83     QUICHE_CODE_COUNT_N(decompress_failure_3, 20, 23);
84   }
85 }
86 
OnValueStart(bool huffman_encoded,size_t len)87 void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) {
88   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnValueStart: huffman_encoded="
89                   << (huffman_encoded ? "true" : "false") << ",  len=" << len;
90   if (!error_detected_) {
91     if (len > max_string_size_bytes_) {
92       QUICHE_DVLOG(1) << "Value length (" << len << ") of ["
93                       << name_.GetStringIfComplete()
94                       << "] is longer than permitted ("
95                       << max_string_size_bytes_ << ")";
96 
97       ReportError(HpackDecodingError::kValueTooLong);
98       QUICHE_CODE_COUNT_N(decompress_failure_3, 21, 23);
99       return;
100     }
101     value_.OnStart(huffman_encoded, len);
102   }
103 }
104 
OnValueData(const char * data,size_t len)105 void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) {
106   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len
107                   << " data:\n"
108                   << quiche::QuicheTextUtils::HexDump(
109                          absl::string_view(data, len));
110   if (!error_detected_ && !value_.OnData(data, len)) {
111     ReportError(HpackDecodingError::kValueHuffmanError);
112     QUICHE_CODE_COUNT_N(decompress_failure_3, 22, 23);
113   }
114 }
115 
OnValueEnd()116 void HpackWholeEntryBuffer::OnValueEnd() {
117   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnValueEnd";
118   if (error_detected_) {
119     return;
120   }
121   if (!value_.OnEnd()) {
122     ReportError(HpackDecodingError::kValueHuffmanError);
123     QUICHE_CODE_COUNT_N(decompress_failure_3, 23, 23);
124     return;
125   }
126   if (maybe_name_index_ == 0) {
127     listener_->OnLiteralNameAndValue(entry_type_, &name_, &value_);
128     name_.Reset();
129   } else {
130     listener_->OnNameIndexAndLiteralValue(entry_type_, maybe_name_index_,
131                                           &value_);
132   }
133   value_.Reset();
134 }
135 
OnDynamicTableSizeUpdate(size_t size)136 void HpackWholeEntryBuffer::OnDynamicTableSizeUpdate(size_t size) {
137   QUICHE_DVLOG(2) << "HpackWholeEntryBuffer::OnDynamicTableSizeUpdate: size="
138                   << size;
139   listener_->OnDynamicTableSizeUpdate(size);
140 }
141 
ReportError(HpackDecodingError error)142 void HpackWholeEntryBuffer::ReportError(HpackDecodingError error) {
143   if (!error_detected_) {
144     QUICHE_DVLOG(1) << "HpackWholeEntryBuffer::ReportError: "
145                     << HpackDecodingErrorToString(error);
146     error_detected_ = true;
147     listener_->OnHpackDecodeError(error);
148     listener_ = HpackWholeEntryNoOpListener::NoOpListener();
149   }
150 }
151 
152 }  // namespace http2
153