diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 4f5a4f012..1b7bca486 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1216,6 +1216,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS { size_t _max_tables = 1000000) : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth), num_tables_(0), max_tables_(_max_tables) + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + , upper_bound_(buf) + #endif {} // Central location where any verification failures register. @@ -1223,11 +1226,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS { #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE assert(ok); #endif + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + if (!ok) + upper_bound_ = buf_; + #endif return ok; } // Verify any range within the buffer. bool Verify(const void *elem, size_t elem_len) const { + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + auto upper_bound = reinterpret_cast(elem) + elem_len; + if (upper_bound_ < upper_bound) + upper_bound_ = upper_bound; + #endif return Check(elem_len <= (size_t) (end_ - buf_) && elem >= buf_ && elem <= end_ - elem_len); @@ -1306,7 +1318,11 @@ class Verifier FLATBUFFERS_FINAL_CLASS { // Call T::Verify, which must be in the generated code for this type. return Verify(buf_) && reinterpret_cast(buf_ + ReadScalar(buf_))-> - Verify(*this); + Verify(*this) + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + && GetComputedSize() + #endif + ; } // Called at the start of a table to increase counters measuring data @@ -1325,6 +1341,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS { return true; } + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + // Returns the message size in bytes + size_t GetComputedSize() const { + uintptr_t size = upper_bound_ - buf_; + // Align the size to uoffset_t + size = (size - 1 + sizeof(uoffset_t)) & -uintptr_t(sizeof(uoffset_t)); + return (buf_ + size > end_) ? 0 : size; + } + #endif + private: const uint8_t *buf_; const uint8_t *end_; @@ -1332,6 +1358,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS { size_t max_depth_; size_t num_tables_; size_t max_tables_; + #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE + mutable const uint8_t *upper_bound_; + #endif }; // Convenient way to bundle a buffer and its length, to pass it around diff --git a/tests/test.cpp b/tests/test.cpp index 6f3b06299..4cdfbea16 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -15,6 +15,7 @@ */ #define FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 1 +#define FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" @@ -160,6 +161,23 @@ void AccessFlatBufferTest(const uint8_t *flatbuf, size_t length) { flatbuffers::Verifier verifier(flatbuf, length); TEST_EQ(VerifyMonsterBuffer(verifier), true); + std::vector test_buff; + test_buff.resize(length * 2); + std::memcpy(&test_buff[0], flatbuf , length); + std::memcpy(&test_buff[length], flatbuf , length); + + flatbuffers::Verifier verifierl(&test_buff[0], length - 1); + TEST_EQ(VerifyMonsterBuffer(verifierl), false); + TEST_EQ(verifierl.GetComputedSize(), 0); + + flatbuffers::Verifier verifier1(&test_buff[0], length); + TEST_EQ(VerifyMonsterBuffer(verifier1), true); + TEST_EQ(verifier1.GetComputedSize(), length); + + flatbuffers::Verifier verifier2(&test_buff[length], length); + TEST_EQ(VerifyMonsterBuffer(verifier2), true); + TEST_EQ(verifier2.GetComputedSize(), length); + TEST_EQ(strcmp(MonsterIdentifier(), "MONS"), 0); TEST_EQ(MonsterBufferHasIdentifier(flatbuf), true); TEST_EQ(strcmp(MonsterExtension(), "mon"), 0);