summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHidehiko Abe <hidehiko@google.com>2019-03-27 19:19:14 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-03-27 19:19:14 -0700
commit55967eb9834b29331829f8b18af55e3b970dd237 (patch)
tree57467c96bf26dd2c2188411804e99248deb63337
parentd43323de5c5f15193e483d605b18d5568cd76080 (diff)
parent8935bdd250765c2b49cf355211647eac719a18cb (diff)
downloadlibchrome-55967eb9834b29331829f8b18af55e3b970dd237.tar.gz
libchrome: import fuzzed_data_provider for Chrome OS. am: e40d01b28a
am: 8935bdd250 Change-Id: I4a1b6256b6bd451dcafec94d32b67a171460f7a3
-rw-r--r--base/test/fuzzed_data_provider.cc98
-rw-r--r--base/test/fuzzed_data_provider.h80
2 files changed, 178 insertions, 0 deletions
diff --git a/base/test/fuzzed_data_provider.cc b/base/test/fuzzed_data_provider.cc
new file mode 100644
index 0000000000..b2d443a9b9
--- /dev/null
+++ b/base/test/fuzzed_data_provider.cc
@@ -0,0 +1,98 @@
+// 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 "base/test/fuzzed_data_provider.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/logging.h"
+
+namespace base {
+
+FuzzedDataProvider::FuzzedDataProvider(const uint8_t* data, size_t size)
+ : remaining_data_(reinterpret_cast<const char*>(data), size) {}
+
+FuzzedDataProvider::~FuzzedDataProvider() = default;
+
+std::string FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
+ num_bytes = std::min(num_bytes, remaining_data_.length());
+ StringPiece result(remaining_data_.data(), num_bytes);
+ remaining_data_ = remaining_data_.substr(num_bytes);
+ return result.as_string();
+}
+
+std::string FuzzedDataProvider::ConsumeRemainingBytes() {
+ return ConsumeBytes(remaining_data_.length());
+}
+
+uint32_t FuzzedDataProvider::ConsumeUint32InRange(uint32_t min, uint32_t max) {
+ CHECK_LE(min, max);
+
+ uint32_t range = max - min;
+ uint32_t offset = 0;
+ uint32_t result = 0;
+
+ while (offset < 32 && (range >> offset) > 0 && !remaining_data_.empty()) {
+ // Pull bytes off the end of the seed data. Experimentally, this seems to
+ // allow the fuzzer to more easily explore the input space. This makes
+ // sense, since it works by modifying inputs that caused new code to run,
+ // and this data is often used to encode length of data read by
+ // ConsumeBytes. Separating out read lengths makes it easier modify the
+ // contents of the data that is actually read.
+ uint8_t next_byte = remaining_data_.back();
+ remaining_data_.remove_suffix(1);
+ result = (result << 8) | next_byte;
+ offset += 8;
+ }
+
+ // Avoid division by 0, in the case |range + 1| results in overflow.
+ if (range == std::numeric_limits<uint32_t>::max())
+ return result;
+
+ return min + result % (range + 1);
+}
+
+std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
+ // Reads bytes from start of |remaining_data_|. Maps "\\" to "\", and maps "\"
+ // followed by anything else to the end of the string. As a result of this
+ // logic, a fuzzer can insert characters into the string, and the string will
+ // be lengthened to include those new characters, resulting in a more stable
+ // fuzzer than picking the length of a string independently from picking its
+ // contents.
+ std::string out;
+ for (size_t i = 0; i < max_length && !remaining_data_.empty(); ++i) {
+ char next = remaining_data_[0];
+ remaining_data_.remove_prefix(1);
+ if (next == '\\' && !remaining_data_.empty()) {
+ next = remaining_data_[0];
+ remaining_data_.remove_prefix(1);
+ if (next != '\\')
+ return out;
+ }
+ out += next;
+ }
+ return out;
+}
+
+int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) {
+ CHECK_LE(min, max);
+
+ uint32_t range = max - min;
+ return min + ConsumeUint32InRange(0, range);
+}
+
+bool FuzzedDataProvider::ConsumeBool() {
+ return (ConsumeUint8() & 0x01) == 0x01;
+}
+
+uint8_t FuzzedDataProvider::ConsumeUint8() {
+ return ConsumeUint32InRange(0, 0xFF);
+}
+
+uint16_t FuzzedDataProvider::ConsumeUint16() {
+ return ConsumeUint32InRange(0, 0xFFFF);
+}
+
+} // namespace base
diff --git a/base/test/fuzzed_data_provider.h b/base/test/fuzzed_data_provider.h
new file mode 100644
index 0000000000..425c820a21
--- /dev/null
+++ b/base/test/fuzzed_data_provider.h
@@ -0,0 +1,80 @@
+// 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.
+
+#ifndef BASE_TEST_FUZZED_DATA_PROVIDER_H_
+#define BASE_TEST_FUZZED_DATA_PROVIDER_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "base/base_export.h"
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+
+namespace base {
+
+// Utility class to break up fuzzer input for multiple consumers. Whenever run
+// on the same input, provides the same output, as long as its methods are
+// called in the same order, with the same arguments.
+class FuzzedDataProvider {
+ public:
+ // |data| is an array of length |size| that the FuzzedDataProvider wraps to
+ // provide more granular access. |data| must outlive the FuzzedDataProvider.
+ FuzzedDataProvider(const uint8_t* data, size_t size);
+ ~FuzzedDataProvider();
+
+ // Returns a std::string containing |num_bytes| of input data. If fewer than
+ // |num_bytes| of data remain, returns a shorter std::string containing all
+ // of the data that's left.
+ std::string ConsumeBytes(size_t num_bytes);
+
+ // Returns a std::string containing all remaining bytes of the input data.
+ std::string ConsumeRemainingBytes();
+
+ // Returns a std::string of length from 0 to |max_length|. When it runs out of
+ // input data, returns what remains of the input. Designed to be more stable
+ // with respect to a fuzzer inserting characters than just picking a random
+ // length and then consuming that many bytes with ConsumeBytes().
+ std::string ConsumeRandomLengthString(size_t max_length);
+
+ // Returns a number in the range [min, max] by consuming bytes from the input
+ // data. The value might not be uniformly distributed in the given range. If
+ // there's no input data left, always returns |min|. |min| must be less than
+ // or equal to |max|.
+ uint32_t ConsumeUint32InRange(uint32_t min, uint32_t max);
+ int ConsumeInt32InRange(int min, int max);
+
+ // Returns a bool, or false when no data remains.
+ bool ConsumeBool();
+
+ // Returns a uint8_t from the input or 0 if nothing remains. This is
+ // equivalent to ConsumeUint32InRange(0, 0xFF).
+ uint8_t ConsumeUint8();
+
+ // Returns a uint16_t from the input. If fewer than 2 bytes of data remain
+ // will fill the most significant bytes with 0. This is equivalent to
+ // ConsumeUint32InRange(0, 0xFFFF).
+ uint16_t ConsumeUint16();
+
+ // Returns a value from |array|, consuming as many bytes as needed to do so.
+ // |array| must be a fixed-size array. Equivalent to
+ // array[ConsumeUint32InRange(sizeof(array)-1)];
+ template <typename Type, size_t size>
+ Type PickValueInArray(Type (&array)[size]) {
+ return array[ConsumeUint32InRange(0, size - 1)];
+ }
+
+ // Reports the remaining bytes available for fuzzed input.
+ size_t remaining_bytes() { return remaining_data_.length(); }
+
+ private:
+ StringPiece remaining_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(FuzzedDataProvider);
+};
+
+} // namespace base
+
+#endif // BASE_TEST_FUZZED_DATA_PROVIDER_H_