Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(318)

Side by Side Diff: net/url_request/url_request_data_job_fuzzer.cc

Issue 1919013003: Add fuzzer to test Fuzz URLRequestDataJob (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@url_request_fuzzer
Patch Set: self review Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <memory>
6
7 #include "base/memory/ptr_util.h"
8 #include "base/memory/singleton.h"
9 #include "base/run_loop.h"
10 #include "net/base/fuzzed_data_provider.h"
11 #include "net/http/http_request_headers.h"
12 #include "net/url_request/data_protocol_handler.h"
13 #include "net/url_request/url_request_job_factory_impl.h"
14 #include "net/url_request/url_request_test_util.h"
15
16 namespace {
17
18 // This function generates a random Range header value. It takes as input a
19 // FuzzedDataProvider, which is used to pick random elements from |range_vals|.
20 // This helps the fuzzer explore the set of possible range headers with "bytes="
21 // easily.
22 std::string GenerateRandomRange(net::FuzzedDataProvider* provider,
23 size_t max_size) {
24 std::vector<char> range_vals{'\0', '-', '0', '1', '2', '3', '4',
25 '5', '6', '7', '8', '9', ','};
26 std::string range = "bytes=";
27 for (size_t i = 0; i < max_size; i++) {
28 uint32_t index = provider->ConsumeValueInRange(0, range_vals.size() - 1);
29 if (range_vals[index] == '\0')
30 break;
31 range.push_back(range_vals[index]);
32 }
33 return range;
34 }
35
36 const size_t kMaxLengthForFuzzedData = 512;
37 const size_t kMaxLengthForFuzzedRange = 16;
38
39 } // namespace
40
41 class URLRequestDataJobFuzzerHarness {
42 public:
43 URLRequestDataJobFuzzerHarness() : context_(true) {
44 job_factory_.SetProtocolHandler(
45 "data", base::WrapUnique(new net::DataProtocolHandler()));
46 context_.set_job_factory(&job_factory_);
47 context_.Init();
48 }
49
50 static URLRequestDataJobFuzzerHarness* GetInstance() {
51 return base::Singleton<URLRequestDataJobFuzzerHarness>::get();
52 }
53
54 // Tests creating and reading to completion a URLRequest with fuzzed input.
55 // The fuzzer provides a data: URL and optionally generates custom Range
56 // headers. The amount of data read in each Read call is also fuzzed, as is
57 // the size of the IOBuffer to read data into.
58 int CreateAndReadFromDataURLRequest(const uint8_t* data, size_t size) {
59 net::FuzzedDataProvider provider(data, size);
60
61 // Allocate an IOBuffer with fuzzed size.
62 uint32_t buf_size = provider.ConsumeBits(7u);
63 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer((size_t)buf_size));
eroman 2016/04/27 00:43:01 static_cast<size_t>(buf_size).
Charlie Harrison 2016/04/27 17:39:54 Done.
64
65 // Optionally generate a range header using the end of the fuzzed data.
66 // Early return if the header value is invalid.
67 std::string range = "";
68 bool use_range = provider.ConsumeBool();
69 if (use_range) {
70 range = GenerateRandomRange(&provider, kMaxLengthForFuzzedRange);
71 if (!net::HttpUtil::IsValidHeaderValue(range))
72 return 0;
73 }
74
75 // Generate a sequence of reads sufficient to read the entire data url.
76 size_t simulated_bytes_read = 0;
77 while (simulated_bytes_read < provider.remaining_bytes()) {
78 size_t read_length = provider.ConsumeValueInRange(0, 32);
eroman 2016/04/27 00:43:01 I wonder if a read length of 0 make sense. Maybe u
Charlie Harrison 2016/04/27 17:39:54 Done.
79 read_lengths_.push_back(read_length);
80 simulated_bytes_read += read_length;
81 }
82
83 // The data url is the rest of the fuzzed data.
84 size_t data_size =
85 provider.ConsumeBytes(data_bytes_, kMaxLengthForFuzzedData);
86 std::string data_string(data_bytes_, data_size);
87
88 // Create a URLRequest with the given data url and start reading
89 // from it.
90 std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
91 GURL("data:" + data_string), net::DEFAULT_PRIORITY, &delegate_);
eroman 2016/04/27 00:43:01 What happens in the case of invalid GURLs? i.e. GU
Charlie Harrison 2016/04/27 17:39:54 I early returned if the url wasn't valid. Not sure
92 if (use_range)
93 request->SetExtraRequestHeaderByName("Range", range, true);
94
95 request->Start();
96 for (const size_t read_length : read_lengths_) {
97 base::RunLoop().RunUntilIdle();
eroman 2016/04/27 00:43:01 This is making some assumptions about how the code
Charlie Harrison 2016/04/27 17:39:54 Done. I made this class a URLRequest::Delegate to
98 int bytes_read = 0;
99 request->Read(buf.get(), read_length, &bytes_read);
100 }
101
102 // Tear down.
103 read_lengths_.clear();
eroman 2016/04/27 00:43:01 I would actually put this at the start of the func
Charlie Harrison 2016/04/27 17:39:55 Moved it to the top, as it is now referenced in va
104 return 0;
105 }
106
107 private:
108 friend struct base::DefaultSingletonTraits<URLRequestDataJobFuzzerHarness>;
109
110 char data_bytes_[kMaxLengthForFuzzedData];
111 net::TestURLRequestContext context_;
112 net::URLRequestJobFactoryImpl job_factory_;
113 net::TestDelegate delegate_;
114 std::vector<size_t> read_lengths_;
115
116 DISALLOW_COPY_AND_ASSIGN(URLRequestDataJobFuzzerHarness);
117 };
118
119 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
120 // Statically initialize most of the harness, per fuzzing efficiency best
121 // practices. Without these the test runs ~3-4x slower.
122 return URLRequestDataJobFuzzerHarness::GetInstance()
123 ->CreateAndReadFromDataURLRequest(data, size);
124 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698