diff --git a/include/flatbuffers/verifier.h b/include/flatbuffers/verifier.h index 8d99dc64b..b6971c1dc 100644 --- a/include/flatbuffers/verifier.h +++ b/include/flatbuffers/verifier.h @@ -183,6 +183,14 @@ class Verifier FLATBUFFERS_FINAL_CLASS { // clang-format on } + template + bool VerifyNestedFlatBuffer(const Vector *buf, + const char *identifier) { + if (!buf) return true; + Verifier nested_verifier(buf->data(), buf->size()); + return nested_verifier.VerifyBuffer(identifier); + } + // Verify this whole buffer, starting with root type T. template bool VerifyBuffer() { return VerifyBuffer(nullptr); } diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index cb0ace650..39d09786f 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -1999,6 +1999,14 @@ class CppGenerator : public BaseGenerator { } default: break; } + + auto nfn = GetNestedFlatBufferName(field); + if (!nfn.empty()) { + code_.SetValue("CPP_NAME", nfn); + // FIXME: file_identifier. + code_ += "{{PRE}}verifier.VerifyNestedFlatBuffer<{{CPP_NAME}}>" + "({{NAME}}(), nullptr)\\"; + } break; } default: { @@ -2294,6 +2302,21 @@ class CppGenerator : public BaseGenerator { } } + std::string GetNestedFlatBufferName(const FieldDef &field) { + auto nested = field.attributes.Lookup("nested_flatbuffer"); + if (!nested) return ""; + std::string qualified_name = nested->constant; + auto nested_root = parser_.LookupStruct(nested->constant); + if (nested_root == nullptr) { + qualified_name = + parser_.current_namespace_->GetFullyQualifiedName(nested->constant); + nested_root = parser_.LookupStruct(qualified_name); + } + FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser. + (void)nested_root; + return TranslateNameSpace(qualified_name); + } + // Generate an accessor struct, builder structs & function for a table. void GenTable(const StructDef &struct_def) { if (opts_.generate_object_based_api) { GenNativeTable(struct_def); } @@ -2357,19 +2380,9 @@ class CppGenerator : public BaseGenerator { GenTableFieldGetter(field); if (opts_.mutable_buffer) { GenTableFieldSetter(field); } - auto nested = field.attributes.Lookup("nested_flatbuffer"); - if (nested) { - std::string qualified_name = nested->constant; - auto nested_root = parser_.LookupStruct(nested->constant); - if (nested_root == nullptr) { - qualified_name = parser_.current_namespace_->GetFullyQualifiedName( - nested->constant); - nested_root = parser_.LookupStruct(qualified_name); - } - FLATBUFFERS_ASSERT(nested_root); // Guaranteed to exist by parser. - (void)nested_root; - code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name)); - + auto nfn = GetNestedFlatBufferName(field); + if (!nfn.empty()) { + code_.SetValue("CPP_NAME", nfn); code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {"; code_ += " return " diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h index db45b604b..c2fdf76f8 100644 --- a/tests/cpp17/generated_cpp17/monster_test_generated.h +++ b/tests/cpp17/generated_cpp17/monster_test_generated.h @@ -1716,6 +1716,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyTable(enemy()) && VerifyOffset(verifier, VT_TESTNESTEDFLATBUFFER) && verifier.VerifyVector(testnestedflatbuffer()) && + verifier.VerifyNestedFlatBuffer(testnestedflatbuffer(), nullptr) && VerifyOffset(verifier, VT_TESTEMPTY) && verifier.VerifyTable(testempty()) && VerifyField(verifier, VT_TESTBOOL) && @@ -1773,6 +1774,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_SIGNED_ENUM) && VerifyOffset(verifier, VT_TESTREQUIREDNESTEDFLATBUFFER) && verifier.VerifyVector(testrequirednestedflatbuffer()) && + verifier.VerifyNestedFlatBuffer(testrequirednestedflatbuffer(), nullptr) && VerifyOffset(verifier, VT_SCALAR_KEY_SORTED_TABLES) && verifier.VerifyVector(scalar_key_sorted_tables()) && verifier.VerifyVectorOfTables(scalar_key_sorted_tables()) && diff --git a/tests/fuzzer/flatbuffers_monster_fuzzer.cc b/tests/fuzzer/flatbuffers_monster_fuzzer.cc index 727db0c4a..0b140f4df 100644 --- a/tests/fuzzer/flatbuffers_monster_fuzzer.cc +++ b/tests/fuzzer/flatbuffers_monster_fuzzer.cc @@ -82,7 +82,6 @@ std::string do_test(const flatbuffers::IDLOptions &opts, TEST_EQ(true, MyGame::Example::VerifyMonsterBuffer(verifier)); // FIXME: these are currently not being properly verified, so turn them off // for fuzzing until they are. - parser.opts.json_nested_flatbuffers = false; parser.opts.json_nested_flexbuffers = false; TEST_ASSERT( GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen)); diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index 0345d4b13..cec752341 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -1656,6 +1656,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { verifier.VerifyTable(enemy()) && VerifyOffset(verifier, VT_TESTNESTEDFLATBUFFER) && verifier.VerifyVector(testnestedflatbuffer()) && + verifier.VerifyNestedFlatBuffer(testnestedflatbuffer(), nullptr) && VerifyOffset(verifier, VT_TESTEMPTY) && verifier.VerifyTable(testempty()) && VerifyField(verifier, VT_TESTBOOL) && @@ -1713,6 +1714,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyField(verifier, VT_SIGNED_ENUM) && VerifyOffset(verifier, VT_TESTREQUIREDNESTEDFLATBUFFER) && verifier.VerifyVector(testrequirednestedflatbuffer()) && + verifier.VerifyNestedFlatBuffer(testrequirednestedflatbuffer(), nullptr) && VerifyOffset(verifier, VT_SCALAR_KEY_SORTED_TABLES) && verifier.VerifyVector(scalar_key_sorted_tables()) && verifier.VerifyVectorOfTables(scalar_key_sorted_tables()) &&