diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index 6908305535..bb5d06ffef 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -182,13 +182,15 @@ struct JsonPrinter { const uint8_t* prev_val, soffset_t vector_index) { switch (type.base_type) { case BASE_TYPE_UNION: { - // If this assert hits, you have an corrupt buffer, a union type field - // was not present or was out of range. - FLATBUFFERS_ASSERT(prev_val); + // Guard against corrupt buffer where union type field is missing or out of range. + if (!prev_val) return "corrupt buffer: missing union type field"; auto union_type_byte = *prev_val; // Always a uint8_t. if (vector_index >= 0) { auto type_vec = reinterpret_cast*>( prev_val + ReadScalar(prev_val)); + if (static_cast(vector_index) >= type_vec->size()) { + return "corrupt buffer: union type vector out of range"; + } union_type_byte = type_vec->Get(static_cast(vector_index)); } auto enum_val = type.enum_def->ReverseLookup(union_type_byte, true); diff --git a/tests/test.cpp b/tests/test.cpp index 5a43546f53..fc92b920f8 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -398,6 +398,23 @@ void UnionVectorTest(const std::string& tests_data_path) { "root_type Root;"), true); TEST_EQ(parser2.Parse("{a_type:Bool,a:{b:true}}"), true); + { + // Test corrupt buffer where union type field is missing in vtable (fixes #9033). + std::vector corrupt_buf( + parser2.builder_.GetBufferPointer(), + parser2.builder_.GetBufferPointer() + parser2.builder_.GetSize()); + auto root_pos = + flatbuffers::ReadScalar(corrupt_buf.data()); + auto vtable_soffset = flatbuffers::ReadScalar( + corrupt_buf.data() + root_pos); + auto vtable_pos = root_pos - vtable_soffset; + flatbuffers::WriteScalar( + corrupt_buf.data() + vtable_pos + 4, 0); + std::string corrupt_json; + auto corrupt_result = GenText(parser2, corrupt_buf.data(), &corrupt_json); + TEST_NOTNULL(corrupt_result); + TEST_EQ_STR(corrupt_result, "corrupt buffer: missing union type field"); + } } #endif