17#ifndef FLATBUFFERS_VERIFIER_H_
18#define FLATBUFFERS_VERIFIER_H_
26class Verifier FLATBUFFERS_FINAL_CLASS {
30 uoffset_t max_depth = 64;
32 uoffset_t max_tables = 1000000;
34 bool check_alignment =
true;
36 bool check_nested_flatbuffers =
true;
38 size_t max_size = FLATBUFFERS_MAX_BUFFER_SIZE;
43 explicit Verifier(
const uint8_t *
const buf,
const size_t buf_len,
45 : buf_(buf), size_(buf_len), opts_(opts) {
50 Verifier(
const uint8_t *
const buf,
const size_t buf_len,
51 const uoffset_t max_depth = 64,
const uoffset_t max_tables = 1000000,
52 const bool check_alignment =
true)
53 : Verifier(buf, buf_len, [&] {
62 bool Check(
const bool ok)
const {
64 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
67 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
76 bool Verify(
const size_t elem,
const size_t elem_len)
const {
78 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
79 auto upper_bound = elem + elem_len;
80 if (upper_bound_ < upper_bound)
81 upper_bound_ = upper_bound;
84 return Check(elem_len < size_ && elem <= size_ - elem_len);
88 return Check((elem & (align - 1)) == 0 || !opts_.check_alignment);
92 template<
typename T>
bool Verify(
const size_t elem)
const {
93 return VerifyAlignment(elem,
sizeof(T)) &&
Verify(elem,
sizeof(T));
97 return Verify(
static_cast<size_t>(
p - buf_), len);
102 const size_t elem_len,
const size_t align)
const {
103 const auto f =
static_cast<size_t>(base - buf_) + elem_off;
104 return VerifyAlignment(f, align) &&
Verify(f, elem_len);
108 bool VerifyField(
const uint8_t *
const base,
const voffset_t elem_off,
109 const size_t align)
const {
110 const auto f =
static_cast<size_t>(base - buf_) + elem_off;
111 return VerifyAlignment(f, align) &&
Verify(f,
sizeof(T));
116 return !table || table->Verify(*
this);
120 template<
int &...,
typename T,
typename LenT>
122 return !vec || VerifyVectorOrString<LenT>(
123 reinterpret_cast<const uint8_t *
>(vec),
sizeof(T));
127 template<
int &...,
typename T,
typename LenT>
135 return !str || (VerifyVectorOrString<uoffset_t>(
136 reinterpret_cast<const uint8_t *
>(str), 1, &end) &&
138 Check(buf_[end] ==
'\0'));
142 template<
typename LenT = uoffset_t>
144 size_t *
const end =
nullptr)
const {
145 const auto vec_offset =
static_cast<size_t>(vec - buf_);
147 if (!Verify<LenT>(vec_offset))
return false;
150 const LenT
size = ReadScalar<LenT>(vec);
151 const auto max_elems = opts_.max_size / elem_size;
152 if (!Check(
size < max_elems))
154 const auto byte_size =
sizeof(LenT) + elem_size *
size;
155 if (end) *end = vec_offset + byte_size;
156 return Verify(vec_offset, byte_size);
162 for (uoffset_t i = 0; i < vec->size(); i++) {
163 if (!VerifyString(vec->Get(i)))
return false;
173 for (uoffset_t i = 0; i < vec->size(); i++) {
174 if (!vec->Get(i)->Verify(*
this))
return false;
180 FLATBUFFERS_SUPPRESS_UBSAN(
"unsigned-integer-overflow")
181 bool VerifyTableStart(const uint8_t *const table) {
183 const auto tableo =
static_cast<size_t>(table - buf_);
184 if (!Verify<soffset_t>(tableo))
return false;
188 tableo -
static_cast<size_t>(ReadScalar<soffset_t>(table));
190 if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) &&
191 VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo),
194 const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo);
195 return Check((vsize & 1) == 0) &&
Verify(vtableo, vsize);
203 if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE))
return false;
206 if (identifier && !Check((size_ >= 2 *
sizeof(flatbuffers::uoffset_t) &&
207 BufferHasIdentifier(buf_ + start, identifier)))) {
212 const auto o = VerifyOffset<uoffset_t>(start);
213 return Check(o != 0) &&
214 reinterpret_cast<const T *
>(buf_ + start + o)->
Verify(*
this)
216 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
223 template<
typename T,
int &...,
typename SizeT>
225 const char *
const identifier) {
227 if (!opts_.check_nested_flatbuffers)
return true;
230 if (!buf)
return true;
233 if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE))
return false;
235 Verifier nested_verifier(buf->data(), buf->size(), opts_);
236 return nested_verifier.VerifyBuffer<T>(identifier);
240 template<
typename T>
bool VerifyBuffer() {
return VerifyBuffer<T>(
nullptr); }
243 return VerifyBufferFromStart<T>(identifier, 0);
246 template<
typename T,
typename SizeT = uoffset_t>
248 return Verify<SizeT>(0U) &&
251 Check(ReadScalar<SizeT>(buf_) +
sizeof(SizeT) <= size_) &&
252 VerifyBufferFromStart<T>(identifier,
sizeof(SizeT));
255 template<
typename OffsetT = uoffset_t,
typename SOffsetT = soffset_t>
257 if (!Verify<OffsetT>(start))
return 0;
258 const auto o = ReadScalar<OffsetT>(buf_ + start);
260 if (!Check(o != 0))
return 0;
262 if (!Check(
static_cast<SOffsetT
>(o) >= 0))
return 0;
265 if (!
Verify(start + o, 1))
return 0;
269 template<
typename OffsetT = uoffset_t>
270 size_t VerifyOffset(
const uint8_t *
const base,
const voffset_t start)
const {
271 return VerifyOffset<OffsetT>(
static_cast<size_t>(base - buf_) + start);
280 return Check(depth_ <= opts_.max_depth && num_tables_ <= opts_.max_tables);
292 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
293 uintptr_t
size = upper_bound_;
295 size = (
size - 1 +
sizeof(uoffset_t)) & ~(
sizeof(uoffset_t) - 1);
309 flex_reuse_tracker_ = rt;
317 mutable size_t upper_bound_ = 0;
319 uoffset_t depth_ = 0;
320 uoffset_t num_tables_ = 0;
321 std::vector<uint8_t> *flex_reuse_tracker_ =
nullptr;
326inline size_t Verifier::VerifyOffset<uoffset64_t>(
const size_t start)
const {
327 return VerifyOffset<uoffset64_t, soffset64_t>(start);
#define FLATBUFFERS_ASSERT
bool VerifyVector(const Vector< T, LenT > *const vec) const
bool VerifyField(const uint8_t *const base, const voffset_t elem_off, const size_t align) const
bool Verify(const size_t elem) const
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size, size_t *const end=nullptr) const
bool VerifyFromPointer(const uint8_t *const p, const size_t len)
bool VerifyBufferFromStart(const char *const identifier, const size_t start)
bool Verify(const size_t elem, const size_t elem_len) const
bool VerifyString(const String *const str) const
bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off, const size_t elem_len, const size_t align) const
void SetFlexReuseTracker(std::vector< uint8_t > *const rt)
bool VerifyAlignment(const size_t elem, const size_t align) const
bool Check(const bool ok) const
bool VerifySizePrefixedBuffer(const char *const identifier)
size_t GetComputedSize() const
size_t VerifyOffset(const uint8_t *const base, const voffset_t start) const
std::vector< uint8_t > * GetFlexReuseTracker()
bool VerifyVectorOfTables(const Vector< Offset< T > > *const vec)
size_t VerifyOffset(const size_t start) const
bool VerifyVectorOfStrings(const Vector< Offset< String > > *const vec) const
bool VerifyBuffer(const char *const identifier)
bool VerifyVector(const Vector< const T *, LenT > *const vec) const
bool VerifyNestedFlatBuffer(const Vector< uint8_t, SizeT > *const buf, const char *const identifier)
Verifier(const uint8_t *const buf, const size_t buf_len, const uoffset_t max_depth=64, const uoffset_t max_tables=1000000, const bool check_alignment=true)
Verifier(const uint8_t *const buf, const size_t buf_len, const Options &opts)
bool VerifyTable(const T *const table)
bool Verify(const reflection::Schema &schema, const reflection::Object &root, const uint8_t *buf, size_t length, uoffset_t max_depth=64, uoffset_t max_tables=1000000)