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

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: 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 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..2fd245ffe00c5f6f8885452a5fe8fdd11c46b59f
--- /dev/null
+++ b/net/url_request/url_request_data_job_fuzzer.cc
@@ -0,0 +1,123 @@
+// 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 <algorithm>
Charlie Harrison 2016/04/26 12:58:40 Remove <algorithm>
+#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"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// This function generates a random Range header value. It takes as input a
+// random byte stream, where each element is used as a random index into the
+// |range_vals| array.
Charlie Harrison 2016/04/26 12:58:40 Update comment.
+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 = 256;
+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 generates custom Range headers. The
+ // 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
+ // The structure of the data that the fuzzer generates looks like:
+ // |-- data url --|-- read metadata --|-- range header --|
Charlie Harrison 2016/04/26 12:58:40 This line is unclear because we now fuzz IOBuffer
+ int CreateAndReadFromDataURLRequest(const uint8_t* data, size_t size) {
+ net::FuzzedDataProvider provider(data, size);
+ uint32_t buf_size = provider.ConsumeBits(7u);
+ scoped_refptr<net::IOBuffer> buf(new net::IOBuffer((size_t)buf_size));
+
+ // 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);
+ 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.ConsumeRemainingBytes(data_bytes_);
+ 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_);
+ if (use_range)
+ request->SetExtraRequestHeaderByName("Range", range, true);
+
+ request->Start();
+ for (const size_t read_length : read_lengths_) {
+ base::RunLoop().RunUntilIdle();
+ int bytes_read = 0;
+ request->Read(buf.get(), read_length, &bytes_read);
+ }
+
+ // Tear down.
+ read_lengths_.clear();
+ 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