Coverage Report

Created: 2025-07-09 06:34

/src/flatbuffers/tests/fuzzer/flatbuffers_64bit_fuzzer.cc
Line
Count
Source (jump to first uncovered line)
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
15
OneTimeTestInit OneTimeTestInit::one_time_init_;
16
17
static RootTableBinarySchema schema;
18
19
static constexpr uint8_t flags_sized_prefixed = 0b00000001;
20
21
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
22
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
23
24
namespace flatbuffers {
25
26
template<typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
27
7.57M
uint64_t Hash(T value, uint64_t hash) {
28
7.57M
  return (hash * kFnvPrime) ^ value;
29
7.57M
}
unsigned long flatbuffers::Hash<unsigned char, void>(unsigned char, unsigned long)
Line
Count
Source
27
7.39M
uint64_t Hash(T value, uint64_t hash) {
28
7.39M
  return (hash * kFnvPrime) ^ value;
29
7.39M
}
unsigned long flatbuffers::Hash<int, void>(int, unsigned long)
Line
Count
Source
27
176k
uint64_t Hash(T value, uint64_t hash) {
28
176k
  return (hash * kFnvPrime) ^ value;
29
176k
}
30
31
175k
uint64_t Hash(double value, uint64_t hash) {
32
175k
  static_assert(sizeof(double) == sizeof(uint64_t));
33
175k
  return (hash * kFnvPrime) ^ static_cast<uint64_t>(value);
34
175k
}
35
36
1.56k
uint64_t Hash(const flatbuffers::String *value, uint64_t hash) {
37
1.56k
  if (value == nullptr) { return hash * kFnvPrime; }
38
2.49M
  for (auto &c : value->str()) { hash = Hash(static_cast<uint8_t>(c), hash); }
39
486
  return hash;
40
1.56k
}
41
42
175k
uint64_t Hash(const LeafStruct *value, uint64_t hash) {
43
175k
  if (value == nullptr) { return hash * kFnvPrime; }
44
175k
  hash = Hash(value->a(), hash);
45
175k
  hash = Hash(value->b(), hash);
46
175k
  return hash;
47
175k
}
48
49
1.56k
template<typename T> uint64_t Hash(const Vector<T> *value, uint64_t hash) {
50
1.56k
  if (value == nullptr) { return hash * kFnvPrime; }
51
1.61M
  for (const T c : *value) { hash = Hash(c, hash); }
52
337
  return hash;
53
1.56k
}
unsigned long flatbuffers::Hash<unsigned char>(flatbuffers::Vector<unsigned char, unsigned int> const*, unsigned long)
Line
Count
Source
49
782
template<typename T> uint64_t Hash(const Vector<T> *value, uint64_t hash) {
50
782
  if (value == nullptr) { return hash * kFnvPrime; }
51
1.54M
  for (const T c : *value) { hash = Hash(c, hash); }
52
178
  return hash;
53
782
}
unsigned long flatbuffers::Hash<LeafStruct const*>(flatbuffers::Vector<LeafStruct const*, unsigned int> const*, unsigned long)
Line
Count
Source
49
782
template<typename T> uint64_t Hash(const Vector<T> *value, uint64_t hash) {
50
782
  if (value == nullptr) { return hash * kFnvPrime; }
51
71.3k
  for (const T c : *value) { hash = Hash(c, hash); }
52
159
  return hash;
53
782
}
54
55
2.34k
template<typename T> uint64_t Hash(const Vector64<T> *value, uint64_t hash) {
56
2.34k
  if (value == nullptr) { return hash * kFnvPrime; }
57
3.46M
  for (const T c : *value) { hash = Hash(c, hash); }
58
485
  return hash;
59
2.34k
}
unsigned long flatbuffers::Hash<unsigned char>(flatbuffers::Vector<unsigned char, unsigned long> const*, unsigned long)
Line
Count
Source
55
1.56k
template<typename T> uint64_t Hash(const Vector64<T> *value, uint64_t hash) {
56
1.56k
  if (value == nullptr) { return hash * kFnvPrime; }
57
3.35M
  for (const T c : *value) { hash = Hash(c, hash); }
58
379
  return hash;
59
1.56k
}
unsigned long flatbuffers::Hash<LeafStruct const*>(flatbuffers::Vector<LeafStruct const*, unsigned long> const*, unsigned long)
Line
Count
Source
55
782
template<typename T> uint64_t Hash(const Vector64<T> *value, uint64_t hash) {
56
782
  if (value == nullptr) { return hash * kFnvPrime; }
57
104k
  for (const T c : *value) { hash = Hash(c, hash); }
58
106
  return hash;
59
782
}
60
61
1.25k
uint64_t Hash(const RootTable *value, uint64_t hash) {
62
1.25k
  if (value == nullptr) { return hash * kFnvPrime; }
63
  // Hash all the fields so we can exercise all parts of the code.
64
782
  hash = Hash(value->far_vector(), hash);
65
782
  hash = Hash(value->a(), hash);
66
782
  hash = Hash(value->far_string(), hash);
67
782
  hash = Hash(value->big_vector(), hash);
68
782
  hash = Hash(value->near_string(), hash);
69
782
  hash = Hash(value->nested_root(), hash);
70
782
  hash = Hash(value->far_struct_vector(), hash);
71
782
  hash = Hash(value->big_struct_vector(), hash);
72
782
  return hash;
73
1.25k
}
74
75
static int AccessBuffer(const uint8_t *data, size_t size,
76
625
                        bool is_size_prefixed) {
77
625
  const RootTable *root_table =
78
625
      is_size_prefixed ? GetSizePrefixedRootTable(data) : GetRootTable(data);
79
625
  TEST_NOTNULL(root_table);
80
81
625
  uint64_t hash = kOffsetBasis;
82
625
  hash = Hash(root_table, hash);
83
625
  hash = Hash(root_table->nested_root_nested_root(), hash);
84
85
625
  return 0;
86
625
}
87
88
6
extern "C" int LLVMFuzzerInitialize(int *, char ***argv) {
89
6
  Verifier verifier(schema.begin(), schema.size());
90
6
  TEST_EQ(true, reflection::VerifySchemaBuffer(verifier));
91
92
6
  return 0;
93
6
}
94
95
3.03k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
96
3.03k
  if (size < FLATBUFFERS_MIN_BUFFER_SIZE) { return 0; }
97
98
  // Take the first bit of data as a flag to control things.
99
3.03k
  const uint8_t flags = data[0];
100
3.03k
  data++;
101
3.03k
  size--;
102
103
3.03k
  Verifier::Options options;
104
3.03k
  options.assert = true;
105
3.03k
  options.check_alignment = true;
106
3.03k
  options.check_nested_flatbuffers = true;
107
108
3.03k
  Verifier verifier(data, size, options);
109
110
3.03k
  const bool is_size_prefixed = flags & flags_sized_prefixed;
111
112
  // Filter out data that isn't valid.
113
3.03k
  if ((is_size_prefixed && !VerifySizePrefixedRootTableBuffer(verifier)) ||
114
3.03k
      !VerifyRootTableBuffer(verifier)) {
115
2.40k
    return 0;
116
2.40k
  }
117
118
625
  return AccessBuffer(data, size, is_size_prefixed);
119
3.03k
}
120
121
}  // namespace flatbuffers