diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 4f5a4f012..01ab6db04 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); @@ -1302,11 +1314,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS { } // Verify this whole buffer, starting with root type T. - template bool VerifyBuffer() { + template bool VerifyBuffer(const char *identifier) { + if (identifier && (size_t(end_ - buf_) < 2 * sizeof(flatbuffers::uoffset_t) || + !BufferHasIdentifier(buf_, identifier))) { + return false; + } + // 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 +1346,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 +1363,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/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h index da1124939..eb981857b 100644 --- a/include/flatbuffers/reflection_generated.h +++ b/include/flatbuffers/reflection_generated.h @@ -478,12 +478,12 @@ inline flatbuffers::Offset CreateSchema(flatbuffers::FlatBufferBuilder & inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot(buf); } -inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } - inline const char *SchemaIdentifier() { return "BFBS"; } inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); } +inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(SchemaIdentifier()); } + inline const char *SchemaExtension() { return "bfbs"; } inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root, SchemaIdentifier()); } diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 1a16126a5..62a23ad82 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -135,15 +135,15 @@ struct MonsterBuilder { }; inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, - const Vec3 *pos = 0, - int16_t mana = 150, - int16_t hp = 100, - flatbuffers::Offset name = 0, - flatbuffers::Offset> inventory = 0, - Color color = Color_Blue, - flatbuffers::Offset>> weapons = 0, - Equipment equipped_type = Equipment_NONE, - flatbuffers::Offset equipped = 0) { + const Vec3 *pos = 0, + int16_t mana = 150, + int16_t hp = 100, + flatbuffers::Offset name = 0, + flatbuffers::Offset> inventory = 0, + Color color = Color_Blue, + flatbuffers::Offset>> weapons = 0, + Equipment equipped_type = Equipment_NONE, + flatbuffers::Offset equipped = 0) { MonsterBuilder builder_(_fbb); builder_.add_equipped(equipped); builder_.add_weapons(weapons); @@ -157,6 +157,19 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder return builder_.Finish(); } +inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, + const Vec3 *pos = 0, + int16_t mana = 150, + int16_t hp = 100, + const char *name = nullptr, + const std::vector *inventory = nullptr, + Color color = Color_Blue, + const std::vector> *weapons = nullptr, + Equipment equipped_type = Equipment_NONE, + flatbuffers::Offset equipped = 0) { + return CreateMonster(_fbb, pos, mana, hp, name ? 0 : _fbb.CreateString(name), inventory ? 0 : _fbb.CreateVector(*inventory), color, weapons ? 0 : _fbb.CreateVector>(*weapons), equipped_type, equipped); +} + struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum { VT_NAME = 4, @@ -189,14 +202,20 @@ struct WeaponBuilder { }; inline flatbuffers::Offset CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset name = 0, - int16_t damage = 0) { + flatbuffers::Offset name = 0, + int16_t damage = 0) { WeaponBuilder builder_(_fbb); builder_.add_name(name); builder_.add_damage(damage); return builder_.Finish(); } +inline flatbuffers::Offset CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, + const char *name = nullptr, + int16_t damage = 0) { + return CreateWeapon(_fbb, name ? 0 : _fbb.CreateString(name), damage); +} + inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) { switch (type) { case Equipment_NONE: return true; @@ -209,7 +228,7 @@ inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatb inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot(buf); } -inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } +inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(nullptr); } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root); } diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 463f3a0be..e12e8a34a 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -158,14 +158,6 @@ class CppGenerator : public BaseGenerator { code += name + ">(buf); }\n\n"; } - // The root verifier: - code += "inline bool Verify"; - code += name; - code += - "Buffer(flatbuffers::Verifier &verifier) { " - "return verifier.VerifyBuffer<"; - code += cpp_qualified_name + ">(); }\n\n"; - if (parser_.file_identifier_.length()) { // Return the identifier code += "inline const char *" + name; @@ -179,6 +171,20 @@ class CppGenerator : public BaseGenerator { code += name + "Identifier()); }\n\n"; } + // The root verifier: + code += "inline bool Verify"; + code += name; + code += + "Buffer(flatbuffers::Verifier &verifier) { " + "return verifier.VerifyBuffer<"; + code += cpp_qualified_name + ">("; + if (parser_.file_identifier_.length()) + code += name + "Identifier()"; + else + code += "nullptr"; + code += "); }\n\n"; + + if (parser_.file_extension_.length()) { // Return the extension code += "inline const char *" + name; diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 40e7c4089..9f3d4de0f 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -510,12 +510,12 @@ inline const MyGame::Example::Monster *GetMonster(const void *buf) { return flat inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot(buf); } -inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } - inline const char *MonsterIdentifier() { return "MONS"; } inline bool MonsterBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier()); } +inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(MonsterIdentifier()); } + inline const char *MonsterExtension() { return "mon"; } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root, MonsterIdentifier()); } diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h index 9e10eb4c1..23a0964fb 100644 --- a/tests/namespace_test/namespace_test1_generated.h +++ b/tests/namespace_test/namespace_test1_generated.h @@ -69,7 +69,7 @@ struct TableInNestedNSBuilder { }; inline flatbuffers::Offset CreateTableInNestedNS(flatbuffers::FlatBufferBuilder &_fbb, - int32_t foo = 0) { + int32_t foo = 0) { TableInNestedNSBuilder builder_(_fbb); builder_.add_foo(foo); return builder_.Finish(); diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index 8e6b3ada8..885eae29b 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -60,9 +60,9 @@ struct TableInFirstNSBuilder { }; inline flatbuffers::Offset CreateTableInFirstNS(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset foo_table = 0, - NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A, - const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) { + flatbuffers::Offset foo_table = 0, + NamespaceA::NamespaceB::EnumInNestedNS foo_enum = NamespaceA::NamespaceB::EnumInNestedNS_A, + const NamespaceA::NamespaceB::StructInNestedNS *foo_struct = 0) { TableInFirstNSBuilder builder_(_fbb); builder_.add_foo_struct(foo_struct); builder_.add_foo_table(foo_table); @@ -107,8 +107,8 @@ struct TableInCBuilder { }; inline flatbuffers::Offset CreateTableInC(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset refer_to_a1 = 0, - flatbuffers::Offset refer_to_a2 = 0) { + flatbuffers::Offset refer_to_a1 = 0, + flatbuffers::Offset refer_to_a2 = 0) { TableInCBuilder builder_(_fbb); builder_.add_refer_to_a2(refer_to_a2); builder_.add_refer_to_a1(refer_to_a1); @@ -146,7 +146,7 @@ struct SecondTableInABuilder { }; inline flatbuffers::Offset CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb, - flatbuffers::Offset refer_to_c = 0) { + flatbuffers::Offset refer_to_c = 0) { SecondTableInABuilder builder_(_fbb); builder_.add_refer_to_c(refer_to_c); return builder_.Finish(); diff --git a/tests/test.cpp b/tests/test.cpp index 209ec699f..402843a6f 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);