aboutsummaryrefslogtreecommitdiffstats
path: root/executor/_include/flatbuffers/verifier.h
diff options
context:
space:
mode:
Diffstat (limited to 'executor/_include/flatbuffers/verifier.h')
-rw-r--r--executor/_include/flatbuffers/verifier.h85
1 files changed, 50 insertions, 35 deletions
diff --git a/executor/_include/flatbuffers/verifier.h b/executor/_include/flatbuffers/verifier.h
index 87d3f54a5..de1146be9 100644
--- a/executor/_include/flatbuffers/verifier.h
+++ b/executor/_include/flatbuffers/verifier.h
@@ -34,12 +34,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool check_alignment = true;
// If true, run verifier on nested flatbuffers
bool check_nested_flatbuffers = true;
+ // The maximum size of a buffer.
+ size_t max_size = FLATBUFFERS_MAX_BUFFER_SIZE;
+ // Use assertions to check for errors.
+ bool assert = false;
};
explicit Verifier(const uint8_t *const buf, const size_t buf_len,
const Options &opts)
: buf_(buf), size_(buf_len), opts_(opts) {
- FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
+ FLATBUFFERS_ASSERT(size_ < opts.max_size);
}
// Deprecated API, please construct with Verifier::Options.
@@ -58,7 +62,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool Check(const bool ok) const {
// clang-format off
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
- FLATBUFFERS_ASSERT(ok);
+ if (opts_.assert) { FLATBUFFERS_ASSERT(ok); }
#endif
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
if (!ok)
@@ -113,41 +117,43 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Verify a pointer (may be NULL) of any vector type.
- template<typename T> bool VerifyVector(const Vector<T> *const vec) const {
- return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
- sizeof(T));
+ template<int &..., typename T, typename LenT>
+ bool VerifyVector(const Vector<T, LenT> *const vec) const {
+ return !vec || VerifyVectorOrString<LenT>(
+ reinterpret_cast<const uint8_t *>(vec), sizeof(T));
}
// Verify a pointer (may be NULL) of a vector to struct.
- template<typename T>
- bool VerifyVector(const Vector<const T *> *const vec) const {
- return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
+ template<int &..., typename T, typename LenT>
+ bool VerifyVector(const Vector<const T *, LenT> *const vec) const {
+ return VerifyVector(reinterpret_cast<const Vector<T, LenT> *>(vec));
}
// Verify a pointer (may be NULL) to string.
bool VerifyString(const String *const str) const {
size_t end;
- return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
- 1, &end) &&
+ return !str || (VerifyVectorOrString<uoffset_t>(
+ reinterpret_cast<const uint8_t *>(str), 1, &end) &&
Verify(end, 1) && // Must have terminator
Check(buf_[end] == '\0')); // Terminating byte must be 0.
}
// Common code between vectors and strings.
+ template<typename LenT = uoffset_t>
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
size_t *const end = nullptr) const {
- const auto veco = static_cast<size_t>(vec - buf_);
+ const auto vec_offset = static_cast<size_t>(vec - buf_);
// Check we can read the size field.
- if (!Verify<uoffset_t>(veco)) return false;
+ if (!Verify<LenT>(vec_offset)) return false;
// Check the whole array. If this is a string, the byte past the array must
// be 0.
- const auto size = ReadScalar<uoffset_t>(vec);
- const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
+ const LenT size = ReadScalar<LenT>(vec);
+ const auto max_elems = opts_.max_size / elem_size;
if (!Check(size < max_elems))
return false; // Protect against byte_size overflowing.
- const auto byte_size = sizeof(size) + elem_size * size;
- if (end) *end = veco + byte_size;
- return Verify(veco, byte_size);
+ const auto byte_size = sizeof(LenT) + elem_size * size;
+ if (end) *end = vec_offset + byte_size;
+ return Verify(vec_offset, byte_size);
}
// Special case for string contents, after the above has been called.
@@ -171,8 +177,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true;
}
- __suppress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
- const uint8_t *const table) {
+ FLATBUFFERS_SUPPRESS_UBSAN("unsigned-integer-overflow")
+ bool VerifyTableStart(const uint8_t *const table) {
// Check the vtable offset.
const auto tableo = static_cast<size_t>(table - buf_);
if (!Verify<soffset_t>(tableo)) return false;
@@ -203,7 +209,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Call T::Verify, which must be in the generated code for this type.
- const auto o = VerifyOffset(start);
+ const auto o = VerifyOffset<uoffset_t>(start);
return Check(o != 0) &&
reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
// clang-format off
@@ -214,8 +220,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// clang-format on
}
- template<typename T>
- bool VerifyNestedFlatBuffer(const Vector<uint8_t> *const buf,
+ template<typename T, int &..., typename SizeT>
+ bool VerifyNestedFlatBuffer(const Vector<uint8_t, SizeT> *const buf,
const char *const identifier) {
// Caller opted out of this.
if (!opts_.check_nested_flatbuffers) return true;
@@ -226,7 +232,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// If there is a nested buffer, it must be greater than the min size.
if (!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
- Verifier nested_verifier(buf->data(), buf->size());
+ Verifier nested_verifier(buf->data(), buf->size(), opts_);
return nested_verifier.VerifyBuffer<T>(identifier);
}
@@ -237,29 +243,32 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return VerifyBufferFromStart<T>(identifier, 0);
}
- template<typename T>
+ template<typename T, typename SizeT = uoffset_t>
bool VerifySizePrefixedBuffer(const char *const identifier) {
- return Verify<uoffset_t>(0U) &&
- Check(ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t)) &&
- VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
+ return Verify<SizeT>(0U) &&
+ // Ensure the prefixed size is within the bounds of the provided
+ // length.
+ Check(ReadScalar<SizeT>(buf_) + sizeof(SizeT) <= size_) &&
+ VerifyBufferFromStart<T>(identifier, sizeof(SizeT));
}
- uoffset_t VerifyOffset(const size_t start) const {
- if (!Verify<uoffset_t>(start)) return 0;
- const auto o = ReadScalar<uoffset_t>(buf_ + start);
+ template<typename OffsetT = uoffset_t, typename SOffsetT = soffset_t>
+ size_t VerifyOffset(const size_t start) const {
+ if (!Verify<OffsetT>(start)) return 0;
+ const auto o = ReadScalar<OffsetT>(buf_ + start);
// May not point to itself.
if (!Check(o != 0)) return 0;
- // Can't wrap around / buffers are max 2GB.
- if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
+ // Can't wrap around larger than the max size.
+ if (!Check(static_cast<SOffsetT>(o) >= 0)) return 0;
// Must be inside the buffer to create a pointer from it (pointer outside
// buffer is UB).
if (!Verify(start + o, 1)) return 0;
return o;
}
- uoffset_t VerifyOffset(const uint8_t *const base,
- const voffset_t start) const {
- return VerifyOffset(static_cast<size_t>(base - buf_) + start);
+ template<typename OffsetT = uoffset_t>
+ size_t VerifyOffset(const uint8_t *const base, const voffset_t start) const {
+ return VerifyOffset<OffsetT>(static_cast<size_t>(base - buf_) + start);
}
// Called at the start of a table to increase counters measuring data
@@ -312,6 +321,12 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
std::vector<uint8_t> *flex_reuse_tracker_ = nullptr;
};
+// Specialization for 64-bit offsets.
+template<>
+inline size_t Verifier::VerifyOffset<uoffset64_t>(const size_t start) const {
+ return VerifyOffset<uoffset64_t, soffset64_t>(start);
+}
+
} // namespace flatbuffers
#endif // FLATBUFFERS_VERIFIER_H_