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

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: Encapsulated logic in a singleton class. Rebased / updated for FuzzedDataProvider. Created 4 years, 8 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 <algorithm>
Charlie Harrison 2016/04/26 12:58:40 Remove <algorithm>
6 #include <memory>
7
8 #include "base/memory/ptr_util.h"
9 #include "base/memory/singleton.h"
10 #include "base/run_loop.h"
11 #include "net/base/fuzzed_data_provider.h"
12 #include "net/http/http_request_headers.h"
13 #include "net/url_request/data_protocol_handler.h"
14 #include "net/url_request/url_request_job_factory_impl.h"
15 #include "net/url_request/url_request_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace {
19
20 // This function generates a random Range header value. It takes as input a
21 // random byte stream, where each element is used as a random index into the
22 // |range_vals| array.
Charlie Harrison 2016/04/26 12:58:40 Update comment.
23 std::string GenerateRandomRange(net::FuzzedDataProvider* provider,
24 size_t max_size) {
25 std::vector<char> range_vals{'\0', '-', '0', '1', '2', '3', '4',
26 '5', '6', '7', '8', '9', ','};
27 std::string range = "bytes=";
28 for (size_t i = 0; i < max_size; i++) {
29 uint32_t index = provider->ConsumeValueInRange(0, range_vals.size() - 1);
30 if (range_vals[index] == '\0')
31 break;
32 range.push_back(range_vals[index]);
33 }
34 return range;
35 }
36
37 const size_t kMaxLengthForFuzzedData = 256;
38 const size_t kMaxLengthForFuzzedRange = 16;
39
40 } // namespace
41
42 class URLRequestDataJobFuzzerHarness {
43 public:
44 URLRequestDataJobFuzzerHarness() : context_(true) {
45 job_factory_.SetProtocolHandler(
46 "data", base::WrapUnique(new net::DataProtocolHandler()));
47 context_.set_job_factory(&job_factory_);
48 context_.Init();
49 }
50
51 static URLRequestDataJobFuzzerHarness* GetInstance() {
52 return base::Singleton<URLRequestDataJobFuzzerHarness>::get();
53 }
54
55 // Tests creating and reading to completion a URLRequest with fuzzed input.
56 // The fuzzer provides a data: URL and generates custom Range headers. The
57 // amount of data read in each Read call is also fuzzed.
Charlie Harrison 2016/04/26 12:58:40 Include that the IOBuffer size is fuzzed, and we r
58 // The structure of the data that the fuzzer generates looks like:
59 // |-- data url --|-- read metadata --|-- range header --|
Charlie Harrison 2016/04/26 12:58:40 This line is unclear because we now fuzz IOBuffer
60 int CreateAndReadFromDataURLRequest(const uint8_t* data, size_t size) {
61 net::FuzzedDataProvider provider(data, size);
62 uint32_t buf_size = provider.ConsumeBits(7u);
63 scoped_refptr<net::IOBuffer> buf(new net::IOBuffer((size_t)buf_size));
64
65 // Generate a range header using the end of the fuzzed data. Early return if
66 // 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);
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 = provider.ConsumeRemainingBytes(data_bytes_);
85 std::string data_string(data_bytes_, data_size);
86
87 // Create a URLRequest with the given data url and start reading
88 // from it.
89 std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
90 GURL("data:" + data_string), net::DEFAULT_PRIORITY, &delegate_);
91 if (use_range)
92 request->SetExtraRequestHeaderByName("Range", range, true);
93
94 request->Start();
95 for (const size_t read_length : read_lengths_) {
96 base::RunLoop().RunUntilIdle();
97 int bytes_read = 0;
98 request->Read(buf.get(), read_length, &bytes_read);
99 }
100
101 // Tear down.
102 read_lengths_.clear();
103 return 0;
104 }
105
106 private:
107 friend struct base::DefaultSingletonTraits<URLRequestDataJobFuzzerHarness>;
108
109 char data_bytes_[kMaxLengthForFuzzedData];
110 net::TestURLRequestContext context_;
111 net::URLRequestJobFactoryImpl job_factory_;
112 net::TestDelegate delegate_;
113 std::vector<size_t> read_lengths_;
114
115 DISALLOW_COPY_AND_ASSIGN(URLRequestDataJobFuzzerHarness);
116 };
117
118 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
119 // Statically initialize most of the harness, per fuzzing efficiency best
120 // practices. Without these the test runs ~3-4x slower.
121 return URLRequestDataJobFuzzerHarness::GetInstance()
122 ->CreateAndReadFromDataURLRequest(data, size);
123 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698