1 /*
2 * Copyright (c) 2009-2021, Google LLC
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Google LLC nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include "upb/mini_table/decode.h"
29
30 #include <inttypes.h>
31 #include <stdlib.h>
32
33 #include "upb/base/log2.h"
34 #include "upb/base/string_view.h"
35 #include "upb/mem/arena.h"
36 #include "upb/mini_table/common.h"
37 #include "upb/mini_table/common_internal.h"
38 #include "upb/mini_table/enum_internal.h"
39 #include "upb/mini_table/extension_internal.h"
40
41 // Must be last.
42 #include "upb/port/def.inc"
43
44 // Note: we sort by this number when calculating layout order.
45 typedef enum {
46 kUpb_LayoutItemType_OneofCase, // Oneof case.
47 kUpb_LayoutItemType_OneofField, // Oneof field data.
48 kUpb_LayoutItemType_Field, // Non-oneof field data.
49
50 kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field,
51 } upb_LayoutItemType;
52
53 #define kUpb_LayoutItem_IndexSentinel ((uint16_t)-1)
54
55 typedef struct {
56 // Index of the corresponding field. When this is a oneof field, the field's
57 // offset will be the index of the next field in a linked list.
58 uint16_t field_index;
59 uint16_t offset;
60 upb_FieldRep rep;
61 upb_LayoutItemType type;
62 } upb_LayoutItem;
63
64 typedef struct {
65 upb_LayoutItem* data;
66 size_t size;
67 size_t capacity;
68 } upb_LayoutItemVector;
69
70 typedef struct {
71 const char* end;
72 upb_MiniTable* table;
73 upb_MiniTableField* fields;
74 upb_MiniTablePlatform platform;
75 upb_LayoutItemVector vec;
76 upb_Arena* arena;
77 upb_Status* status;
78
79 // When building enums.
80 upb_MiniTableEnum* enum_table;
81 uint32_t enum_value_count;
82 uint32_t enum_data_count;
83 uint32_t enum_data_capacity;
84
85 jmp_buf err;
86 } upb_MtDecoder;
87
88 UPB_PRINTF(2, 3)
upb_MtDecoder_ErrorFormat(upb_MtDecoder * d,const char * fmt,...)89 UPB_NORETURN static void upb_MtDecoder_ErrorFormat(upb_MtDecoder* d,
90 const char* fmt, ...) {
91 if (d->status) {
92 va_list argp;
93 upb_Status_SetErrorMessage(d->status, "Error building mini table: ");
94 va_start(argp, fmt);
95 upb_Status_VAppendErrorFormat(d->status, fmt, argp);
96 va_end(argp);
97 }
98 UPB_LONGJMP(d->err, 1);
99 }
100
upb_MtDecoder_CheckOutOfMemory(upb_MtDecoder * d,const void * ptr)101 static void upb_MtDecoder_CheckOutOfMemory(upb_MtDecoder* d, const void* ptr) {
102 if (!ptr) upb_MtDecoder_ErrorFormat(d, "Out of memory");
103 }
104
105 // In each field's offset, we temporarily store a presence classifier:
106 enum PresenceClass {
107 kNoPresence = 0,
108 kHasbitPresence = 1,
109 kRequiredPresence = 2,
110 kOneofBase = 3,
111 // Negative values refer to a specific oneof with that number. Positive
112 // values >= kOneofBase indicate that this field is in a oneof, and specify
113 // the next field in this oneof's linked list.
114 };
115
upb_MiniTable_DecodeBase92Varint(upb_MtDecoder * d,const char * ptr,char first_ch,uint8_t min,uint8_t max,uint32_t * out_val)116 static const char* upb_MiniTable_DecodeBase92Varint(upb_MtDecoder* d,
117 const char* ptr,
118 char first_ch, uint8_t min,
119 uint8_t max,
120 uint32_t* out_val) {
121 uint32_t val = 0;
122 uint32_t shift = 0;
123 const int bits_per_char =
124 upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min));
125 char ch = first_ch;
126 while (1) {
127 uint32_t bits = _upb_FromBase92(ch) - _upb_FromBase92(min);
128 val |= bits << shift;
129 if (ptr == d->end || *ptr < min || max < *ptr) {
130 *out_val = val;
131 return ptr;
132 }
133 ch = *ptr++;
134 shift += bits_per_char;
135 if (shift >= 32) upb_MtDecoder_ErrorFormat(d, "Overlong varint");
136 }
137 }
138
upb_MiniTable_HasSub(upb_MiniTableField * field,uint64_t msg_modifiers)139 static bool upb_MiniTable_HasSub(upb_MiniTableField* field,
140 uint64_t msg_modifiers) {
141 switch (field->UPB_PRIVATE(descriptortype)) {
142 case kUpb_FieldType_Message:
143 case kUpb_FieldType_Group:
144 case kUpb_FieldType_Enum:
145 return true;
146 case kUpb_FieldType_String:
147 if (!(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) {
148 field->UPB_PRIVATE(descriptortype) = kUpb_FieldType_Bytes;
149 field->mode |= kUpb_LabelFlags_IsAlternate;
150 }
151 return false;
152 default:
153 return false;
154 }
155 }
156
upb_MtDecoder_FieldIsPackable(upb_MiniTableField * field)157 static bool upb_MtDecoder_FieldIsPackable(upb_MiniTableField* field) {
158 return (field->mode & kUpb_FieldMode_Array) &&
159 upb_FieldType_IsPackable(field->UPB_PRIVATE(descriptortype));
160 }
161
upb_MiniTable_SetTypeAndSub(upb_MiniTableField * field,upb_FieldType type,uint32_t * sub_count,uint64_t msg_modifiers,bool is_proto3_enum)162 static void upb_MiniTable_SetTypeAndSub(upb_MiniTableField* field,
163 upb_FieldType type, uint32_t* sub_count,
164 uint64_t msg_modifiers,
165 bool is_proto3_enum) {
166 field->UPB_PRIVATE(descriptortype) = type;
167
168 if (is_proto3_enum) {
169 UPB_ASSERT(field->UPB_PRIVATE(descriptortype) == kUpb_FieldType_Enum);
170 field->UPB_PRIVATE(descriptortype) = kUpb_FieldType_Int32;
171 field->mode |= kUpb_LabelFlags_IsAlternate;
172 }
173
174 if (upb_MiniTable_HasSub(field, msg_modifiers)) {
175 field->UPB_PRIVATE(submsg_index) = sub_count ? (*sub_count)++ : 0;
176 } else {
177 field->UPB_PRIVATE(submsg_index) = kUpb_NoSub;
178 }
179
180 if (upb_MtDecoder_FieldIsPackable(field) &&
181 (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) {
182 field->mode |= kUpb_LabelFlags_IsPacked;
183 }
184 }
185
186 static const char kUpb_EncodedToType[] = {
187 [kUpb_EncodedType_Double] = kUpb_FieldType_Double,
188 [kUpb_EncodedType_Float] = kUpb_FieldType_Float,
189 [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64,
190 [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64,
191 [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32,
192 [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64,
193 [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32,
194 [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool,
195 [kUpb_EncodedType_String] = kUpb_FieldType_String,
196 [kUpb_EncodedType_Group] = kUpb_FieldType_Group,
197 [kUpb_EncodedType_Message] = kUpb_FieldType_Message,
198 [kUpb_EncodedType_Bytes] = kUpb_FieldType_Bytes,
199 [kUpb_EncodedType_UInt32] = kUpb_FieldType_UInt32,
200 [kUpb_EncodedType_OpenEnum] = kUpb_FieldType_Enum,
201 [kUpb_EncodedType_SFixed32] = kUpb_FieldType_SFixed32,
202 [kUpb_EncodedType_SFixed64] = kUpb_FieldType_SFixed64,
203 [kUpb_EncodedType_SInt32] = kUpb_FieldType_SInt32,
204 [kUpb_EncodedType_SInt64] = kUpb_FieldType_SInt64,
205 [kUpb_EncodedType_ClosedEnum] = kUpb_FieldType_Enum,
206 };
207
upb_MiniTable_SetField(upb_MtDecoder * d,uint8_t ch,upb_MiniTableField * field,uint64_t msg_modifiers,uint32_t * sub_count)208 static void upb_MiniTable_SetField(upb_MtDecoder* d, uint8_t ch,
209 upb_MiniTableField* field,
210 uint64_t msg_modifiers,
211 uint32_t* sub_count) {
212 static const char kUpb_EncodedToFieldRep[] = {
213 [kUpb_EncodedType_Double] = kUpb_FieldRep_8Byte,
214 [kUpb_EncodedType_Float] = kUpb_FieldRep_4Byte,
215 [kUpb_EncodedType_Int64] = kUpb_FieldRep_8Byte,
216 [kUpb_EncodedType_UInt64] = kUpb_FieldRep_8Byte,
217 [kUpb_EncodedType_Int32] = kUpb_FieldRep_4Byte,
218 [kUpb_EncodedType_Fixed64] = kUpb_FieldRep_8Byte,
219 [kUpb_EncodedType_Fixed32] = kUpb_FieldRep_4Byte,
220 [kUpb_EncodedType_Bool] = kUpb_FieldRep_1Byte,
221 [kUpb_EncodedType_String] = kUpb_FieldRep_StringView,
222 [kUpb_EncodedType_Bytes] = kUpb_FieldRep_StringView,
223 [kUpb_EncodedType_UInt32] = kUpb_FieldRep_4Byte,
224 [kUpb_EncodedType_OpenEnum] = kUpb_FieldRep_4Byte,
225 [kUpb_EncodedType_SFixed32] = kUpb_FieldRep_4Byte,
226 [kUpb_EncodedType_SFixed64] = kUpb_FieldRep_8Byte,
227 [kUpb_EncodedType_SInt32] = kUpb_FieldRep_4Byte,
228 [kUpb_EncodedType_SInt64] = kUpb_FieldRep_8Byte,
229 [kUpb_EncodedType_ClosedEnum] = kUpb_FieldRep_4Byte,
230 };
231
232 char pointer_rep = d->platform == kUpb_MiniTablePlatform_32Bit
233 ? kUpb_FieldRep_4Byte
234 : kUpb_FieldRep_8Byte;
235
236 int8_t type = _upb_FromBase92(ch);
237 if (ch >= _upb_ToBase92(kUpb_EncodedType_RepeatedBase)) {
238 type -= kUpb_EncodedType_RepeatedBase;
239 field->mode = kUpb_FieldMode_Array;
240 field->mode |= pointer_rep << kUpb_FieldRep_Shift;
241 field->offset = kNoPresence;
242 } else {
243 field->mode = kUpb_FieldMode_Scalar;
244 field->offset = kHasbitPresence;
245 if (type == kUpb_EncodedType_Group || type == kUpb_EncodedType_Message) {
246 field->mode |= pointer_rep << kUpb_FieldRep_Shift;
247 } else if ((unsigned long)type >= sizeof(kUpb_EncodedToFieldRep)) {
248 upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
249 UPB_UNREACHABLE();
250 } else {
251 field->mode |= kUpb_EncodedToFieldRep[type] << kUpb_FieldRep_Shift;
252 }
253 }
254 if ((unsigned long)type >= sizeof(kUpb_EncodedToType)) {
255 upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
256 UPB_UNREACHABLE();
257 }
258 upb_MiniTable_SetTypeAndSub(field, kUpb_EncodedToType[type], sub_count,
259 msg_modifiers, type == kUpb_EncodedType_OpenEnum);
260 }
261
upb_MtDecoder_ModifyField(upb_MtDecoder * d,uint32_t message_modifiers,uint32_t field_modifiers,upb_MiniTableField * field)262 static void upb_MtDecoder_ModifyField(upb_MtDecoder* d,
263 uint32_t message_modifiers,
264 uint32_t field_modifiers,
265 upb_MiniTableField* field) {
266 if (field_modifiers & kUpb_EncodedFieldModifier_FlipPacked) {
267 if (!upb_MtDecoder_FieldIsPackable(field)) {
268 upb_MtDecoder_ErrorFormat(
269 d, "Cannot flip packed on unpackable field %" PRIu32, field->number);
270 UPB_UNREACHABLE();
271 }
272 field->mode ^= kUpb_LabelFlags_IsPacked;
273 }
274
275 bool singular = field_modifiers & kUpb_EncodedFieldModifier_IsProto3Singular;
276 bool required = field_modifiers & kUpb_EncodedFieldModifier_IsRequired;
277
278 // Validate.
279 if ((singular || required) && field->offset != kHasbitPresence) {
280 upb_MtDecoder_ErrorFormat(
281 d, "Invalid modifier(s) for repeated field %" PRIu32, field->number);
282 UPB_UNREACHABLE();
283 }
284 if (singular && required) {
285 upb_MtDecoder_ErrorFormat(
286 d, "Field %" PRIu32 " cannot be both singular and required",
287 field->number);
288 UPB_UNREACHABLE();
289 }
290
291 if (singular) field->offset = kNoPresence;
292 if (required) {
293 field->offset = kRequiredPresence;
294 }
295 }
296
upb_MtDecoder_PushItem(upb_MtDecoder * d,upb_LayoutItem item)297 static void upb_MtDecoder_PushItem(upb_MtDecoder* d, upb_LayoutItem item) {
298 if (d->vec.size == d->vec.capacity) {
299 size_t new_cap = UPB_MAX(8, d->vec.size * 2);
300 d->vec.data = realloc(d->vec.data, new_cap * sizeof(*d->vec.data));
301 upb_MtDecoder_CheckOutOfMemory(d, d->vec.data);
302 d->vec.capacity = new_cap;
303 }
304 d->vec.data[d->vec.size++] = item;
305 }
306
upb_MtDecoder_PushOneof(upb_MtDecoder * d,upb_LayoutItem item)307 static void upb_MtDecoder_PushOneof(upb_MtDecoder* d, upb_LayoutItem item) {
308 if (item.field_index == kUpb_LayoutItem_IndexSentinel) {
309 upb_MtDecoder_ErrorFormat(d, "Empty oneof");
310 UPB_UNREACHABLE();
311 }
312 item.field_index -= kOneofBase;
313
314 // Push oneof data.
315 item.type = kUpb_LayoutItemType_OneofField;
316 upb_MtDecoder_PushItem(d, item);
317
318 // Push oneof case.
319 item.rep = kUpb_FieldRep_4Byte; // Field Number.
320 item.type = kUpb_LayoutItemType_OneofCase;
321 upb_MtDecoder_PushItem(d, item);
322 }
323
upb_MtDecoder_SizeOfRep(upb_FieldRep rep,upb_MiniTablePlatform platform)324 size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
325 upb_MiniTablePlatform platform) {
326 static const uint8_t kRepToSize32[] = {
327 [kUpb_FieldRep_1Byte] = 1,
328 [kUpb_FieldRep_4Byte] = 4,
329 [kUpb_FieldRep_StringView] = 8,
330 [kUpb_FieldRep_8Byte] = 8,
331 };
332 static const uint8_t kRepToSize64[] = {
333 [kUpb_FieldRep_1Byte] = 1,
334 [kUpb_FieldRep_4Byte] = 4,
335 [kUpb_FieldRep_StringView] = 16,
336 [kUpb_FieldRep_8Byte] = 8,
337 };
338 UPB_ASSERT(sizeof(upb_StringView) ==
339 UPB_SIZE(kRepToSize32, kRepToSize64)[kUpb_FieldRep_StringView]);
340 return platform == kUpb_MiniTablePlatform_32Bit ? kRepToSize32[rep]
341 : kRepToSize64[rep];
342 }
343
upb_MtDecoder_AlignOfRep(upb_FieldRep rep,upb_MiniTablePlatform platform)344 size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
345 upb_MiniTablePlatform platform) {
346 static const uint8_t kRepToAlign32[] = {
347 [kUpb_FieldRep_1Byte] = 1,
348 [kUpb_FieldRep_4Byte] = 4,
349 [kUpb_FieldRep_StringView] = 4,
350 [kUpb_FieldRep_8Byte] = 8,
351 };
352 static const uint8_t kRepToAlign64[] = {
353 [kUpb_FieldRep_1Byte] = 1,
354 [kUpb_FieldRep_4Byte] = 4,
355 [kUpb_FieldRep_StringView] = 8,
356 [kUpb_FieldRep_8Byte] = 8,
357 };
358 UPB_ASSERT(UPB_ALIGN_OF(upb_StringView) ==
359 UPB_SIZE(kRepToAlign32, kRepToAlign64)[kUpb_FieldRep_StringView]);
360 return platform == kUpb_MiniTablePlatform_32Bit ? kRepToAlign32[rep]
361 : kRepToAlign64[rep];
362 }
363
upb_MtDecoder_DecodeOneofField(upb_MtDecoder * d,const char * ptr,char first_ch,upb_LayoutItem * item)364 static const char* upb_MtDecoder_DecodeOneofField(upb_MtDecoder* d,
365 const char* ptr,
366 char first_ch,
367 upb_LayoutItem* item) {
368 uint32_t field_num;
369 ptr = upb_MiniTable_DecodeBase92Varint(
370 d, ptr, first_ch, kUpb_EncodedValue_MinOneofField,
371 kUpb_EncodedValue_MaxOneofField, &field_num);
372 upb_MiniTableField* f =
373 (void*)upb_MiniTable_FindFieldByNumber(d->table, field_num);
374
375 if (!f) {
376 upb_MtDecoder_ErrorFormat(d,
377 "Couldn't add field number %" PRIu32
378 " to oneof, no such field number.",
379 field_num);
380 UPB_UNREACHABLE();
381 }
382 if (f->offset != kHasbitPresence) {
383 upb_MtDecoder_ErrorFormat(
384 d,
385 "Cannot add repeated, required, or singular field %" PRIu32
386 " to oneof.",
387 field_num);
388 UPB_UNREACHABLE();
389 }
390
391 // Oneof storage must be large enough to accommodate the largest member.
392 int rep = f->mode >> kUpb_FieldRep_Shift;
393 if (upb_MtDecoder_SizeOfRep(rep, d->platform) >
394 upb_MtDecoder_SizeOfRep(item->rep, d->platform)) {
395 item->rep = rep;
396 }
397 // Prepend this field to the linked list.
398 f->offset = item->field_index;
399 item->field_index = (f - d->fields) + kOneofBase;
400 return ptr;
401 }
402
upb_MtDecoder_DecodeOneofs(upb_MtDecoder * d,const char * ptr)403 static const char* upb_MtDecoder_DecodeOneofs(upb_MtDecoder* d,
404 const char* ptr) {
405 upb_LayoutItem item = {.rep = 0,
406 .field_index = kUpb_LayoutItem_IndexSentinel};
407 while (ptr < d->end) {
408 char ch = *ptr++;
409 if (ch == kUpb_EncodedValue_FieldSeparator) {
410 // Field separator, no action needed.
411 } else if (ch == kUpb_EncodedValue_OneofSeparator) {
412 // End of oneof.
413 upb_MtDecoder_PushOneof(d, item);
414 item.field_index = kUpb_LayoutItem_IndexSentinel; // Move to next oneof.
415 } else {
416 ptr = upb_MtDecoder_DecodeOneofField(d, ptr, ch, &item);
417 }
418 }
419
420 // Push final oneof.
421 upb_MtDecoder_PushOneof(d, item);
422 return ptr;
423 }
424
upb_MtDecoder_ParseModifier(upb_MtDecoder * d,const char * ptr,char first_ch,upb_MiniTableField * last_field,uint64_t * msg_modifiers)425 static const char* upb_MtDecoder_ParseModifier(upb_MtDecoder* d,
426 const char* ptr, char first_ch,
427 upb_MiniTableField* last_field,
428 uint64_t* msg_modifiers) {
429 uint32_t mod;
430 ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, first_ch,
431 kUpb_EncodedValue_MinModifier,
432 kUpb_EncodedValue_MaxModifier, &mod);
433 if (last_field) {
434 upb_MtDecoder_ModifyField(d, *msg_modifiers, mod, last_field);
435 } else {
436 if (!d->table) {
437 upb_MtDecoder_ErrorFormat(d, "Extensions cannot have message modifiers");
438 UPB_UNREACHABLE();
439 }
440 *msg_modifiers = mod;
441 }
442
443 return ptr;
444 }
445
upb_MtDecoder_AllocateSubs(upb_MtDecoder * d,uint32_t sub_count)446 static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, uint32_t sub_count) {
447 size_t subs_bytes = sizeof(*d->table->subs) * sub_count;
448 void* subs = upb_Arena_Malloc(d->arena, subs_bytes);
449 memset(subs, 0, subs_bytes);
450 d->table->subs = subs;
451 upb_MtDecoder_CheckOutOfMemory(d, d->table->subs);
452 }
453
upb_MtDecoder_Parse(upb_MtDecoder * d,const char * ptr,size_t len,void * fields,size_t field_size,uint16_t * field_count,uint32_t * sub_count)454 static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr,
455 size_t len, void* fields,
456 size_t field_size, uint16_t* field_count,
457 uint32_t* sub_count) {
458 uint64_t msg_modifiers = 0;
459 uint32_t last_field_number = 0;
460 upb_MiniTableField* last_field = NULL;
461 bool need_dense_below = d->table != NULL;
462
463 d->end = UPB_PTRADD(ptr, len);
464
465 while (ptr < d->end) {
466 char ch = *ptr++;
467 if (ch <= kUpb_EncodedValue_MaxField) {
468 if (!d->table && last_field) {
469 // For extensions, consume only a single field and then return.
470 return --ptr;
471 }
472 upb_MiniTableField* field = fields;
473 *field_count += 1;
474 fields = (char*)fields + field_size;
475 field->number = ++last_field_number;
476 last_field = field;
477 upb_MiniTable_SetField(d, ch, field, msg_modifiers, sub_count);
478 } else if (kUpb_EncodedValue_MinModifier <= ch &&
479 ch <= kUpb_EncodedValue_MaxModifier) {
480 ptr = upb_MtDecoder_ParseModifier(d, ptr, ch, last_field, &msg_modifiers);
481 if (msg_modifiers & kUpb_MessageModifier_IsExtendable) {
482 d->table->ext |= kUpb_ExtMode_Extendable;
483 }
484 } else if (ch == kUpb_EncodedValue_End) {
485 if (!d->table) {
486 upb_MtDecoder_ErrorFormat(d, "Extensions cannot have oneofs.");
487 UPB_UNREACHABLE();
488 }
489 ptr = upb_MtDecoder_DecodeOneofs(d, ptr);
490 } else if (kUpb_EncodedValue_MinSkip <= ch &&
491 ch <= kUpb_EncodedValue_MaxSkip) {
492 if (need_dense_below) {
493 d->table->dense_below = d->table->field_count;
494 need_dense_below = false;
495 }
496 uint32_t skip;
497 ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, ch,
498 kUpb_EncodedValue_MinSkip,
499 kUpb_EncodedValue_MaxSkip, &skip);
500 last_field_number += skip;
501 last_field_number--; // Next field seen will increment.
502 } else {
503 upb_MtDecoder_ErrorFormat(d, "Invalid char: %c", ch);
504 UPB_UNREACHABLE();
505 }
506 }
507
508 if (need_dense_below) {
509 d->table->dense_below = d->table->field_count;
510 }
511
512 return ptr;
513 }
514
upb_MtDecoder_ParseMessage(upb_MtDecoder * d,const char * data,size_t len)515 static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
516 size_t len) {
517 // Buffer length is an upper bound on the number of fields. We will return
518 // what we don't use.
519 d->fields = upb_Arena_Malloc(d->arena, sizeof(*d->fields) * len);
520 upb_MtDecoder_CheckOutOfMemory(d, d->fields);
521
522 uint32_t sub_count = 0;
523 d->table->field_count = 0;
524 d->table->fields = d->fields;
525 upb_MtDecoder_Parse(d, data, len, d->fields, sizeof(*d->fields),
526 &d->table->field_count, &sub_count);
527
528 upb_Arena_ShrinkLast(d->arena, d->fields, sizeof(*d->fields) * len,
529 sizeof(*d->fields) * d->table->field_count);
530 d->table->fields = d->fields;
531 upb_MtDecoder_AllocateSubs(d, sub_count);
532 }
533
upb_MtDecoder_CompareFields(const void * _a,const void * _b)534 int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
535 const upb_LayoutItem* a = _a;
536 const upb_LayoutItem* b = _b;
537 // Currently we just sort by:
538 // 1. rep (smallest fields first)
539 // 2. type (oneof cases first)
540 // 2. field_index (smallest numbers first)
541 // The main goal of this is to reduce space lost to padding.
542 // Later we may have more subtle reasons to prefer a different ordering.
543 const int rep_bits = upb_Log2Ceiling(kUpb_FieldRep_Max);
544 const int type_bits = upb_Log2Ceiling(kUpb_LayoutItemType_Max);
545 const int idx_bits = (sizeof(a->field_index) * 8);
546 UPB_ASSERT(idx_bits + rep_bits + type_bits < 32);
547 #define UPB_COMBINE(rep, ty, idx) (((rep << type_bits) | ty) << idx_bits) | idx
548 uint32_t a_packed = UPB_COMBINE(a->rep, a->type, a->field_index);
549 uint32_t b_packed = UPB_COMBINE(b->rep, b->type, b->field_index);
550 assert(a_packed != b_packed);
551 #undef UPB_COMBINE
552 return a_packed < b_packed ? -1 : 1;
553 }
554
upb_MtDecoder_SortLayoutItems(upb_MtDecoder * d)555 static bool upb_MtDecoder_SortLayoutItems(upb_MtDecoder* d) {
556 // Add items for all non-oneof fields (oneofs were already added).
557 int n = d->table->field_count;
558 for (int i = 0; i < n; i++) {
559 upb_MiniTableField* f = &d->fields[i];
560 if (f->offset >= kOneofBase) continue;
561 upb_LayoutItem item = {.field_index = i,
562 .rep = f->mode >> kUpb_FieldRep_Shift,
563 .type = kUpb_LayoutItemType_Field};
564 upb_MtDecoder_PushItem(d, item);
565 }
566
567 if (d->vec.size) {
568 qsort(d->vec.data, d->vec.size, sizeof(*d->vec.data),
569 upb_MtDecoder_CompareFields);
570 }
571
572 return true;
573 }
574
upb_MiniTable_DivideRoundUp(size_t n,size_t d)575 static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) {
576 return (n + d - 1) / d;
577 }
578
upb_MtDecoder_AssignHasbits(upb_MiniTable * ret)579 static void upb_MtDecoder_AssignHasbits(upb_MiniTable* ret) {
580 int n = ret->field_count;
581 int last_hasbit = 0; // 0 cannot be used.
582
583 // First assign required fields, which must have the lowest hasbits.
584 for (int i = 0; i < n; i++) {
585 upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
586 if (field->offset == kRequiredPresence) {
587 field->presence = ++last_hasbit;
588 } else if (field->offset == kNoPresence) {
589 field->presence = 0;
590 }
591 }
592 ret->required_count = last_hasbit;
593
594 // Next assign non-required hasbit fields.
595 for (int i = 0; i < n; i++) {
596 upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
597 if (field->offset == kHasbitPresence) {
598 field->presence = ++last_hasbit;
599 }
600 }
601
602 ret->size = last_hasbit ? upb_MiniTable_DivideRoundUp(last_hasbit + 1, 8) : 0;
603 }
604
upb_MtDecoder_Place(upb_MtDecoder * d,upb_FieldRep rep)605 size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
606 size_t size = upb_MtDecoder_SizeOfRep(rep, d->platform);
607 size_t align = upb_MtDecoder_AlignOfRep(rep, d->platform);
608 size_t ret = UPB_ALIGN_UP(d->table->size, align);
609 static const size_t max = UINT16_MAX;
610 size_t new_size = ret + size;
611 if (new_size > max) {
612 upb_MtDecoder_ErrorFormat(
613 d, "Message size exceeded maximum size of %zu bytes", max);
614 }
615 d->table->size = new_size;
616 return ret;
617 }
618
upb_MtDecoder_AssignOffsets(upb_MtDecoder * d)619 static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
620 upb_LayoutItem* end = UPB_PTRADD(d->vec.data, d->vec.size);
621
622 // Compute offsets.
623 for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
624 item->offset = upb_MtDecoder_Place(d, item->rep);
625 }
626
627 // Assign oneof case offsets. We must do these first, since assigning
628 // actual offsets will overwrite the links of the linked list.
629 for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
630 if (item->type != kUpb_LayoutItemType_OneofCase) continue;
631 upb_MiniTableField* f = &d->fields[item->field_index];
632 while (true) {
633 f->presence = ~item->offset;
634 if (f->offset == kUpb_LayoutItem_IndexSentinel) break;
635 UPB_ASSERT(f->offset - kOneofBase < d->table->field_count);
636 f = &d->fields[f->offset - kOneofBase];
637 }
638 }
639
640 // Assign offsets.
641 for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
642 upb_MiniTableField* f = &d->fields[item->field_index];
643 switch (item->type) {
644 case kUpb_LayoutItemType_OneofField:
645 while (true) {
646 uint16_t next_offset = f->offset;
647 f->offset = item->offset;
648 if (next_offset == kUpb_LayoutItem_IndexSentinel) break;
649 f = &d->fields[next_offset - kOneofBase];
650 }
651 break;
652 case kUpb_LayoutItemType_Field:
653 f->offset = item->offset;
654 break;
655 default:
656 break;
657 }
658 }
659
660 // The fasttable parser (supported on 64-bit only) depends on this being a
661 // multiple of 8 in order to satisfy UPB_MALLOC_ALIGN, which is also 8.
662 //
663 // On 32-bit we could potentially make this smaller, but there is no
664 // compelling reason to optimize this right now.
665 d->table->size = UPB_ALIGN_UP(d->table->size, 8);
666 }
667
upb_MtDecoder_ValidateEntryField(upb_MtDecoder * d,const upb_MiniTableField * f,uint32_t expected_num)668 static void upb_MtDecoder_ValidateEntryField(upb_MtDecoder* d,
669 const upb_MiniTableField* f,
670 uint32_t expected_num) {
671 const char* name = expected_num == 1 ? "key" : "val";
672 if (f->number != expected_num) {
673 upb_MtDecoder_ErrorFormat(d,
674 "map %s did not have expected number (%d vs %d)",
675 name, expected_num, (int)f->number);
676 }
677
678 if (upb_IsRepeatedOrMap(f)) {
679 upb_MtDecoder_ErrorFormat(
680 d, "map %s cannot be repeated or map, or be in oneof", name);
681 }
682
683 uint32_t not_ok_types;
684 if (expected_num == 1) {
685 not_ok_types = (1 << kUpb_FieldType_Float) | (1 << kUpb_FieldType_Double) |
686 (1 << kUpb_FieldType_Message) | (1 << kUpb_FieldType_Group) |
687 (1 << kUpb_FieldType_Bytes) | (1 << kUpb_FieldType_Enum);
688 } else {
689 not_ok_types = 1 << kUpb_FieldType_Group;
690 }
691
692 if ((1 << upb_MiniTableField_Type(f)) & not_ok_types) {
693 upb_MtDecoder_ErrorFormat(d, "map %s cannot have type %d", name,
694 (int)f->UPB_PRIVATE(descriptortype));
695 }
696 }
697
upb_MtDecoder_ParseMap(upb_MtDecoder * d,const char * data,size_t len)698 static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
699 size_t len) {
700 upb_MtDecoder_ParseMessage(d, data, len);
701 upb_MtDecoder_AssignHasbits(d->table);
702
703 if (UPB_UNLIKELY(d->table->field_count != 2)) {
704 upb_MtDecoder_ErrorFormat(d, "%hu fields in map", d->table->field_count);
705 UPB_UNREACHABLE();
706 }
707
708 upb_LayoutItem* end = UPB_PTRADD(d->vec.data, d->vec.size);
709 for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
710 if (item->type == kUpb_LayoutItemType_OneofCase) {
711 upb_MtDecoder_ErrorFormat(d, "Map entry cannot have oneof");
712 }
713 }
714
715 upb_MtDecoder_ValidateEntryField(d, &d->table->fields[0], 1);
716 upb_MtDecoder_ValidateEntryField(d, &d->table->fields[1], 2);
717
718 // Map entries have a pre-determined layout, regardless of types.
719 // NOTE: sync with mini_table/message_internal.h.
720 const size_t kv_size = d->platform == kUpb_MiniTablePlatform_32Bit ? 8 : 16;
721 const size_t hasbit_size = 8;
722 d->fields[0].offset = hasbit_size;
723 d->fields[1].offset = hasbit_size + kv_size;
724 d->table->size = UPB_ALIGN_UP(hasbit_size + kv_size + kv_size, 8);
725
726 // Map entries have a special bit set to signal it's a map entry, used in
727 // upb_MiniTable_SetSubMessage() below.
728 d->table->ext |= kUpb_ExtMode_IsMapEntry;
729 }
730
upb_MtDecoder_ParseMessageSet(upb_MtDecoder * d,const char * data,size_t len)731 static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data,
732 size_t len) {
733 if (len > 0) {
734 upb_MtDecoder_ErrorFormat(d, "Invalid message set encode length: %zu", len);
735 UPB_UNREACHABLE();
736 }
737
738 upb_MiniTable* ret = d->table;
739 ret->size = 0;
740 ret->field_count = 0;
741 ret->ext = kUpb_ExtMode_IsMessageSet;
742 ret->dense_below = 0;
743 ret->table_mask = -1;
744 ret->required_count = 0;
745 }
746
upb_MtDecoder_DoBuildMiniTableWithBuf(upb_MtDecoder * decoder,const char * data,size_t len,void ** buf,size_t * buf_size)747 static upb_MiniTable* upb_MtDecoder_DoBuildMiniTableWithBuf(
748 upb_MtDecoder* decoder, const char* data, size_t len, void** buf,
749 size_t* buf_size) {
750 upb_MtDecoder_CheckOutOfMemory(decoder, decoder->table);
751
752 decoder->table->size = 0;
753 decoder->table->field_count = 0;
754 decoder->table->ext = kUpb_ExtMode_NonExtendable;
755 decoder->table->dense_below = 0;
756 decoder->table->table_mask = -1;
757 decoder->table->required_count = 0;
758
759 // Strip off and verify the version tag.
760 if (!len--) goto done;
761 const char vers = *data++;
762
763 switch (vers) {
764 case kUpb_EncodedVersion_MapV1:
765 upb_MtDecoder_ParseMap(decoder, data, len);
766 break;
767
768 case kUpb_EncodedVersion_MessageV1:
769 upb_MtDecoder_ParseMessage(decoder, data, len);
770 upb_MtDecoder_AssignHasbits(decoder->table);
771 upb_MtDecoder_SortLayoutItems(decoder);
772 upb_MtDecoder_AssignOffsets(decoder);
773 break;
774
775 case kUpb_EncodedVersion_MessageSetV1:
776 upb_MtDecoder_ParseMessageSet(decoder, data, len);
777 break;
778
779 default:
780 upb_MtDecoder_ErrorFormat(decoder, "Invalid message version: %c", vers);
781 UPB_UNREACHABLE();
782 }
783
784 done:
785 *buf = decoder->vec.data;
786 *buf_size = decoder->vec.capacity * sizeof(*decoder->vec.data);
787 return decoder->table;
788 }
789
upb_MtDecoder_BuildMiniTableWithBuf(upb_MtDecoder * const decoder,const char * const data,const size_t len,void ** const buf,size_t * const buf_size)790 static upb_MiniTable* upb_MtDecoder_BuildMiniTableWithBuf(
791 upb_MtDecoder* const decoder, const char* const data, const size_t len,
792 void** const buf, size_t* const buf_size) {
793 if (UPB_SETJMP(decoder->err) != 0) {
794 *buf = decoder->vec.data;
795 *buf_size = decoder->vec.capacity * sizeof(*decoder->vec.data);
796 return NULL;
797 }
798
799 return upb_MtDecoder_DoBuildMiniTableWithBuf(decoder, data, len, buf,
800 buf_size);
801 }
802
upb_MiniTable_BuildWithBuf(const char * data,size_t len,upb_MiniTablePlatform platform,upb_Arena * arena,void ** buf,size_t * buf_size,upb_Status * status)803 upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
804 upb_MiniTablePlatform platform,
805 upb_Arena* arena, void** buf,
806 size_t* buf_size,
807 upb_Status* status) {
808 upb_MtDecoder decoder = {
809 .platform = platform,
810 .vec =
811 {
812 .data = *buf,
813 .capacity = *buf_size / sizeof(*decoder.vec.data),
814 .size = 0,
815 },
816 .arena = arena,
817 .status = status,
818 .table = upb_Arena_Malloc(arena, sizeof(*decoder.table)),
819 };
820
821 return upb_MtDecoder_BuildMiniTableWithBuf(&decoder, data, len, buf,
822 buf_size);
823 }
824
upb_MiniTableEnum_Size(size_t count)825 static size_t upb_MiniTableEnum_Size(size_t count) {
826 return sizeof(upb_MiniTableEnum) + count * sizeof(uint32_t);
827 }
828
_upb_MiniTable_AddEnumDataMember(upb_MtDecoder * d,uint32_t val)829 static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MtDecoder* d,
830 uint32_t val) {
831 if (d->enum_data_count == d->enum_data_capacity) {
832 size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
833 d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2);
834 size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
835 d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz);
836 upb_MtDecoder_CheckOutOfMemory(d, d->enum_table);
837 }
838 d->enum_table->data[d->enum_data_count++] = val;
839 return d->enum_table;
840 }
841
upb_MiniTableEnum_BuildValue(upb_MtDecoder * d,uint32_t val)842 static void upb_MiniTableEnum_BuildValue(upb_MtDecoder* d, uint32_t val) {
843 upb_MiniTableEnum* table = d->enum_table;
844 d->enum_value_count++;
845 if (table->value_count || (val > 512 && d->enum_value_count < val / 32)) {
846 if (table->value_count == 0) {
847 assert(d->enum_data_count == table->mask_limit / 32);
848 }
849 table = _upb_MiniTable_AddEnumDataMember(d, val);
850 table->value_count++;
851 } else {
852 uint32_t new_mask_limit = ((val / 32) + 1) * 32;
853 while (table->mask_limit < new_mask_limit) {
854 table = _upb_MiniTable_AddEnumDataMember(d, 0);
855 table->mask_limit += 32;
856 }
857 table->data[val / 32] |= 1ULL << (val % 32);
858 }
859 }
860
upb_MtDecoder_DoBuildMiniTableEnum(upb_MtDecoder * decoder,const char * data,size_t len)861 static upb_MiniTableEnum* upb_MtDecoder_DoBuildMiniTableEnum(
862 upb_MtDecoder* decoder, const char* data, size_t len) {
863 // If the string is non-empty then it must begin with a version tag.
864 if (len) {
865 if (*data != kUpb_EncodedVersion_EnumV1) {
866 upb_MtDecoder_ErrorFormat(decoder, "Invalid enum version: %c", *data);
867 UPB_UNREACHABLE();
868 }
869 data++;
870 len--;
871 }
872
873 upb_MtDecoder_CheckOutOfMemory(decoder, decoder->enum_table);
874
875 // Guarantee at least 64 bits of mask without checking mask size.
876 decoder->enum_table->mask_limit = 64;
877 decoder->enum_table = _upb_MiniTable_AddEnumDataMember(decoder, 0);
878 decoder->enum_table = _upb_MiniTable_AddEnumDataMember(decoder, 0);
879
880 decoder->enum_table->value_count = 0;
881
882 const char* ptr = data;
883 uint32_t base = 0;
884
885 while (ptr < decoder->end) {
886 char ch = *ptr++;
887 if (ch <= kUpb_EncodedValue_MaxEnumMask) {
888 uint32_t mask = _upb_FromBase92(ch);
889 for (int i = 0; i < 5; i++, base++, mask >>= 1) {
890 if (mask & 1) upb_MiniTableEnum_BuildValue(decoder, base);
891 }
892 } else if (kUpb_EncodedValue_MinSkip <= ch &&
893 ch <= kUpb_EncodedValue_MaxSkip) {
894 uint32_t skip;
895 ptr = upb_MiniTable_DecodeBase92Varint(decoder, ptr, ch,
896 kUpb_EncodedValue_MinSkip,
897 kUpb_EncodedValue_MaxSkip, &skip);
898 base += skip;
899 } else {
900 upb_MtDecoder_ErrorFormat(decoder, "Unexpected character: %c", ch);
901 return NULL;
902 }
903 }
904
905 return decoder->enum_table;
906 }
907
upb_MtDecoder_BuildMiniTableEnum(upb_MtDecoder * const decoder,const char * const data,size_t const len)908 static upb_MiniTableEnum* upb_MtDecoder_BuildMiniTableEnum(
909 upb_MtDecoder* const decoder, const char* const data, size_t const len) {
910 if (UPB_SETJMP(decoder->err) != 0) return NULL;
911 return upb_MtDecoder_DoBuildMiniTableEnum(decoder, data, len);
912 }
913
upb_MiniTableEnum_Build(const char * data,size_t len,upb_Arena * arena,upb_Status * status)914 upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
915 upb_Arena* arena,
916 upb_Status* status) {
917 upb_MtDecoder decoder = {
918 .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)),
919 .enum_value_count = 0,
920 .enum_data_count = 0,
921 .enum_data_capacity = 1,
922 .status = status,
923 .end = UPB_PTRADD(data, len),
924 .arena = arena,
925 };
926
927 return upb_MtDecoder_BuildMiniTableEnum(&decoder, data, len);
928 }
929
upb_MtDecoder_DoBuildMiniTableExtension(upb_MtDecoder * decoder,const char * data,size_t len,upb_MiniTableExtension * ext,const upb_MiniTable * extendee,upb_MiniTableSub sub)930 static const char* upb_MtDecoder_DoBuildMiniTableExtension(
931 upb_MtDecoder* decoder, const char* data, size_t len,
932 upb_MiniTableExtension* ext, const upb_MiniTable* extendee,
933 upb_MiniTableSub sub) {
934 // If the string is non-empty then it must begin with a version tag.
935 if (len) {
936 if (*data != kUpb_EncodedVersion_ExtensionV1) {
937 upb_MtDecoder_ErrorFormat(decoder, "Invalid ext version: %c", *data);
938 UPB_UNREACHABLE();
939 }
940 data++;
941 len--;
942 }
943
944 uint16_t count = 0;
945 const char* ret =
946 upb_MtDecoder_Parse(decoder, data, len, ext, sizeof(*ext), &count, NULL);
947 if (!ret || count != 1) return NULL;
948
949 upb_MiniTableField* f = &ext->field;
950
951 f->mode |= kUpb_LabelFlags_IsExtension;
952 f->offset = 0;
953 f->presence = 0;
954
955 if (extendee->ext & kUpb_ExtMode_IsMessageSet) {
956 // Extensions of MessageSet must be messages.
957 if (!upb_IsSubMessage(f)) return NULL;
958
959 // Extensions of MessageSet must be non-repeating.
960 if ((f->mode & kUpb_FieldMode_Mask) == kUpb_FieldMode_Array) return NULL;
961 }
962
963 ext->extendee = extendee;
964 ext->sub = sub;
965
966 return ret;
967 }
968
upb_MtDecoder_BuildMiniTableExtension(upb_MtDecoder * const decoder,const char * const data,const size_t len,upb_MiniTableExtension * const ext,const upb_MiniTable * const extendee,const upb_MiniTableSub sub)969 static const char* upb_MtDecoder_BuildMiniTableExtension(
970 upb_MtDecoder* const decoder, const char* const data, const size_t len,
971 upb_MiniTableExtension* const ext, const upb_MiniTable* const extendee,
972 const upb_MiniTableSub sub) {
973 if (UPB_SETJMP(decoder->err) != 0) return NULL;
974 return upb_MtDecoder_DoBuildMiniTableExtension(decoder, data, len, ext,
975 extendee, sub);
976 }
977
_upb_MiniTableExtension_Init(const char * data,size_t len,upb_MiniTableExtension * ext,const upb_MiniTable * extendee,upb_MiniTableSub sub,upb_MiniTablePlatform platform,upb_Status * status)978 const char* _upb_MiniTableExtension_Init(const char* data, size_t len,
979 upb_MiniTableExtension* ext,
980 const upb_MiniTable* extendee,
981 upb_MiniTableSub sub,
982 upb_MiniTablePlatform platform,
983 upb_Status* status) {
984 upb_MtDecoder decoder = {
985 .arena = NULL,
986 .status = status,
987 .table = NULL,
988 .platform = platform,
989 };
990
991 return upb_MtDecoder_BuildMiniTableExtension(&decoder, data, len, ext,
992 extendee, sub);
993 }
994
_upb_MiniTableExtension_Build(const char * data,size_t len,const upb_MiniTable * extendee,upb_MiniTableSub sub,upb_MiniTablePlatform platform,upb_Arena * arena,upb_Status * status)995 upb_MiniTableExtension* _upb_MiniTableExtension_Build(
996 const char* data, size_t len, const upb_MiniTable* extendee,
997 upb_MiniTableSub sub, upb_MiniTablePlatform platform, upb_Arena* arena,
998 upb_Status* status) {
999 upb_MiniTableExtension* ext =
1000 upb_Arena_Malloc(arena, sizeof(upb_MiniTableExtension));
1001 if (UPB_UNLIKELY(!ext)) return NULL;
1002
1003 const char* ptr = _upb_MiniTableExtension_Init(data, len, ext, extendee, sub,
1004 platform, status);
1005 if (UPB_UNLIKELY(!ptr)) return NULL;
1006
1007 return ext;
1008 }
1009
_upb_MiniTable_Build(const char * data,size_t len,upb_MiniTablePlatform platform,upb_Arena * arena,upb_Status * status)1010 upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len,
1011 upb_MiniTablePlatform platform,
1012 upb_Arena* arena, upb_Status* status) {
1013 void* buf = NULL;
1014 size_t size = 0;
1015 upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(data, len, platform, arena,
1016 &buf, &size, status);
1017 free(buf);
1018 return ret;
1019 }
1020
upb_MiniTable_SetSubMessage(upb_MiniTable * table,upb_MiniTableField * field,const upb_MiniTable * sub)1021 bool upb_MiniTable_SetSubMessage(upb_MiniTable* table,
1022 upb_MiniTableField* field,
1023 const upb_MiniTable* sub) {
1024 UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
1025 (uintptr_t)field <
1026 (uintptr_t)(table->fields + table->field_count));
1027 UPB_ASSERT(sub);
1028
1029 const bool sub_is_map = sub->ext & kUpb_ExtMode_IsMapEntry;
1030
1031 switch (field->UPB_PRIVATE(descriptortype)) {
1032 case kUpb_FieldType_Message:
1033 if (sub_is_map) {
1034 const bool table_is_map = table->ext & kUpb_ExtMode_IsMapEntry;
1035 if (UPB_UNLIKELY(table_is_map)) return false;
1036
1037 field->mode = (field->mode & ~kUpb_FieldMode_Mask) | kUpb_FieldMode_Map;
1038 }
1039 break;
1040
1041 case kUpb_FieldType_Group:
1042 if (UPB_UNLIKELY(sub_is_map)) return false;
1043 break;
1044
1045 default:
1046 return false;
1047 }
1048
1049 upb_MiniTableSub* table_sub =
1050 (void*)&table->subs[field->UPB_PRIVATE(submsg_index)];
1051 table_sub->submsg = sub;
1052 return true;
1053 }
1054
upb_MiniTable_SetSubEnum(upb_MiniTable * table,upb_MiniTableField * field,const upb_MiniTableEnum * sub)1055 bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
1056 const upb_MiniTableEnum* sub) {
1057 UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
1058 (uintptr_t)field <
1059 (uintptr_t)(table->fields + table->field_count));
1060 UPB_ASSERT(sub);
1061
1062 upb_MiniTableSub* table_sub =
1063 (void*)&table->subs[field->UPB_PRIVATE(submsg_index)];
1064 table_sub->subenum = sub;
1065 return true;
1066 }
1067
upb_MiniTable_GetSubList(const upb_MiniTable * mt,const upb_MiniTableField ** subs)1068 uint32_t upb_MiniTable_GetSubList(const upb_MiniTable* mt,
1069 const upb_MiniTableField** subs) {
1070 uint32_t msg_count = 0;
1071 uint32_t enum_count = 0;
1072
1073 for (int i = 0; i < mt->field_count; i++) {
1074 const upb_MiniTableField* f = &mt->fields[i];
1075 if (upb_MiniTableField_CType(f) == kUpb_CType_Message) {
1076 *subs = f;
1077 ++subs;
1078 msg_count++;
1079 }
1080 }
1081
1082 for (int i = 0; i < mt->field_count; i++) {
1083 const upb_MiniTableField* f = &mt->fields[i];
1084 if (upb_MiniTableField_CType(f) == kUpb_CType_Enum) {
1085 *subs = f;
1086 ++subs;
1087 enum_count++;
1088 }
1089 }
1090
1091 return (msg_count << 16) | enum_count;
1092 }
1093
1094 // The list of sub_tables and sub_enums must exactly match the number and order
1095 // of sub-message fields and sub-enum fields given by upb_MiniTable_GetSubList()
1096 // above.
upb_MiniTable_Link(upb_MiniTable * mt,const upb_MiniTable ** sub_tables,size_t sub_table_count,const upb_MiniTableEnum ** sub_enums,size_t sub_enum_count)1097 bool upb_MiniTable_Link(upb_MiniTable* mt, const upb_MiniTable** sub_tables,
1098 size_t sub_table_count,
1099 const upb_MiniTableEnum** sub_enums,
1100 size_t sub_enum_count) {
1101 uint32_t msg_count = 0;
1102 uint32_t enum_count = 0;
1103
1104 for (int i = 0; i < mt->field_count; i++) {
1105 upb_MiniTableField* f = (upb_MiniTableField*)&mt->fields[i];
1106 if (upb_MiniTableField_CType(f) == kUpb_CType_Message) {
1107 const upb_MiniTable* sub = sub_tables[msg_count++];
1108 if (msg_count > sub_table_count) return false;
1109 if (sub != NULL) {
1110 if (!upb_MiniTable_SetSubMessage(mt, f, sub)) return false;
1111 }
1112 }
1113 }
1114
1115 for (int i = 0; i < mt->field_count; i++) {
1116 upb_MiniTableField* f = (upb_MiniTableField*)&mt->fields[i];
1117 if (upb_MiniTableField_CType(f) == kUpb_CType_Enum) {
1118 const upb_MiniTableEnum* sub = sub_enums[enum_count++];
1119 if (enum_count > sub_enum_count) return false;
1120 if (sub != NULL) {
1121 if (!upb_MiniTable_SetSubEnum(mt, f, sub)) return false;
1122 }
1123 }
1124 }
1125
1126 return true;
1127 }
1128