1 // Copyright 2023 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Fuzzer for SpdyHeaderstoHttpResponseHeadersUsingBuilder. Compares the output 6 // for the same input to SpdyHeadersToHttpResponseHeadersUsingRawString and 7 // verifies they match. 8 9 // TODO(ricea): Remove this when SpdyHeadersToHttpResponseHeadersUsingRawString 10 // is removed. 11 12 #include <stddef.h> 13 14 #include "base/check.h" 15 #include "base/check_op.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/strings/string_piece.h" 18 #include "base/types/expected.h" 19 #include "net/http/http_response_headers.h" 20 #include "net/http/http_util.h" 21 #include "net/spdy/spdy_http_utils.h" 22 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" 23 24 namespace net { 25 LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)26extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 27 base::StringPiece rest(reinterpret_cast<const char*>(data), size); 28 // We split the input at "\n" to force the fuzzer to produce a corpus that is 29 // human-readable. "\n" cannot appear in a valid header name or value so this 30 // is safe. 31 auto get_string = [&rest]() { 32 size_t newline_pos = rest.find('\n'); 33 if (newline_pos == base::StringPiece::npos) { 34 newline_pos = rest.size(); 35 } 36 base::StringPiece first_line = rest.substr(0, newline_pos); 37 if (newline_pos + 1 < rest.size()) { 38 rest = rest.substr(newline_pos + 1); 39 } else { 40 rest = base::StringPiece(); 41 } 42 return first_line; 43 }; 44 spdy::Http2HeaderBlock input; 45 46 const base::StringPiece status = get_string(); 47 if (!HttpUtil::IsValidHeaderValue(status)) { 48 return 0; 49 } 50 input[":status"] = status; 51 while (!rest.empty()) { 52 const base::StringPiece name = get_string(); 53 if (!HttpUtil::IsValidHeaderName(name)) { 54 return 0; 55 } 56 const base::StringPiece value = get_string(); 57 if (!HttpUtil::IsValidHeaderValue(value)) { 58 return 0; 59 } 60 input.AppendValueOrAddHeader(name, value); 61 } 62 const auto by_builder = SpdyHeadersToHttpResponseHeadersUsingBuilder(input); 63 const auto by_raw_string = 64 SpdyHeadersToHttpResponseHeadersUsingRawString(input); 65 if (by_builder.has_value()) { 66 CHECK(by_builder.value()->StrictlyEquals(*by_raw_string.value())); 67 } else { 68 CHECK(!by_raw_string.has_value()); 69 CHECK_EQ(by_builder.error(), by_raw_string.error()); 70 } 71 return 0; 72 } 73 74 } // namespace net 75