xref: /aosp_15_r20/external/cronet/net/spdy/spdy_headers_to_http_response_headers_fuzzer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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)27 extern "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