Treat mismatched length-delimited repeated Group tags as unknown fields in upb.

PiperOrigin-RevId: 921438940
This commit is contained in:
Rachel Goldfinger 2026-05-26 06:49:51 -07:00 committed by Copybara-Service
parent 40825a1df7
commit 9040f41344
4 changed files with 49 additions and 3 deletions

View file

@ -855,7 +855,7 @@ static int _upb_Decoder_GetDelimitedOp(upb_Decoder* d, const upb_MiniTable* mt,
[kRepeatedBase + kUpb_FieldType_Fixed32] = OP_FIXPCK_LG2(2),
[kRepeatedBase + kUpb_FieldType_Bool] = OP_VARPCK_LG2(0),
[kRepeatedBase + kUpb_FieldType_String] = kUpb_DecodeOp_String,
[kRepeatedBase + kUpb_FieldType_Group] = kUpb_DecodeOp_SubMessage,
[kRepeatedBase + kUpb_FieldType_Group] = kUpb_DecodeOp_UnknownField,
[kRepeatedBase + kUpb_FieldType_Message] = kUpb_DecodeOp_SubMessage,
[kRepeatedBase + kUpb_FieldType_Bytes] = kUpb_DecodeOp_Bytes,
[kRepeatedBase + kUpb_FieldType_UInt32] = OP_VARPCK_LG2(2),

View file

@ -471,6 +471,43 @@ TEST(DecodeTest, MaxDepthPayloadParsesSuccessfully) {
}
}
TEST(DecodeTest, DecodeGroupFieldFromDelimitedWireFormatAsUnknown) {
upb::Arena mt_arena;
upb::Arena msg_arena;
// 1. Create Parent MiniTable containing a repeated Group field directly.
auto [parent_mt, parent_field] =
test::MiniTable::MakeSingleFieldTable<test::field_types::Group>(
5, kUpb_DecodeFast_Repeated, mt_arena.ptr());
// 2. Build length-delimited wire payload for Group field 5:
// Tag 5 Delimited = 42 (0x2a), length = 2, child field 1 = 123 ("\x08\x7b").
std::string payload("\x2a\x02\x08\x7b", 4);
// 3. Parse the payload into Parent Message.
upb_Message* parent_msg = upb_Message_New(parent_mt, msg_arena.ptr());
upb_DecodeStatus result =
upb_Decode(payload.data(), payload.size(), parent_msg, parent_mt, nullptr,
0, msg_arena.ptr());
// 4. Verify parsing succeeded cleanly.
ASSERT_EQ(result, kUpb_DecodeStatus_Ok) << upb_DecodeStatus_String(result);
// 5. Verify repeated Group field 5 was NOT populated as a known field.
const upb_Array* arr = upb_Message_GetArray(parent_msg, parent_field);
EXPECT_EQ(arr, nullptr);
// 6. Verify the wire payload was instead preserved inside the Unknown field
// set.
EXPECT_TRUE(upb_Message_HasUnknown(parent_msg));
uintptr_t iter = kUpb_Message_UnknownBegin;
upb_StringView data;
ASSERT_TRUE(upb_Message_NextUnknown(parent_msg, &data, &iter));
EXPECT_EQ(absl::string_view(data.data, data.size), payload);
EXPECT_FALSE(upb_Message_NextUnknown(parent_msg, &data, &iter));
}
} // namespace
} // namespace test

View file

@ -293,7 +293,16 @@ struct ClosedEnum {
}
};
// TODO: Group
struct Group {
using Value = std::string;
static constexpr upb_FieldType kFieldType = kUpb_FieldType_Group;
static constexpr absl::string_view kName = "Group";
static constexpr upb_DecodeFast_Type kFastType = kUpb_DecodeFast_Message;
static wire_types::WireValue WireValue(std::string value) {
return wire_types::Delimited(value);
}
};
} // namespace field_types

View file

@ -100,7 +100,7 @@ MiniTable::MakeSingleFieldTable(int field_number, upb_FieldType type,
ABSL_CHECK(ok);
}
#if UPB_FASTTABLE
if (field_number < (1 << 11)) {
if (field_number < (1 << 11) && type != kUpb_FieldType_Group) {
ABSL_CHECK_EQ(HasFastTableEntry(table, field),
UPB_DECODEFAST_ISENABLED(fast_type, cardinality,
kUpb_DecodeFast_Tag1Byte))