Home | History | Annotate | Download | only in test
      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 "base/test/fuzzed_data_provider.h"
      6 
      7 #include <algorithm>
      8 #include <limits>
      9 
     10 #include "base/logging.h"
     11 
     12 namespace base {
     13 
     14 FuzzedDataProvider::FuzzedDataProvider(const uint8_t* data, size_t size)
     15     : remaining_data_(reinterpret_cast<const char*>(data), size) {}
     16 
     17 FuzzedDataProvider::~FuzzedDataProvider() = default;
     18 
     19 std::string FuzzedDataProvider::ConsumeBytes(size_t num_bytes) {
     20   num_bytes = std::min(num_bytes, remaining_data_.length());
     21   StringPiece result(remaining_data_.data(), num_bytes);
     22   remaining_data_ = remaining_data_.substr(num_bytes);
     23   return result.as_string();
     24 }
     25 
     26 std::string FuzzedDataProvider::ConsumeRemainingBytes() {
     27   return ConsumeBytes(remaining_data_.length());
     28 }
     29 
     30 uint32_t FuzzedDataProvider::ConsumeUint32InRange(uint32_t min, uint32_t max) {
     31   CHECK_LE(min, max);
     32 
     33   uint32_t range = max - min;
     34   uint32_t offset = 0;
     35   uint32_t result = 0;
     36 
     37   while (offset < 32 && (range >> offset) > 0 && !remaining_data_.empty()) {
     38     // Pull bytes off the end of the seed data. Experimentally, this seems to
     39     // allow the fuzzer to more easily explore the input space. This makes
     40     // sense, since it works by modifying inputs that caused new code to run,
     41     // and this data is often used to encode length of data read by
     42     // ConsumeBytes. Separating out read lengths makes it easier modify the
     43     // contents of the data that is actually read.
     44     uint8_t next_byte = remaining_data_.back();
     45     remaining_data_.remove_suffix(1);
     46     result = (result << 8) | next_byte;
     47     offset += 8;
     48   }
     49 
     50   // Avoid division by 0, in the case |range + 1| results in overflow.
     51   if (range == std::numeric_limits<uint32_t>::max())
     52     return result;
     53 
     54   return min + result % (range + 1);
     55 }
     56 
     57 std::string FuzzedDataProvider::ConsumeRandomLengthString(size_t max_length) {
     58   // Reads bytes from start of |remaining_data_|. Maps "\\" to "\", and maps "\"
     59   // followed by anything else to the end of the string. As a result of this
     60   // logic, a fuzzer can insert characters into the string, and the string will
     61   // be lengthened to include those new characters, resulting in a more stable
     62   // fuzzer than picking the length of a string independently from picking its
     63   // contents.
     64   std::string out;
     65   for (size_t i = 0; i < max_length && !remaining_data_.empty(); ++i) {
     66     char next = remaining_data_[0];
     67     remaining_data_.remove_prefix(1);
     68     if (next == '\\' && !remaining_data_.empty()) {
     69       next = remaining_data_[0];
     70       remaining_data_.remove_prefix(1);
     71       if (next != '\\')
     72         return out;
     73     }
     74     out += next;
     75   }
     76   return out;
     77 }
     78 
     79 int FuzzedDataProvider::ConsumeInt32InRange(int min, int max) {
     80   CHECK_LE(min, max);
     81 
     82   uint32_t range = max - min;
     83   return min + ConsumeUint32InRange(0, range);
     84 }
     85 
     86 bool FuzzedDataProvider::ConsumeBool() {
     87   return (ConsumeUint8() & 0x01) == 0x01;
     88 }
     89 
     90 uint8_t FuzzedDataProvider::ConsumeUint8() {
     91   return ConsumeUint32InRange(0, 0xFF);
     92 }
     93 
     94 uint16_t FuzzedDataProvider::ConsumeUint16() {
     95   return ConsumeUint32InRange(0, 0xFFFF);
     96 }
     97 
     98 }  // namespace base
     99