From 54f8b787cbdac587b1c9fec1ffe5a2ad2f0d61a2 Mon Sep 17 00:00:00 2001 From: xtrm0 Date: Wed, 12 Feb 2020 20:12:45 +0000 Subject: [PATCH] Fix memory leak on cpp object api (#5761) Previously UnPack would allocate data with new and assign it to a raw pointer. This behavior makes it possible for the pointer to be leaked in case of OOM. This commit defaults to use the user specified pointer (which needs to implement a move constructor, a .get() and a .release() operators), thus preventing these leaks. --- samples/monster_generated.h | 12 +++--- src/flatc.cpp | 5 +-- src/idl_gen_cpp.cpp | 13 ++++-- tests/arrays_test_generated.h | 6 +-- .../generated_cpp17/monster_test_generated.h | 42 +++++++++---------- tests/monster_extra_generated.h | 6 +-- tests/monster_test_generated.h | 42 +++++++++---------- .../namespace_test1_generated.h | 6 +-- .../namespace_test2_generated.h | 18 ++++---- tests/native_type_test_generated.h | 6 +-- tests/union_vector/union_vector_generated.h | 12 +++--- 11 files changed, 87 insertions(+), 81 deletions(-) diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 4a71b606f..6c5267c94 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -568,9 +568,9 @@ inline flatbuffers::Offset CreateWeaponDirect( flatbuffers::Offset CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new MonsterT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -621,9 +621,9 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder } inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new WeaponT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new WeaponT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Weapon::UnPackTo(WeaponT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/src/flatc.cpp b/src/flatc.cpp index 1be817539..c29db15e3 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -117,7 +117,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { " T::c_str(), T::length() and T::empty() must be supported.\n" " The custom type also needs to be constructible from std::string\n" " (see the --cpp-str-flex-ctor option to change this behavior).\n" - " --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n" + " --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n" " from Flatbuffers, but (char* + length).\n" " --cpp-std CPP_STD Generate a C++ code using features of selected C++ standard.\n" " Supported CPP_STD values:\n" @@ -353,8 +353,7 @@ int FlatCompiler::Compile(int argc, const char **argv) { } else if (arg == "--flexbuffers") { opts.use_flexbuffers = true; } else if (arg == "--cpp-std") { - if (++argi >= argc) - Error("missing C++ standard specification" + arg, true); + if (++argi >= argc) Error("missing C++ standard specification" + arg, true); opts.cpp_std = argv[argi]; } else { for (size_t i = 0; i < params_.num_generators; ++i) { diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index d9a335164..ea7dac16b 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -2705,14 +2705,21 @@ class CppGenerator : public BaseGenerator { code_.SetValue("STRUCT_NAME", Name(struct_def)); code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, opts_)); + auto native_name = + NativeName(WrapInNameSpace(struct_def), &struct_def, parser_.opts); + code_.SetValue("POINTER_TYPE", + GenTypeNativePtr(native_name, nullptr, false)); if (opts_.generate_object_based_api) { // Generate the X::UnPack() method. code_ += "inline " + TableUnPackSignature(struct_def, false, opts_) + " {"; - code_ += " auto _o = new {{NATIVE_NAME}}();"; - code_ += " UnPackTo(_o, _resolver);"; - code_ += " return _o;"; + + code_ += + " {{POINTER_TYPE}} _o = {{POINTER_TYPE}}(new {{NATIVE_NAME}}());"; + code_ += " UnPackTo(_o.get(), _resolver);"; + code_ += " return _o.release();"; + code_ += "}"; code_ += ""; diff --git a/tests/arrays_test_generated.h b/tests/arrays_test_generated.h index d533c74c1..30e788462 100644 --- a/tests/arrays_test_generated.h +++ b/tests/arrays_test_generated.h @@ -283,9 +283,9 @@ inline flatbuffers::Offset CreateArrayTable( flatbuffers::Offset CreateArrayTable(flatbuffers::FlatBufferBuilder &_fbb, const ArrayTableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline ArrayTableT *ArrayTable::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new ArrayTableT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new ArrayTableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void ArrayTable::UnPackTo(ArrayTableT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h index 00df82570..d32d84a4a 100644 --- a/tests/cpp17/generated_cpp17/monster_test_generated.h +++ b/tests/cpp17/generated_cpp17/monster_test_generated.h @@ -2193,9 +2193,9 @@ flatbuffers::Offset CreateTypeAliases(flatbuffers::FlatBufferBuilde } // namespace Example inline InParentNamespaceT *InParentNamespace::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new InParentNamespaceT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new InParentNamespaceT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void InParentNamespace::UnPackTo(InParentNamespaceT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2218,9 +2218,9 @@ inline flatbuffers::Offset CreateInParentNamespace(flatbuffer namespace Example2 { inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new MonsterT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2245,9 +2245,9 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder namespace Example { inline TestSimpleTableWithEnumT *TestSimpleTableWithEnum::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TestSimpleTableWithEnumT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new TestSimpleTableWithEnumT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TestSimpleTableWithEnum::UnPackTo(TestSimpleTableWithEnumT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2271,9 +2271,9 @@ inline flatbuffers::Offset CreateTestSimpleTableWithEnu } inline StatT *Stat::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new StatT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new StatT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Stat::UnPackTo(StatT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2303,9 +2303,9 @@ inline flatbuffers::Offset CreateStat(flatbuffers::FlatBufferBuilder &_fbb } inline ReferrableT *Referrable::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new ReferrableT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new ReferrableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Referrable::UnPackTo(ReferrableT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2329,9 +2329,9 @@ inline flatbuffers::Offset CreateReferrable(flatbuffers::FlatBufferB } inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new MonsterT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2503,9 +2503,9 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder } inline TypeAliasesT *TypeAliases::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TypeAliasesT(); - UnPackTo(_o, _resolver); - return _o; + std::unique_ptr _o = std::unique_ptr(new TypeAliasesT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TypeAliases::UnPackTo(TypeAliasesT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/monster_extra_generated.h b/tests/monster_extra_generated.h index 1db81da90..3b4ee27ad 100644 --- a/tests/monster_extra_generated.h +++ b/tests/monster_extra_generated.h @@ -262,9 +262,9 @@ inline flatbuffers::Offset CreateMonsterExtraDirect( flatbuffers::Offset CreateMonsterExtra(flatbuffers::FlatBufferBuilder &_fbb, const MonsterExtraT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline MonsterExtraT *MonsterExtra::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterExtraT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new MonsterExtraT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void MonsterExtra::UnPackTo(MonsterExtraT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index f5cf6f817..2808dc708 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -2428,9 +2428,9 @@ flatbuffers::Offset CreateTypeAliases(flatbuffers::FlatBufferBuilde } // namespace Example inline InParentNamespaceT *InParentNamespace::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new InParentNamespaceT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new InParentNamespaceT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void InParentNamespace::UnPackTo(InParentNamespaceT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2453,9 +2453,9 @@ inline flatbuffers::Offset CreateInParentNamespace(flatbuffer namespace Example2 { inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new MonsterT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2480,9 +2480,9 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder namespace Example { inline TestSimpleTableWithEnumT *TestSimpleTableWithEnum::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TestSimpleTableWithEnumT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new TestSimpleTableWithEnumT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TestSimpleTableWithEnum::UnPackTo(TestSimpleTableWithEnumT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2506,9 +2506,9 @@ inline flatbuffers::Offset CreateTestSimpleTableWithEnu } inline StatT *Stat::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new StatT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new StatT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Stat::UnPackTo(StatT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2538,9 +2538,9 @@ inline flatbuffers::Offset CreateStat(flatbuffers::FlatBufferBuilder &_fbb } inline ReferrableT *Referrable::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new ReferrableT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new ReferrableT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Referrable::UnPackTo(ReferrableT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2564,9 +2564,9 @@ inline flatbuffers::Offset CreateReferrable(flatbuffers::FlatBufferB } inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MonsterT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new MonsterT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -2738,9 +2738,9 @@ inline flatbuffers::Offset CreateMonster(flatbuffers::FlatBufferBuilder } inline TypeAliasesT *TypeAliases::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TypeAliasesT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new TypeAliasesT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TypeAliases::UnPackTo(TypeAliasesT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h index 397e9d137..feae671a0 100644 --- a/tests/namespace_test/namespace_test1_generated.h +++ b/tests/namespace_test/namespace_test1_generated.h @@ -172,9 +172,9 @@ inline flatbuffers::Offset CreateTableInNestedNS( flatbuffers::Offset CreateTableInNestedNS(flatbuffers::FlatBufferBuilder &_fbb, const TableInNestedNST *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline TableInNestedNST *TableInNestedNS::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TableInNestedNST(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new TableInNestedNST()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TableInNestedNS::UnPackTo(TableInNestedNST *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index 2d9e5cf56..bb6844b88 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -329,9 +329,9 @@ inline flatbuffers::Offset CreateSecondTableInA( flatbuffers::Offset CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb, const SecondTableInAT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline TableInFirstNST *TableInFirstNS::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TableInFirstNST(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new TableInFirstNST()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TableInFirstNS::UnPackTo(TableInFirstNST *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -365,9 +365,9 @@ inline flatbuffers::Offset CreateTableInFirstNS(flatbuffers::Fla namespace NamespaceC { inline TableInCT *TableInC::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new TableInCT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new TableInCT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void TableInC::UnPackTo(TableInCT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -398,9 +398,9 @@ inline flatbuffers::Offset CreateTableInC(flatbuffers::FlatBufferBuild namespace NamespaceA { inline SecondTableInAT *SecondTableInA::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new SecondTableInAT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new SecondTableInAT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void SecondTableInA::UnPackTo(SecondTableInAT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/native_type_test_generated.h b/tests/native_type_test_generated.h index 4e3fc4cec..911142641 100644 --- a/tests/native_type_test_generated.h +++ b/tests/native_type_test_generated.h @@ -131,9 +131,9 @@ inline flatbuffers::Offset CreateApplicationDataDirect( flatbuffers::Offset CreateApplicationData(flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline ApplicationDataT *ApplicationData::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new ApplicationDataT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new ApplicationDataT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void ApplicationData::UnPackTo(ApplicationDataT *_o, const flatbuffers::resolver_function_t *_resolver) const { diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h index b38d757f6..d65c77cd8 100644 --- a/tests/union_vector/union_vector_generated.h +++ b/tests/union_vector/union_vector_generated.h @@ -480,9 +480,9 @@ inline flatbuffers::Offset CreateMovieDirect( flatbuffers::Offset CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); inline AttackerT *Attacker::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new AttackerT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new AttackerT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Attacker::UnPackTo(AttackerT *_o, const flatbuffers::resolver_function_t *_resolver) const { @@ -506,9 +506,9 @@ inline flatbuffers::Offset CreateAttacker(flatbuffers::FlatBufferBuild } inline MovieT *Movie::UnPack(const flatbuffers::resolver_function_t *_resolver) const { - auto _o = new MovieT(); - UnPackTo(_o, _resolver); - return _o; + flatbuffers::unique_ptr _o = flatbuffers::unique_ptr(new MovieT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); } inline void Movie::UnPackTo(MovieT *_o, const flatbuffers::resolver_function_t *_resolver) const {