From ca417426c7694d962752c6124d3b77878987323a Mon Sep 17 00:00:00 2001 From: Frank Benkstein Date: Mon, 22 Oct 2018 15:57:45 -0700 Subject: [PATCH] make flatbuffers::IsFieldPresent safer (#4988) Give the vtable offset enum inside each table the name "FlatBuffersVTableOffset" and base type voffset_t so it can be used as a dependent type in IsFieldPresent. This makes that function slightly safer since it prevents calling it with arbitrary, non-table types. Now, the only way to use IsFieldPresent incorrectly is to create your own type which does not inherit from flatbuffers::Table but has a dependent voffset convertible type "FlatBuffersVTableOffset". --- include/flatbuffers/base.h | 2 ++ include/flatbuffers/flatbuffers.h | 6 ++++-- include/flatbuffers/reflection_generated.h | 18 +++++++++--------- samples/monster_generated.h | 4 ++-- src/idl_gen_cpp.cpp | 2 +- tests/monster_test_generated.h | 10 +++++----- .../namespace_test/namespace_test1_generated.h | 2 +- .../namespace_test/namespace_test2_generated.h | 6 +++--- tests/union_vector/union_vector_generated.h | 4 ++-- 9 files changed, 29 insertions(+), 25 deletions(-) diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index 02c8f0c12..7e6dc53ef 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -122,9 +122,11 @@ defined(__clang__) #define FLATBUFFERS_FINAL_CLASS final #define FLATBUFFERS_OVERRIDE override + #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t #else #define FLATBUFFERS_FINAL_CLASS #define FLATBUFFERS_OVERRIDE + #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE #endif #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index a4543033b..b6f3681dc 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -2370,9 +2370,11 @@ typedef uint64_t hash_value_t; // Note: this function will return false for fields equal to the default // value, since they're not stored in the buffer (unless force_defaults was // used). -template bool IsFieldPresent(const T *table, voffset_t field) { +template +bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { // Cast, since Table is a private baseclass of any table types. - return reinterpret_cast(table)->CheckField(field); + return reinterpret_cast(table)->CheckField( + static_cast(field)); } // Utility function for reverse lookups on the EnumNames*() functions diff --git a/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h index 9b56d3d35..0424d6ae9 100644 --- a/include/flatbuffers/reflection_generated.h +++ b/include/flatbuffers/reflection_generated.h @@ -100,7 +100,7 @@ inline const char *EnumNameBaseType(BaseType e) { } struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_BASE_TYPE = 4, VT_ELEMENT = 6, VT_INDEX = 8 @@ -160,7 +160,7 @@ inline flatbuffers::Offset CreateType( } struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_KEY = 4, VT_VALUE = 6 }; @@ -229,7 +229,7 @@ inline flatbuffers::Offset CreateKeyValueDirect( } struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_VALUE = 6, VT_OBJECT = 8, @@ -337,7 +337,7 @@ inline flatbuffers::Offset CreateEnumValDirect( } struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_VALUES = 6, VT_IS_UNION = 8, @@ -462,7 +462,7 @@ inline flatbuffers::Offset CreateEnumDirect( } struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_TYPE = 6, VT_ID = 8, @@ -644,7 +644,7 @@ inline flatbuffers::Offset CreateFieldDirect( } struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_FIELDS = 6, VT_IS_STRUCT = 8, @@ -779,7 +779,7 @@ inline flatbuffers::Offset CreateObjectDirect( } struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_REQUEST = 6, VT_RESPONSE = 8, @@ -891,7 +891,7 @@ inline flatbuffers::Offset CreateRPCCallDirect( } struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_CALLS = 6, VT_ATTRIBUTES = 8, @@ -989,7 +989,7 @@ inline flatbuffers::Offset CreateServiceDirect( } struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_OBJECTS = 4, VT_ENUMS = 6, VT_FILE_IDENT = 8, diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 4fbbeccc9..153eac666 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -235,7 +235,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return MonsterTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_POS = 4, VT_MANA = 6, VT_HP = 8, @@ -443,7 +443,7 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return WeaponTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, VT_DAMAGE = 6 }; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index dc951464e..8ab3e93b8 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -1710,7 +1710,7 @@ class CppGenerator : public BaseGenerator { // We need to add a trailing comma to all elements except the last one as // older versions of gcc complain about this. code_.SetValue("SEP", ""); - code_ += " enum {"; + code_ += " enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { const auto &field = **it; diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 80146a966..e21b85ed5 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -539,7 +539,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta static const flatbuffers::TypeTable *MiniReflectTypeTable() { return TestSimpleTableWithEnumTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_COLOR = 4 }; Color color() const { @@ -609,7 +609,7 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return StatTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ID = 4, VT_VAL = 6, VT_COUNT = 8 @@ -713,7 +713,7 @@ struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return ReferrableTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ID = 4 }; uint64_t id() const { @@ -882,7 +882,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return MonsterTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_POS = 4, VT_MANA = 6, VT_HP = 8, @@ -1665,7 +1665,7 @@ struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return TypeAliasesTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_I8 = 4, VT_U8 = 6, VT_I16 = 8, diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h index 0811c8e3f..3f964b090 100644 --- a/tests/namespace_test/namespace_test1_generated.h +++ b/tests/namespace_test/namespace_test1_generated.h @@ -82,7 +82,7 @@ struct TableInNestedNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return TableInNestedNSTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_FOO = 4 }; int32_t foo() const { diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index 4a111dc82..135100a40 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -42,7 +42,7 @@ struct TableInFirstNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return TableInFirstNSTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_FOO_TABLE = 4, VT_FOO_ENUM = 6, VT_FOO_STRUCT = 8 @@ -119,7 +119,7 @@ struct TableInC FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return TableInCTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_REFER_TO_A1 = 4, VT_REFER_TO_A2 = 6 }; @@ -184,7 +184,7 @@ struct SecondTableInA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return SecondTableInATypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_REFER_TO_C = 4 }; const NamespaceC::TableInC *refer_to_c() const { diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h index 76d2f6728..a7e3cd49f 100644 --- a/tests/union_vector/union_vector_generated.h +++ b/tests/union_vector/union_vector_generated.h @@ -251,7 +251,7 @@ struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return AttackerTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_SWORD_ATTACK_DAMAGE = 4 }; int32_t sword_attack_damage() const { @@ -317,7 +317,7 @@ struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static const flatbuffers::TypeTable *MiniReflectTypeTable() { return MovieTypeTable(); } - enum { + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_MAIN_CHARACTER_TYPE = 4, VT_MAIN_CHARACTER = 6, VT_CHARACTERS_TYPE = 8,