diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index b1bdffa01..a346e4dfb 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -4383,23 +4383,24 @@ bool Type::Deserialize(const Parser& parser, const reflection::Type* type) { base_type = static_cast(type->base_type()); element = static_cast(type->element()); fixed_length = type->fixed_length(); - if (type->index() >= 0) { - bool is_series = type->base_type() == reflection::Vector || - type->base_type() == reflection::Array; - if (type->base_type() == reflection::Obj || - (is_series && type->element() == reflection::Obj)) { - if (static_cast(type->index()) < parser.structs_.vec.size()) { - struct_def = parser.structs_.vec[type->index()]; - struct_def->refcount++; - } else { - return false; - } + bool is_series = type->base_type() == reflection::Vector || + type->base_type() == reflection::Array; + bool is_object_type = + type->base_type() == reflection::Obj || + (is_series && type->element() == reflection::Obj); + if (is_object_type) { + if (type->index() < 0) return false; + if (static_cast(type->index()) < parser.structs_.vec.size()) { + struct_def = parser.structs_.vec[type->index()]; + struct_def->refcount++; } else { - if (static_cast(type->index()) < parser.enums_.vec.size()) { - enum_def = parser.enums_.vec[type->index()]; - } else { - return false; - } + return false; + } + } else if (type->index() >= 0) { + if (static_cast(type->index()) < parser.enums_.vec.size()) { + enum_def = parser.enums_.vec[type->index()]; + } else { + return false; } } return true; diff --git a/tests/monster_test.cpp b/tests/monster_test.cpp index 9b188afa2..b40a656da 100644 --- a/tests/monster_test.cpp +++ b/tests/monster_test.cpp @@ -23,6 +23,19 @@ static const auto infinity_d = std::numeric_limits::infinity(); using namespace MyGame::Example; +std::vector HexToBytes(const char* hex) { + auto hex_digit = [](char c) -> uint8_t { + return static_cast(c >= 'a' ? c - 'a' + 10 : c - '0'); + }; + + std::vector bytes; + for (const char* p = hex; *p; p += 2) { + bytes.push_back(static_cast((hex_digit(p[0]) << 4) | + hex_digit(p[1]))); + } + return bytes; +} + // example of how to build up a serialized buffer algorithmically: flatbuffers::DetachedBuffer CreateFlatBufferTest(std::string& buffer) { flatbuffers::FlatBufferBuilder builder; @@ -773,6 +786,21 @@ void TypeAliasesTest() { static_assert(is_samef64()), double>::value, "invalid type"); } +void DeserializeInvalidBinarySchemaTest() { + auto schema = HexToBytes( + "100000004246425308000c0004000800080000000c0000000400000000000000" + "01000000100000000c00140008000c00070010000c0000000000000140000000" + "0800000001000000010000000c00000008000e00040008000800000018000000" + "0c0000000000060008000700060000000000000f010000006600000001000000" + "53000000"); + + flatbuffers::Verifier verifier(schema.data(), schema.size()); + TEST_EQ(reflection::VerifySchemaBuffer(verifier), true); + + flatbuffers::Parser parser; + TEST_EQ(parser.Deserialize(schema.data(), schema.size()), false); +} + // example of parsing text straight into a buffer, and generating // text back from it: void ParseAndGenerateTextTest(const std::string& tests_data_path, bool binary) { @@ -806,6 +834,7 @@ void ParseAndGenerateTextTest(const std::string& tests_data_path, bool binary) { parser.Deserialize(reinterpret_cast(schemafile.c_str()), schemafile.size()), true); + DeserializeInvalidBinarySchemaTest(); } else { TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true); }