From ca828897c2a3db3539f07b3f5f4e54a916cfe991 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 30 Nov 2022 23:37:57 -0800 Subject: [PATCH] Fixed a bug with maps on 32-bit machines. We were not calculating proper offsets for upb_MapEntryData in cases where the compiler was run on a different word size than the runtime. PiperOrigin-RevId: 492114576 --- upb/mini_table/decode.c | 9 ++++++--- upb/mini_table/message_internal.h | 6 +++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/upb/mini_table/decode.c b/upb/mini_table/decode.c index ab798fba2a..a36d3c501c 100644 --- a/upb/mini_table/decode.c +++ b/upb/mini_table/decode.c @@ -696,9 +696,12 @@ static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data, upb_MtDecoder_AssignHasbits(d->table); // Map entries have a pre-determined layout, regardless of types. - d->fields[0].offset = offsetof(upb_MapEntryData, k); - d->fields[1].offset = offsetof(upb_MapEntryData, v); - d->table->size = UPB_ALIGN_UP(sizeof(upb_MapEntryData), 8); + // NOTE: sync with mini_table/message_internal.h. + const size_t kv_size = d->platform == kUpb_MiniTablePlatform_32Bit ? 8 : 16; + const size_t hasbit_size = 8; + d->fields[0].offset = hasbit_size; + d->fields[1].offset = hasbit_size + kv_size; + d->table->size = UPB_ALIGN_UP(hasbit_size + kv_size + kv_size, 8); // Map entries have a special bit set to signal it's a map entry, used in // upb_MiniTable_SetSubMessage() below. diff --git a/upb/mini_table/message_internal.h b/upb/mini_table/message_internal.h index 61e248f182..586e5fc807 100644 --- a/upb/mini_table/message_internal.h +++ b/upb/mini_table/message_internal.h @@ -86,8 +86,12 @@ struct upb_MiniTable { // // Note that users can and do create map entries directly, which will also use // this layout. +// +// NOTE: sync with mini_table/decode.c. typedef struct { - uint32_t hasbits; + // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here, + // and the uint64_t helps make this clear. + uint64_t hasbits; union { upb_StringView str; // For str/bytes. upb_value val; // For all other types.