diff --git a/upb/message/test.cc b/upb/message/test.cc index 59c5516617..cd372a03c8 100644 --- a/upb/message/test.cc +++ b/upb/message/test.cc @@ -649,4 +649,10 @@ TEST(MessageTest, MapField) { // 0, 0); // } // +// TEST(FuzzTest, ExtensionWithoutExt) { +// DecodeEncodeArbitrarySchemaAndPayload({{"$ 3", "", "%#F"}, {}, "", {2, 1}}, +// std::string("\022\002\010\000", 4), 0, +// 0); +// } +// // end:google_only diff --git a/upb/mini_table/decode.c b/upb/mini_table/decode.c index fea9643a74..3c72c5b10c 100644 --- a/upb/mini_table/decode.c +++ b/upb/mini_table/decode.c @@ -665,64 +665,48 @@ static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) { d->table->size = UPB_ALIGN_UP(d->table->size, 8); } -static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, - size_t len) { - if (len < 2) { - upb_MtDecoder_ErrorFormat(d, "Invalid map encode length: %zu", len); - UPB_UNREACHABLE(); +static void upb_MtDecoder_ValidateEntryField(upb_MtDecoder* d, + const upb_MiniTableField* f, + int expected_num) { + const char* name = expected_num == 1 ? "key" : "val"; + if (f->number != expected_num) { + upb_MtDecoder_ErrorFormat(d, + "map %s did not have expected number (%d vs %d)", + name, expected_num, (int)f->number); } - const upb_EncodedType key_type = _upb_FromBase92(data[0]); - switch (key_type) { - case kUpb_EncodedType_Fixed32: - case kUpb_EncodedType_Fixed64: - case kUpb_EncodedType_SFixed32: - case kUpb_EncodedType_SFixed64: - case kUpb_EncodedType_Int32: - case kUpb_EncodedType_UInt32: - case kUpb_EncodedType_SInt32: - case kUpb_EncodedType_Int64: - case kUpb_EncodedType_UInt64: - case kUpb_EncodedType_SInt64: - case kUpb_EncodedType_Bool: - case kUpb_EncodedType_String: - break; - default: - upb_MtDecoder_ErrorFormat(d, "Invalid map key field type: %d", key_type); - UPB_UNREACHABLE(); + if (upb_IsRepeatedOrMap(f) || f->presence < 0) { + upb_MtDecoder_ErrorFormat( + d, "map %s cannot be repeated or map, or be in oneof", name); } - upb_MtDecoder_ParseMessage(d, data, len); - upb_MtDecoder_AssignHasbits(d->table); - - if (UPB_UNLIKELY(d->table->field_count != 2)) { - upb_MtDecoder_ErrorFormat(d, "%hu fields in map", d->table->field_count); - UPB_UNREACHABLE(); + uint32_t not_ok_types; + if (expected_num == 1) { + not_ok_types = (1 << kUpb_FieldType_Float) | (1 << kUpb_FieldType_Double) | + (1 << kUpb_FieldType_Message) | (1 << kUpb_FieldType_Group) | + (1 << kUpb_FieldType_Bytes) | (1 << kUpb_FieldType_Enum); + } else { + not_ok_types = 1 << kUpb_FieldType_Group; } - const int num0 = d->table->fields[0].number; - if (UPB_UNLIKELY(num0 != 1)) { - upb_MtDecoder_ErrorFormat(d, "field %d in map key", num0); - UPB_UNREACHABLE(); + if ((1 << upb_MiniTableField_Type(f)) & not_ok_types) { + upb_MtDecoder_ErrorFormat(d, "map %s cannot have type %d", name, + (int)f->descriptortype); } +} - const int num1 = d->table->fields[1].number; - if (UPB_UNLIKELY(num1 != 2)) { - upb_MtDecoder_ErrorFormat(d, "field %d in map val", num1); - UPB_UNREACHABLE(); - } +static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, + size_t len) { + upb_MtDecoder_ParseMessage(d, data, len); + upb_MtDecoder_AssignHasbits(d->table); - const int off0 = d->table->fields[0].offset; - if (UPB_UNLIKELY(off0 != kNoPresence && off0 != kHasbitPresence)) { - upb_MtDecoder_ErrorFormat(d, "bad offset %d in map key", off0); + if (UPB_UNLIKELY(d->table->field_count != 2)) { + upb_MtDecoder_ErrorFormat(d, "%hu fields in map", d->table->field_count); UPB_UNREACHABLE(); } - const int off1 = d->table->fields[1].offset; - if (UPB_UNLIKELY(off1 != kNoPresence && off1 != kHasbitPresence)) { - upb_MtDecoder_ErrorFormat(d, "bad offset %d in map val", off1); - UPB_UNREACHABLE(); - } + upb_MtDecoder_ValidateEntryField(d, &d->table->fields[0], 1); + upb_MtDecoder_ValidateEntryField(d, &d->table->fields[1], 2); // Map entries have a pre-determined layout, regardless of types. // NOTE: sync with mini_table/message_internal.h. diff --git a/upb/wire/decode.c b/upb/wire/decode.c index 543fd9ad2b..852052f9cd 100644 --- a/upb/wire/decode.c +++ b/upb/wire/decode.c @@ -31,6 +31,7 @@ #include "upb/collections/array_internal.h" #include "upb/collections/map_internal.h" +#include "upb/mini_table/common.h" #include "upb/mini_table/enum_internal.h" #include "upb/wire/common_internal.h" #include "upb/wire/decode_internal.h" @@ -581,8 +582,13 @@ static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr, upb_Map** map_p = UPB_PTR_AT(msg, field->offset, upb_Map*); upb_Map* map = *map_p; upb_MapEntry ent; + UPB_ASSERT(upb_MiniTableField_Type(field) == kUpb_FieldType_Message); const upb_MiniTable* entry = subs[field->submsg_index].submsg; + UPB_ASSERT(entry->field_count == 2); + UPB_ASSERT(!upb_IsRepeatedOrMap(&entry->fields[0])); + UPB_ASSERT(!upb_IsRepeatedOrMap(&entry->fields[1])); + if (!map) { map = _upb_Decoder_CreateMap(d, entry); *map_p = map;