diff options
| -rw-r--r-- | meta-oe/recipes-devtools/grpc/grpc/CVE-2024-7246.patch | 420 | ||||
| -rw-r--r-- | meta-oe/recipes-devtools/grpc/grpc_1.60.1.bb | 1 |
2 files changed, 421 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/grpc/grpc/CVE-2024-7246.patch b/meta-oe/recipes-devtools/grpc/grpc/CVE-2024-7246.patch new file mode 100644 index 0000000000..a690b49c67 --- /dev/null +++ b/meta-oe/recipes-devtools/grpc/grpc/CVE-2024-7246.patch | |||
| @@ -0,0 +1,420 @@ | |||
| 1 | From ac0948e39eb19c3325a576e152709d4cc915a7e4 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Craig Tiller <ctiller@google.com> | ||
| 3 | Date: Thu, 1 Aug 2024 13:02:27 -0700 | ||
| 4 | Subject: [PATCH] [v1.60] [chttp2] Fix a bug in hpack error handling (#37361) | ||
| 5 | |||
| 6 | PiperOrigin-RevId: 657234128 | ||
| 7 | PiperOrigin-RevId: 658458047 | ||
| 8 | |||
| 9 | Craig Tiller <ctiller@google.com> | ||
| 10 | |||
| 11 | CVE: CVE-2024-7246 | ||
| 12 | |||
| 13 | Upstream-Status: Backport | ||
| 14 | [https://github.com/grpc/grpc/pull/37361/files] | ||
| 15 | |||
| 16 | Signed-off-by: Libo Chen <libo.chen.cn@windriver.com> | ||
| 17 | --- | ||
| 18 | .../chttp2/transport/hpack_parser.cc | 63 +++++++------ | ||
| 19 | .../transport/chttp2/transport/hpack_parser.h | 2 + | ||
| 20 | .../transport/chttp2/hpack_parser_test.cc | 89 ++++++++++++++++--- | ||
| 21 | .../transport/chttp2/hpack_sync_fuzzer.cc | 62 +++++++++++++ | ||
| 22 | .../transport/chttp2/hpack_sync_fuzzer.proto | 3 + | ||
| 23 | 5 files changed, 179 insertions(+), 40 deletions(-) | ||
| 24 | |||
| 25 | diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc | ||
| 26 | index 31bf464..f2fe80c 100644 | ||
| 27 | --- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc | ||
| 28 | +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc | ||
| 29 | @@ -91,12 +91,14 @@ constexpr Base64InverseTable kBase64InverseTable; | ||
| 30 | class HPackParser::Input { | ||
| 31 | public: | ||
| 32 | Input(grpc_slice_refcount* current_slice_refcount, const uint8_t* begin, | ||
| 33 | - const uint8_t* end, absl::BitGenRef bitsrc, HpackParseResult& error) | ||
| 34 | + const uint8_t* end, absl::BitGenRef bitsrc, | ||
| 35 | + HpackParseResult& frame_error, HpackParseResult& field_error) | ||
| 36 | : current_slice_refcount_(current_slice_refcount), | ||
| 37 | begin_(begin), | ||
| 38 | end_(end), | ||
| 39 | frontier_(begin), | ||
| 40 | - error_(error), | ||
| 41 | + frame_error_(frame_error), | ||
| 42 | + field_error_(field_error), | ||
| 43 | bitsrc_(bitsrc) {} | ||
| 44 | |||
| 45 | // If input is backed by a slice, retrieve its refcount. If not, return | ||
| 46 | @@ -215,14 +217,18 @@ class HPackParser::Input { | ||
| 47 | |||
| 48 | // Check if we saw an EOF | ||
| 49 | bool eof_error() const { | ||
| 50 | - return min_progress_size_ != 0 || error_.connection_error(); | ||
| 51 | + return min_progress_size_ != 0 || frame_error_.connection_error(); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | + // Reset the field error to be ok | ||
| 55 | + void ClearFieldError() { | ||
| 56 | + if (field_error_.ok()) return; | ||
| 57 | + field_error_ = HpackParseResult(); | ||
| 58 | } | ||
| 59 | |||
| 60 | // Minimum number of bytes to unstuck the current parse | ||
| 61 | size_t min_progress_size() const { return min_progress_size_; } | ||
| 62 | |||
| 63 | - bool has_error() const { return !error_.ok(); } | ||
| 64 | - | ||
| 65 | // Set the current error - tweaks the error to include a stream id so that | ||
| 66 | // chttp2 does not close the connection. | ||
| 67 | // Intended for errors that are specific to a stream and recoverable. | ||
| 68 | @@ -246,10 +252,7 @@ class HPackParser::Input { | ||
| 69 | // read prior to being able to get further in this parse. | ||
| 70 | void UnexpectedEOF(size_t min_progress_size) { | ||
| 71 | GPR_ASSERT(min_progress_size > 0); | ||
| 72 | - if (min_progress_size_ != 0 || error_.connection_error()) { | ||
| 73 | - GPR_DEBUG_ASSERT(eof_error()); | ||
| 74 | - return; | ||
| 75 | - } | ||
| 76 | + if (eof_error()) return; | ||
| 77 | // Set min progress size, taking into account bytes parsed already but not | ||
| 78 | // consumed. | ||
| 79 | min_progress_size_ = min_progress_size + (begin_ - frontier_); | ||
| 80 | @@ -302,13 +305,18 @@ class HPackParser::Input { | ||
| 81 | // Do not use this directly, instead use SetErrorAndContinueParsing or | ||
| 82 | // SetErrorAndStopParsing. | ||
| 83 | void SetError(HpackParseResult error) { | ||
| 84 | - if (!error_.ok() || min_progress_size_ > 0) { | ||
| 85 | - if (error.connection_error() && !error_.connection_error()) { | ||
| 86 | - error_ = std::move(error); // connection errors dominate | ||
| 87 | + SetErrorFor(frame_error_, error); | ||
| 88 | + SetErrorFor(field_error_, std::move(error)); | ||
| 89 | + } | ||
| 90 | + | ||
| 91 | + void SetErrorFor(HpackParseResult& error, HpackParseResult new_error) { | ||
| 92 | + if (!error.ok() || min_progress_size_ > 0) { | ||
| 93 | + if (new_error.connection_error() && !error.connection_error()) { | ||
| 94 | + error = std::move(new_error); // connection errors dominate | ||
| 95 | } | ||
| 96 | return; | ||
| 97 | } | ||
| 98 | - error_ = std::move(error); | ||
| 99 | + error = std::move(new_error); | ||
| 100 | } | ||
| 101 | |||
| 102 | // Refcount if we are backed by a slice | ||
| 103 | @@ -320,7 +328,8 @@ class HPackParser::Input { | ||
| 104 | // Frontier denotes the first byte past successfully processed input | ||
| 105 | const uint8_t* frontier_; | ||
| 106 | // Current error | ||
| 107 | - HpackParseResult& error_; | ||
| 108 | + HpackParseResult& frame_error_; | ||
| 109 | + HpackParseResult& field_error_; | ||
| 110 | // If the error was EOF, we flag it here by noting how many more bytes would | ||
| 111 | // be needed to make progress | ||
| 112 | size_t min_progress_size_ = 0; | ||
| 113 | @@ -597,6 +606,7 @@ class HPackParser::Parser { | ||
| 114 | bool ParseTop() { | ||
| 115 | GPR_DEBUG_ASSERT(state_.parse_state == ParseState::kTop); | ||
| 116 | auto cur = *input_->Next(); | ||
| 117 | + input_->ClearFieldError(); | ||
| 118 | switch (cur >> 4) { | ||
| 119 | // Literal header not indexed - First byte format: 0000xxxx | ||
| 120 | // Literal header never indexed - First byte format: 0001xxxx | ||
| 121 | @@ -702,7 +712,7 @@ class HPackParser::Parser { | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | gpr_log( | ||
| 125 | - GPR_DEBUG, "HTTP:%d:%s:%s: %s%s", log_info_.stream_id, type, | ||
| 126 | + GPR_INFO, "HTTP:%d:%s:%s: %s%s", log_info_.stream_id, type, | ||
| 127 | log_info_.is_client ? "CLI" : "SVR", memento.md.DebugString().c_str(), | ||
| 128 | memento.parse_status == nullptr | ||
| 129 | ? "" | ||
| 130 | @@ -951,11 +961,10 @@ class HPackParser::Parser { | ||
| 131 | state_.string_length) | ||
| 132 | : String::Parse(input_, state_.is_string_huff_compressed, | ||
| 133 | state_.string_length); | ||
| 134 | - HpackParseResult& status = state_.frame_error; | ||
| 135 | absl::string_view key_string; | ||
| 136 | if (auto* s = absl::get_if<Slice>(&state_.key)) { | ||
| 137 | key_string = s->as_string_view(); | ||
| 138 | - if (status.ok()) { | ||
| 139 | + if (state_.field_error.ok()) { | ||
| 140 | auto r = ValidateKey(key_string); | ||
| 141 | if (r != ValidateMetadataResult::kOk) { | ||
| 142 | input_->SetErrorAndContinueParsing( | ||
| 143 | @@ -965,7 +974,7 @@ class HPackParser::Parser { | ||
| 144 | } else { | ||
| 145 | const auto* memento = absl::get<const HPackTable::Memento*>(state_.key); | ||
| 146 | key_string = memento->md.key(); | ||
| 147 | - if (status.ok() && memento->parse_status != nullptr) { | ||
| 148 | + if (state_.field_error.ok() && memento->parse_status != nullptr) { | ||
| 149 | input_->SetErrorAndContinueParsing(*memento->parse_status); | ||
| 150 | } | ||
| 151 | } | ||
| 152 | @@ -992,16 +1001,16 @@ class HPackParser::Parser { | ||
| 153 | key_string.size() + value.wire_size + hpack_constants::kEntryOverhead; | ||
| 154 | auto md = grpc_metadata_batch::Parse( | ||
| 155 | key_string, std::move(value_slice), state_.add_to_table, transport_size, | ||
| 156 | - [key_string, &status, this](absl::string_view message, const Slice&) { | ||
| 157 | - if (!status.ok()) return; | ||
| 158 | + [key_string, this](absl::string_view message, const Slice&) { | ||
| 159 | + if (!state_.field_error.ok()) return; | ||
| 160 | input_->SetErrorAndContinueParsing( | ||
| 161 | HpackParseResult::MetadataParseError(key_string)); | ||
| 162 | gpr_log(GPR_ERROR, "Error parsing '%s' metadata: %s", | ||
| 163 | std::string(key_string).c_str(), | ||
| 164 | std::string(message).c_str()); | ||
| 165 | }); | ||
| 166 | - HPackTable::Memento memento{std::move(md), | ||
| 167 | - status.PersistentStreamErrorOrNullptr()}; | ||
| 168 | + HPackTable::Memento memento{ | ||
| 169 | + std::move(md), state_.field_error.PersistentStreamErrorOrNullptr()}; | ||
| 170 | input_->UpdateFrontier(); | ||
| 171 | state_.parse_state = ParseState::kTop; | ||
| 172 | if (state_.add_to_table) { | ||
| 173 | @@ -1163,13 +1172,13 @@ grpc_error_handle HPackParser::Parse( | ||
| 174 | std::vector<uint8_t> buffer = std::move(unparsed_bytes_); | ||
| 175 | return ParseInput( | ||
| 176 | Input(nullptr, buffer.data(), buffer.data() + buffer.size(), bitsrc, | ||
| 177 | - state_.frame_error), | ||
| 178 | + state_.frame_error, state_.field_error), | ||
| 179 | is_last, call_tracer); | ||
| 180 | } | ||
| 181 | - return ParseInput( | ||
| 182 | - Input(slice.refcount, GRPC_SLICE_START_PTR(slice), | ||
| 183 | - GRPC_SLICE_END_PTR(slice), bitsrc, state_.frame_error), | ||
| 184 | - is_last, call_tracer); | ||
| 185 | + return ParseInput(Input(slice.refcount, GRPC_SLICE_START_PTR(slice), | ||
| 186 | + GRPC_SLICE_END_PTR(slice), bitsrc, state_.frame_error, | ||
| 187 | + state_.field_error), | ||
| 188 | + is_last, call_tracer); | ||
| 189 | } | ||
| 190 | |||
| 191 | grpc_error_handle HPackParser::ParseInput( | ||
| 192 | diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.h b/src/core/ext/transport/chttp2/transport/hpack_parser.h | ||
| 193 | index 3745668..55842e4 100644 | ||
| 194 | --- a/src/core/ext/transport/chttp2/transport/hpack_parser.h | ||
| 195 | +++ b/src/core/ext/transport/chttp2/transport/hpack_parser.h | ||
| 196 | @@ -236,6 +236,8 @@ class HPackParser { | ||
| 197 | HPackTable hpack_table; | ||
| 198 | // Error so far for this frame (set by class Input) | ||
| 199 | HpackParseResult frame_error; | ||
| 200 | + // Error so far for this field (set by class Input) | ||
| 201 | + HpackParseResult field_error; | ||
| 202 | // Length of frame so far. | ||
| 203 | uint32_t frame_length = 0; | ||
| 204 | // Length of the string being parsed | ||
| 205 | diff --git a/test/core/transport/chttp2/hpack_parser_test.cc b/test/core/transport/chttp2/hpack_parser_test.cc | ||
| 206 | index 3772d90..d5b9c6c 100644 | ||
| 207 | --- a/test/core/transport/chttp2/hpack_parser_test.cc | ||
| 208 | +++ b/test/core/transport/chttp2/hpack_parser_test.cc | ||
| 209 | @@ -440,19 +440,82 @@ INSTANTIATE_TEST_SUITE_P( | ||
| 210 | Test{"Base64LegalEncoding", | ||
| 211 | {}, | ||
| 212 | {}, | ||
| 213 | - {// Binary metadata: created using: | ||
| 214 | - // tools/codegen/core/gen_header_frame.py | ||
| 215 | - // --compression inc --no_framing --output hexstr | ||
| 216 | - // < test/core/transport/chttp2/bad-base64.headers | ||
| 217 | - {"4009612e622e632d62696e1c6c75636b696c7920666f722075732c206974" | ||
| 218 | - "27732074756573646179", | ||
| 219 | - absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 220 | - "illegal base64 encoding"), | ||
| 221 | - 0}, | ||
| 222 | - {"be", | ||
| 223 | - absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 224 | - "illegal base64 encoding"), | ||
| 225 | - 0}}}, | ||
| 226 | + { | ||
| 227 | + // Binary metadata: created using: | ||
| 228 | + // tools/codegen/core/gen_header_frame.py | ||
| 229 | + // --compression inc --no_framing --output hexstr | ||
| 230 | + // < test/core/transport/chttp2/bad-base64.headers | ||
| 231 | + {"4009612e622e632d62696e1c6c75636b696c7920666f722075732c206974" | ||
| 232 | + "27732074756573646179", | ||
| 233 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 234 | + "illegal base64 encoding"), | ||
| 235 | + 0}, | ||
| 236 | + {"be", | ||
| 237 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 238 | + "illegal base64 encoding"), | ||
| 239 | + kEndOfHeaders}, | ||
| 240 | + {"82", ":method: GET\n", 0}, | ||
| 241 | + }}, | ||
| 242 | + Test{"Base64LegalEncodingWorksAfterFailure", | ||
| 243 | + {}, | ||
| 244 | + {}, | ||
| 245 | + { | ||
| 246 | + // Binary metadata: created using: | ||
| 247 | + // tools/codegen/core/gen_header_frame.py | ||
| 248 | + // --compression inc --no_framing --output hexstr | ||
| 249 | + // < test/core/transport/chttp2/bad-base64.headers | ||
| 250 | + {"4009612e622e632d62696e1c6c75636b696c7920666f722075732c206974" | ||
| 251 | + "27732074756573646179", | ||
| 252 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 253 | + "illegal base64 encoding"), | ||
| 254 | + 0}, | ||
| 255 | + {"be", | ||
| 256 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 257 | + "illegal base64 encoding"), | ||
| 258 | + 0}, | ||
| 259 | + {"400e636f6e74656e742d6c656e6774680135", | ||
| 260 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 261 | + "illegal base64 encoding"), | ||
| 262 | + kEndOfHeaders}, | ||
| 263 | + {"be", "content-length: 5\n", 0}, | ||
| 264 | + }}, | ||
| 265 | + Test{"Base64LegalEncodingWorksAfterFailure2", | ||
| 266 | + {}, | ||
| 267 | + {}, | ||
| 268 | + { | ||
| 269 | + {// Generated with: tools/codegen/core/gen_header_frame.py | ||
| 270 | + // --compression inc --output hexstr --no_framing < | ||
| 271 | + // test/core/transport/chttp2/MiXeD-CaSe.headers | ||
| 272 | + "400a4d695865442d436153651073686f756c64206e6f74207061727365", | ||
| 273 | + absl::InternalError("Illegal header key: MiXeD-CaSe"), 0}, | ||
| 274 | + // Binary metadata: created using: | ||
| 275 | + // tools/codegen/core/gen_header_frame.py | ||
| 276 | + // --compression inc --no_framing --output hexstr | ||
| 277 | + // < test/core/transport/chttp2/bad-base64.headers | ||
| 278 | + {"4009612e622e632d62696e1c6c75636b696c7920666f722075732c206974" | ||
| 279 | + "27732074756573646179", | ||
| 280 | + absl::InternalError("Illegal header key: MiXeD-CaSe"), 0}, | ||
| 281 | + {"be", absl::InternalError("Illegal header key: MiXeD-CaSe"), | ||
| 282 | + 0}, | ||
| 283 | + {"400e636f6e74656e742d6c656e6774680135", | ||
| 284 | + absl::InternalError("Illegal header key: MiXeD-CaSe"), | ||
| 285 | + kEndOfHeaders}, | ||
| 286 | + {"be", "content-length: 5\n", 0}, | ||
| 287 | + {"bf", | ||
| 288 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 289 | + "illegal base64 encoding"), | ||
| 290 | + 0}, | ||
| 291 | + // Only the first error in each frame is reported, so we should | ||
| 292 | + // still see the same error here... | ||
| 293 | + {"c0", | ||
| 294 | + absl::InternalError("Error parsing 'a.b.c-bin' metadata: " | ||
| 295 | + "illegal base64 encoding"), | ||
| 296 | + kEndOfHeaders}, | ||
| 297 | + // ... but if we look at the next frame we should see the | ||
| 298 | + // stored error | ||
| 299 | + {"c0", absl::InternalError("Illegal header key: MiXeD-CaSe"), | ||
| 300 | + kEndOfHeaders}, | ||
| 301 | + }}, | ||
| 302 | Test{"TeIsTrailers", | ||
| 303 | {}, | ||
| 304 | {}, | ||
| 305 | diff --git a/test/core/transport/chttp2/hpack_sync_fuzzer.cc b/test/core/transport/chttp2/hpack_sync_fuzzer.cc | ||
| 306 | index 47e4265..9afa41f 100644 | ||
| 307 | --- a/test/core/transport/chttp2/hpack_sync_fuzzer.cc | ||
| 308 | +++ b/test/core/transport/chttp2/hpack_sync_fuzzer.cc | ||
| 309 | @@ -85,6 +85,10 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) { | ||
| 310 | // Not an interesting case to fuzz | ||
| 311 | continue; | ||
| 312 | } | ||
| 313 | + if (msg.check_ab_preservation() && | ||
| 314 | + header.literal_inc_idx().key() == "a") { | ||
| 315 | + continue; | ||
| 316 | + } | ||
| 317 | if (absl::EndsWith(header.literal_inc_idx().value(), "-bin")) { | ||
| 318 | std::ignore = encoder.EmitLitHdrWithBinaryStringKeyIncIdx( | ||
| 319 | Slice::FromCopiedString(header.literal_inc_idx().key()), | ||
| 320 | @@ -96,6 +100,10 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) { | ||
| 321 | } | ||
| 322 | break; | ||
| 323 | case hpack_sync_fuzzer::Header::kLiteralNotIdx: | ||
| 324 | + if (msg.check_ab_preservation() && | ||
| 325 | + header.literal_not_idx().key() == "a") { | ||
| 326 | + continue; | ||
| 327 | + } | ||
| 328 | if (absl::EndsWith(header.literal_not_idx().value(), "-bin")) { | ||
| 329 | encoder.EmitLitHdrWithBinaryStringKeyNotIdx( | ||
| 330 | Slice::FromCopiedString(header.literal_not_idx().key()), | ||
| 331 | @@ -114,6 +122,10 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) { | ||
| 332 | break; | ||
| 333 | } | ||
| 334 | } | ||
| 335 | + if (msg.check_ab_preservation()) { | ||
| 336 | + std::ignore = encoder.EmitLitHdrWithNonBinaryStringKeyIncIdx( | ||
| 337 | + Slice::FromCopiedString("a"), Slice::FromCopiedString("b")); | ||
| 338 | + } | ||
| 339 | |||
| 340 | // STAGE 2: Decode the buffer (encode_output) into a list of headers | ||
| 341 | HPackParser parser; | ||
| 342 | @@ -140,6 +152,21 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) { | ||
| 343 | } | ||
| 344 | } | ||
| 345 | |||
| 346 | + if (seen_errors.empty() && msg.check_ab_preservation()) { | ||
| 347 | + std::string backing; | ||
| 348 | + auto a_value = read_metadata.GetStringValue("a", &backing); | ||
| 349 | + if (!a_value.has_value()) { | ||
| 350 | + fprintf(stderr, "Expected 'a' header to be present: %s\n", | ||
| 351 | + read_metadata.DebugString().c_str()); | ||
| 352 | + abort(); | ||
| 353 | + } | ||
| 354 | + if (a_value != "b") { | ||
| 355 | + fprintf(stderr, "Expected 'a' header to be 'b', got '%s'\n", | ||
| 356 | + std::string(*a_value).c_str()); | ||
| 357 | + abort(); | ||
| 358 | + } | ||
| 359 | + } | ||
| 360 | + | ||
| 361 | // STAGE 3: If we reached here we either had a stream error or no error | ||
| 362 | // parsing. | ||
| 363 | // Either way, the hpack tables should be of the same size between client and | ||
| 364 | @@ -168,6 +195,41 @@ void FuzzOneInput(const hpack_sync_fuzzer::Msg& msg) { | ||
| 365 | } | ||
| 366 | abort(); | ||
| 367 | } | ||
| 368 | + | ||
| 369 | + if (msg.check_ab_preservation()) { | ||
| 370 | + SliceBuffer encode_output_2; | ||
| 371 | + hpack_encoder_detail::Encoder encoder_2( | ||
| 372 | + &compressor, msg.use_true_binary_metadata(), encode_output_2); | ||
| 373 | + encoder_2.EmitIndexed(62); | ||
| 374 | + GPR_ASSERT(encode_output_2.Count() == 1); | ||
| 375 | + grpc_metadata_batch read_metadata_2(arena.get()); | ||
| 376 | + parser.BeginFrame( | ||
| 377 | + &read_metadata_2, 1024, 1024, HPackParser::Boundary::EndOfHeaders, | ||
| 378 | + HPackParser::Priority::None, | ||
| 379 | + HPackParser::LogInfo{3, HPackParser::LogInfo::kHeaders, false}); | ||
| 380 | + auto err = parser.Parse(encode_output_2.c_slice_at(0), true, | ||
| 381 | + absl::BitGenRef(proto_bit_src), | ||
| 382 | + /*call_tracer=*/nullptr); | ||
| 383 | + if (!err.ok()) { | ||
| 384 | + fprintf(stderr, "Error parsing preservation encoded data: %s\n", | ||
| 385 | + err.ToString().c_str()); | ||
| 386 | + abort(); | ||
| 387 | + } | ||
| 388 | + std::string backing; | ||
| 389 | + auto a_value = read_metadata_2.GetStringValue("a", &backing); | ||
| 390 | + if (!a_value.has_value()) { | ||
| 391 | + fprintf(stderr, | ||
| 392 | + "Expected 'a' header to be present: %s\nfirst metadata: %s\n", | ||
| 393 | + read_metadata_2.DebugString().c_str(), | ||
| 394 | + read_metadata.DebugString().c_str()); | ||
| 395 | + abort(); | ||
| 396 | + } | ||
| 397 | + if (a_value != "b") { | ||
| 398 | + fprintf(stderr, "Expected 'a' header to be 'b', got '%s'\n", | ||
| 399 | + std::string(*a_value).c_str()); | ||
| 400 | + abort(); | ||
| 401 | + } | ||
| 402 | + } | ||
| 403 | } | ||
| 404 | |||
| 405 | } // namespace | ||
| 406 | diff --git a/test/core/transport/chttp2/hpack_sync_fuzzer.proto b/test/core/transport/chttp2/hpack_sync_fuzzer.proto | ||
| 407 | index 72792b6..2c075a6 100644 | ||
| 408 | --- a/test/core/transport/chttp2/hpack_sync_fuzzer.proto | ||
| 409 | +++ b/test/core/transport/chttp2/hpack_sync_fuzzer.proto | ||
| 410 | @@ -44,4 +44,7 @@ message Msg { | ||
| 411 | repeated Header headers = 2; | ||
| 412 | grpc.testing.FuzzConfigVars config_vars = 3; | ||
| 413 | repeated uint64 random_numbers = 4; | ||
| 414 | + // Ensure that a header "a: b" appended to headers with hpack incremental | ||
| 415 | + // indexing is correctly added to the hpack table. | ||
| 416 | + bool check_ab_preservation = 5; | ||
| 417 | } | ||
| 418 | -- | ||
| 419 | 2.44.1 | ||
| 420 | |||
diff --git a/meta-oe/recipes-devtools/grpc/grpc_1.60.1.bb b/meta-oe/recipes-devtools/grpc/grpc_1.60.1.bb index 63c696a623..4557fcc908 100644 --- a/meta-oe/recipes-devtools/grpc/grpc_1.60.1.bb +++ b/meta-oe/recipes-devtools/grpc/grpc_1.60.1.bb | |||
| @@ -24,6 +24,7 @@ SRCREV_grpc = "e5ae3b6b44bf3b64d24bfb4b4f82556239b986db" | |||
| 24 | BRANCH = "v1.60.x" | 24 | BRANCH = "v1.60.x" |
| 25 | SRC_URI = "gitsm://github.com/grpc/grpc.git;protocol=https;name=grpc;branch=${BRANCH} \ | 25 | SRC_URI = "gitsm://github.com/grpc/grpc.git;protocol=https;name=grpc;branch=${BRANCH} \ |
| 26 | file://0001-cmake-Link-with-libatomic-on-rv32-rv64.patch \ | 26 | file://0001-cmake-Link-with-libatomic-on-rv32-rv64.patch \ |
| 27 | file://CVE-2024-7246.patch \ | ||
| 27 | " | 28 | " |
| 28 | # Fixes build with older compilers 4.8 especially on ubuntu 14.04 | 29 | # Fixes build with older compilers 4.8 especially on ubuntu 14.04 |
| 29 | CXXFLAGS:append:class-native = " -Wl,--no-as-needed" | 30 | CXXFLAGS:append:class-native = " -Wl,--no-as-needed" |
