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

Unified 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, 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 side-by-side diff with in-line comments
Download patch
Index: net/url_request/url_request_data_job_fuzzer.cc
diff --git a/net/url_request/url_request_data_job_fuzzer.cc b/net/url_request/url_request_data_job_fuzzer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..7ec6deac821d167c96aff0fc26ad7589d08cf8a0
--- /dev/null
+++ b/net/url_request/url_request_data_job_fuzzer.cc
@@ -0,0 +1,124 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "base/memory/singleton.h"
+#include "base/run_loop.h"
+#include "net/base/fuzzed_data_provider.h"
+#include "net/http/http_request_headers.h"
+#include "net/url_request/data_protocol_handler.h"
+#include "net/url_request/url_request_job_factory_impl.h"
+#include "net/url_request/url_request_test_util.h"
+
+namespace {
+
+// This function generates a random Range header value. It takes as input a
+// FuzzedDataProvider, which is used to pick random elements from |range_vals|.
+// This helps the fuzzer explore the set of possible range headers with "bytes="
+// easily.
+std::string GenerateRandomRange(net::FuzzedDataProvider* provider,
+ size_t max_size) {
+ std::vector<char> range_vals{'\0', '-', '0', '1', '2', '3', '4',
+ '5', '6', '7', '8', '9', ','};
+ std::string range = "bytes=";
+ for (size_t i = 0; i < max_size; i++) {
+ uint32_t index = provider->ConsumeValueInRange(0, range_vals.size() - 1);
+ if (range_vals[index] == '\0')
+ break;
+ range.push_back(range_vals[index]);
+ }
+ return range;
+}
+
+const size_t kMaxLengthForFuzzedData = 512;
+const size_t kMaxLengthForFuzzedRange = 16;
+
+} // namespace
+
+class URLRequestDataJobFuzzerHarness {
+ public:
+ URLRequestDataJobFuzzerHarness() : context_(true) {
+ job_factory_.SetProtocolHandler(
+ "data", base::WrapUnique(new net::DataProtocolHandler()));
+ context_.set_job_factory(&job_factory_);
+ context_.Init();
+ }
+
+ static URLRequestDataJobFuzzerHarness* GetInstance() {
+ return base::Singleton<URLRequestDataJobFuzzerHarness>::get();
+ }
+
+ // Tests creating and reading to completion a URLRequest with fuzzed input.
+ // The fuzzer provides a data: URL and optionally generates custom Range
+ // headers. The amount of data read in each Read call is also fuzzed, as is
+ // the size of the IOBuffer to read data into.
+ int CreateAndReadFromDataURLRequest(const uint8_t* data, size_t size) {
+ net::FuzzedDataProvider provider(data, size);
+
+ // Allocate an IOBuffer with fuzzed size.
+ uint32_t buf_size = provider.ConsumeBits(7u);
+ 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.
+
+ // Optionally generate a range header using the end of the fuzzed data.
+ // Early return if the header value is invalid.
+ std::string range = "";
+ bool use_range = provider.ConsumeBool();
+ if (use_range) {
+ range = GenerateRandomRange(&provider, kMaxLengthForFuzzedRange);
+ if (!net::HttpUtil::IsValidHeaderValue(range))
+ return 0;
+ }
+
+ // Generate a sequence of reads sufficient to read the entire data url.
+ size_t simulated_bytes_read = 0;
+ while (simulated_bytes_read < provider.remaining_bytes()) {
+ 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.
+ read_lengths_.push_back(read_length);
+ simulated_bytes_read += read_length;
+ }
+
+ // The data url is the rest of the fuzzed data.
+ size_t data_size =
+ provider.ConsumeBytes(data_bytes_, kMaxLengthForFuzzedData);
+ std::string data_string(data_bytes_, data_size);
+
+ // Create a URLRequest with the given data url and start reading
+ // from it.
+ std::unique_ptr<net::URLRequest> request = context_.CreateRequest(
+ 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
+ if (use_range)
+ request->SetExtraRequestHeaderByName("Range", range, true);
+
+ request->Start();
+ for (const size_t read_length : read_lengths_) {
+ 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
+ int bytes_read = 0;
+ request->Read(buf.get(), read_length, &bytes_read);
+ }
+
+ // Tear down.
+ 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
+ return 0;
+ }
+
+ private:
+ friend struct base::DefaultSingletonTraits<URLRequestDataJobFuzzerHarness>;
+
+ char data_bytes_[kMaxLengthForFuzzedData];
+ net::TestURLRequestContext context_;
+ net::URLRequestJobFactoryImpl job_factory_;
+ net::TestDelegate delegate_;
+ std::vector<size_t> read_lengths_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLRequestDataJobFuzzerHarness);
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ // Statically initialize most of the harness, per fuzzing efficiency best
+ // practices. Without these the test runs ~3-4x slower.
+ return URLRequestDataJobFuzzerHarness::GetInstance()
+ ->CreateAndReadFromDataURLRequest(data, size);
+}

Powered by Google App Engine
This is Rietveld 408576698