...

Text file src/github.com/google/flatbuffers/tests/fuzzer/flatbuffers_64bit_fuzzer.cc

Documentation: github.com/google/flatbuffers/tests/fuzzer

     1#include <cstdint>
     2#include <filesystem>
     3#include <type_traits>
     4
     5#include "64bit/test_64bit_bfbs_generated.h"
     6#include "64bit/test_64bit_generated.h"
     7#include "flatbuffers/base.h"
     8#include "flatbuffers/flatbuffer_builder.h"
     9#include "flatbuffers/flatbuffers.h"
    10#include "flatbuffers/reflection.h"
    11#include "flatbuffers/verifier.h"
    12#include "test_assert.h"
    13#include "test_init.h"
    14
    15OneTimeTestInit OneTimeTestInit::one_time_init_;
    16
    17static RootTableBinarySchema schema;
    18
    19static constexpr uint8_t flags_sized_prefixed = 0b00000001;
    20
    21static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
    22static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
    23
    24namespace flatbuffers {
    25
    26template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
    27uint64_t Hash(T value, uint64_t hash) {
    28  return (hash * kFnvPrime) ^ value;
    29}
    30
    31uint64_t Hash(double value, uint64_t hash) {
    32  static_assert(sizeof(double) == sizeof(uint64_t));
    33  return (hash * kFnvPrime) ^ static_cast<uint64_t>(value);
    34}
    35
    36uint64_t Hash(const flatbuffers::String *value, uint64_t hash) {
    37  if (value == nullptr) { return hash * kFnvPrime; }
    38  for (auto &c : value->str()) { hash = Hash(static_cast<uint8_t>(c), hash); }
    39  return hash;
    40}
    41
    42uint64_t Hash(const LeafStruct *value, uint64_t hash) {
    43  if (value == nullptr) { return hash * kFnvPrime; }
    44  hash = Hash(value->a(), hash);
    45  hash = Hash(value->b(), hash);
    46  return hash;
    47}
    48
    49template<typename T> uint64_t Hash(const Vector<T> *value, uint64_t hash) {
    50  if (value == nullptr) { return hash * kFnvPrime; }
    51  for (const T c : *value) { hash = Hash(c, hash); }
    52  return hash;
    53}
    54
    55template<typename T> uint64_t Hash(const Vector64<T> *value, uint64_t hash) {
    56  if (value == nullptr) { return hash * kFnvPrime; }
    57  for (const T c : *value) { hash = Hash(c, hash); }
    58  return hash;
    59}
    60
    61uint64_t Hash(const RootTable *value, uint64_t hash) {
    62  if (value == nullptr) { return hash * kFnvPrime; }
    63  // Hash all the fields so we can exercise all parts of the code.
    64  hash = Hash(value->far_vector(), hash);
    65  hash = Hash(value->a(), hash);
    66  hash = Hash(value->far_string(), hash);
    67  hash = Hash(value->big_vector(), hash);
    68  hash = Hash(value->near_string(), hash);
    69  hash = Hash(value->nested_root(), hash);
    70  hash = Hash(value->far_struct_vector(), hash);
    71  hash = Hash(value->big_struct_vector(), hash);
    72  return hash;
    73}
    74
    75static int AccessBuffer(const uint8_t *data, size_t size,
    76                        bool is_size_prefixed) {
    77  const RootTable *root_table =
    78      is_size_prefixed ? GetSizePrefixedRootTable(data) : GetRootTable(data);
    79  TEST_NOTNULL(root_table);
    80
    81  uint64_t hash = kOffsetBasis;
    82  hash = Hash(root_table, hash);
    83  hash = Hash(root_table->nested_root_nested_root(), hash);
    84
    85  return 0;
    86}
    87
    88extern "C" int LLVMFuzzerInitialize(int *, char ***argv) {
    89  Verifier verifier(schema.begin(), schema.size());
    90  TEST_EQ(true, reflection::VerifySchemaBuffer(verifier));
    91
    92  return 0;
    93}
    94
    95extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    96  if (size < FLATBUFFERS_MIN_BUFFER_SIZE) { return 0; }
    97
    98  // Take the first bit of data as a flag to control things.
    99  const uint8_t flags = data[0];
   100  data++;
   101  size--;
   102
   103  Verifier::Options options;
   104  options.assert = true;
   105  options.check_alignment = true;
   106  options.check_nested_flatbuffers = true;
   107
   108  Verifier verifier(data, size, options);
   109
   110  const bool is_size_prefixed = flags & flags_sized_prefixed;
   111
   112  // Filter out data that isn't valid.
   113  if ((is_size_prefixed && !VerifySizePrefixedRootTableBuffer(verifier)) ||
   114      !VerifyRootTableBuffer(verifier)) {
   115    return 0;
   116  }
   117
   118  return AccessBuffer(data, size, is_size_prefixed);
   119}
   120
   121}  // namespace flatbuffers

View as plain text