• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)26 extern "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