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 <string_view> 15 16 #include "base/check.h" 17 #include "base/check_op.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/types/expected.h" 20 #include "net/http/http_response_headers.h" 21 #include "net/http/http_util.h" 22 #include "net/spdy/spdy_http_utils.h" 23 #include "net/third_party/quiche/src/quiche/spdy/core/http2_header_block.h" 24 25 namespace net { 26 LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)27extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 28 std::string_view rest(reinterpret_cast<const char*>(data), size); 29 // We split the input at "\n" to force the fuzzer to produce a corpus that is 30 // human-readable. "\n" cannot appear in a valid header name or value so this 31 // is safe. 32 auto get_string = [&rest]() { 33 size_t newline_pos = rest.find('\n'); 34 if (newline_pos == std::string_view::npos) { 35 newline_pos = rest.size(); 36 } 37 std::string_view first_line = rest.substr(0, newline_pos); 38 if (newline_pos + 1 < rest.size()) { 39 rest = rest.substr(newline_pos + 1); 40 } else { 41 rest = std::string_view(); 42 } 43 return first_line; 44 }; 45 spdy::Http2HeaderBlock input; 46 47 const std::string_view status = get_string(); 48 if (!HttpUtil::IsValidHeaderValue(status)) { 49 return 0; 50 } 51 input[":status"] = status; 52 while (!rest.empty()) { 53 const std::string_view name = get_string(); 54 if (!HttpUtil::IsValidHeaderName(name)) { 55 return 0; 56 } 57 const std::string_view value = get_string(); 58 if (!HttpUtil::IsValidHeaderValue(value)) { 59 return 0; 60 } 61 input.AppendValueOrAddHeader(name, value); 62 } 63 const auto by_builder = SpdyHeadersToHttpResponseHeadersUsingBuilder(input); 64 const auto by_raw_string = 65 SpdyHeadersToHttpResponseHeadersUsingRawString(input); 66 if (by_builder.has_value()) { 67 CHECK(by_builder.value()->StrictlyEquals(*by_raw_string.value())); 68 } else { 69 CHECK(!by_raw_string.has_value()); 70 CHECK_EQ(by_builder.error(), by_raw_string.error()); 71 } 72 return 0; 73 } 74 75 } // namespace net 76