google-protobuf 4.36.2-java → 4.37.0.rc.1-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -84,6 +84,19 @@
84
84
  #define UPB_HAS_BUILTIN(x) 0
85
85
  #endif
86
86
 
87
+ // UPB_MEMCPY_INLINE(dst, src, n): memcpy() of a compile-time constant number
88
+ // of bytes `n`, which the compiler never turns into a call to the library
89
+ // memcpy(). A plain memcpy() of a constant size is usually inlined as loads and
90
+ // stores too, but the compiler can merge such copies of different sizes (e.g.
91
+ // the cases of a switch on the size) into one copy of a variable size, which
92
+ // it then can't inline; the merge can even happen before the compiler uses the
93
+ // UPB_ASSUME()s about the size.
94
+ #if UPB_HAS_BUILTIN(__builtin_memcpy_inline)
95
+ #define UPB_MEMCPY_INLINE(dst, src, n) __builtin_memcpy_inline(dst, src, n)
96
+ #else
97
+ #define UPB_MEMCPY_INLINE(dst, src, n) memcpy(dst, src, n)
98
+ #endif
99
+
87
100
  #ifdef __has_extension
88
101
  #define UPB_HAS_EXTENSION(x) __has_extension(x)
89
102
  #else
@@ -129,6 +142,14 @@ Error, UINTPTR_MAX is undefined
129
142
  (((SIZE_MAX - offsetof(type, member[0])) / \
130
143
  (offsetof(type, member[1]) - offsetof(type, member[0]))) < (size_t)count)
131
144
 
145
+ // Inverse of UPB_SIZEOF_FLEX; given the size in memory, how many elements can
146
+ // the flexible array member store?
147
+ #define UPB_FLEX_CAPACITY(type, member, size) \
148
+ ((size) < sizeof(type) \
149
+ ? (size_t)0 \
150
+ : ((size) - offsetof(type, member[0])) / \
151
+ (offsetof(type, member[1]) - offsetof(type, member[0])))
152
+
132
153
  #define UPB_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
133
154
 
134
155
  #define UPB_MAPTYPE_STRING 0
@@ -304,12 +325,11 @@ Error, UINTPTR_MAX is undefined
304
325
  #define UPB_NODEREF
305
326
  #endif
306
327
 
307
- // Will be defined properly once call sites are updated
308
- #if false && UPB_HAS_C_ATTRIBUTE(nodiscard)
328
+ #if UPB_HAS_C_ATTRIBUTE(nodiscard)
309
329
  #define UPB_NODISCARD [[nodiscard]]
310
- #elif false && UPB_HAS_ATTRIBUTE(warn_unused_result)
330
+ #elif UPB_HAS_ATTRIBUTE(warn_unused_result)
311
331
  #define UPB_NODISCARD __attribute__((warn_unused_result))
312
- #elif false && UPB_HAS_CPP_ATTRIBUTE(nodiscard)
332
+ #elif UPB_HAS_CPP_ATTRIBUTE(nodiscard)
313
333
  #define UPB_NODISCARD [[nodiscard]]
314
334
  #else
315
335
  #define UPB_NODISCARD
@@ -495,7 +515,7 @@ Error, UINTPTR_MAX is undefined
495
515
 
496
516
  /* aarch64 supports big and little endian modes; fasttable performs multibyte
497
517
  * tag loads assumes the tag of a varint is in the low bits. */
498
- #if (defined(__x86_64__) || defined(__AARCH64EL__)) && \
518
+ #if !defined(_WIN32) && (defined(__x86_64__) || defined(__AARCH64EL__)) && \
499
519
  UPB_HAS_ATTRIBUTE(preserve_none) && UPB_HAS_ATTRIBUTE(musttail)
500
520
  #define UPB_FASTTABLE_SUPPORTED 1
501
521
  #else
@@ -514,7 +534,11 @@ Error, UINTPTR_MAX is undefined
514
534
  * This is useful for releasing code that might be used on multiple platforms,
515
535
  * for example the PHP or Ruby C extensions. */
516
536
  #elif defined(UPB_TRY_ENABLE_FASTTABLE)
517
- #define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED
537
+ #if UPB_FASTTABLE_SUPPORTED
538
+ #define UPB_FASTTABLE 1
539
+ #else
540
+ #define UPB_FASTTABLE 0
541
+ #endif
518
542
  #else
519
543
  #define UPB_FASTTABLE 0
520
544
  #endif
@@ -542,6 +566,25 @@ Error, UINTPTR_MAX is undefined
542
566
  #define UPB_DEPRECATED
543
567
  #endif
544
568
 
569
+ #if defined(__clang__)
570
+ #define UPB_IGNORE_DEPRECATION_START \
571
+ _Pragma("clang diagnostic push") \
572
+ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
573
+ #define UPB_IGNORE_DEPRECATION_STOP _Pragma("clang diagnostic pop")
574
+ #elif defined(__GNUC__)
575
+ #define UPB_IGNORE_DEPRECATION_START \
576
+ _Pragma("GCC diagnostic push") \
577
+ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
578
+ #define UPB_IGNORE_DEPRECATION_STOP _Pragma("GCC diagnostic pop")
579
+ #elif defined(_MSC_VER)
580
+ #define UPB_IGNORE_DEPRECATION_START \
581
+ __pragma(warning(push)) __pragma(warning(disable : 4996))
582
+ #define UPB_IGNORE_DEPRECATION_STOP __pragma(warning(pop))
583
+ #else
584
+ #define UPB_IGNORE_DEPRECATION_START
585
+ #define UPB_IGNORE_DEPRECATION_STOP
586
+ #endif
587
+
545
588
  #if defined(UPB_IS_GOOGLE3) && \
546
589
  (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0)
547
590
  #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init
@@ -568,6 +611,12 @@ Error, UINTPTR_MAX is undefined
568
611
  #define UPB_RETAIN
569
612
  #endif
570
613
 
614
+ #if defined(__GNUC__) || defined(__clang__)
615
+ #define UPB_HIDDEN __attribute__((visibility("hidden")))
616
+ #else
617
+ #define UPB_HIDDEN
618
+ #endif
619
+
571
620
  // Linker arrays combine elements from multiple translation units into a single
572
621
  // array that can be iterated over at runtime.
573
622
  //
@@ -621,7 +670,7 @@ Error, UINTPTR_MAX is undefined
621
670
 
622
671
  #elif defined(__MACH__)
623
672
 
624
- /* As described in: https://stackoverflow.com/a/22366882 */
673
+ /* As described in: https://stackoverflow.com/a/22366882 */
625
674
  #define UPB_LINKARR_APPEND(name) \
626
675
  __attribute__(( \
627
676
  section("__DATA,__la_" #name))) UPB_LINKARR_ATTR UPB_NO_SANITIZE_ADDRESS
@@ -640,10 +689,10 @@ Error, UINTPTR_MAX is undefined
640
689
 
641
690
  #elif defined(_MSC_VER)
642
691
 
643
- /* See:
644
- * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155
645
- * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165
646
- * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */
692
+ /* See:
693
+ * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155
694
+ * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165
695
+ * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */
647
696
  #define UPB_STRINGIFY_INTERNAL(x) #x
648
697
  #define UPB_STRINGIFY(x) UPB_STRINGIFY_INTERNAL(x)
649
698
  #define UPB_CONCAT(a, b, c) a##b##c
@@ -652,7 +701,7 @@ Error, UINTPTR_MAX is undefined
652
701
  #define UPB_LINKARR_APPEND(name) \
653
702
  __pragma(section(UPB_LINKARR_NAME(name, $j), read)) \
654
703
  __declspec(allocate(UPB_LINKARR_NAME(name, $j)))
655
- // clang-format off
704
+ // clang-format off
656
705
  #define UPB_LINKARR_DECLARE(name, type) \
657
706
  __pragma(message(UPB_LINKARR_NAME(name, $j))) \
658
707
  __pragma(section(UPB_LINKARR_NAME(name, $a), read)) \
@@ -663,13 +712,13 @@ Error, UINTPTR_MAX is undefined
663
712
  type __stop_linkarr_##name; \
664
713
  UPB_LINKARR_APPEND(name) \
665
714
  __declspec(selectany) type UPB_linkarr_internal_empty_##name[1] = {0}
666
- // clang-format on
715
+ // clang-format on
667
716
  #define UPB_LINKARR_START(name) (&__start_linkarr_##name)
668
717
  #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name)
669
718
 
670
719
  #else
671
720
 
672
- // Linker arrays are not supported on this platform. Make macros no-ops.
721
+ // Linker arrays are not supported on this platform. Make macros no-ops.
673
722
  #define UPB_LINKARR_APPEND(name)
674
723
  #define UPB_LINKARR_DECLARE(name, type) \
675
724
  UPB_STATIC_ASSERT(sizeof("__la_" #name) <= 17, \
@@ -2682,7 +2731,7 @@ UPB_INLINE int _upb_popcnt32(uint32_t i) {
2682
2731
 
2683
2732
  #undef UPB_FAST_POPCOUNT32
2684
2733
 
2685
- UPB_INLINE uint8_t _upb_log2_table_size(upb_table* t) {
2734
+ UPB_INLINE uint8_t _upb_log2_table_size(const upb_table* t) {
2686
2735
  return _upb_popcnt32(t->mask);
2687
2736
  }
2688
2737
 
@@ -2715,25 +2764,7 @@ typedef bool eqlfunc_t(upb_key k1, upb_value v1, lookupkey_t k2);
2715
2764
 
2716
2765
  /* Base table (shared code) ***************************************************/
2717
2766
 
2718
- static uint32_t upb_inthash(uintptr_t key) {
2719
- UPB_STATIC_ASSERT(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
2720
- "Pointers don't fit");
2721
- if (sizeof(uintptr_t) == 8) {
2722
- return (uint32_t)key ^ (uint32_t)((uint64_t)key >> 32);
2723
- } else {
2724
- return (uint32_t)key;
2725
- }
2726
- }
2727
-
2728
- static upb_tabent* upb_getentry(const upb_table* t, uint32_t hash) {
2729
- return t->entries + (hash & t->mask);
2730
- }
2731
-
2732
- static bool isfull(upb_table* t) {
2733
- uint32_t size = upb_table_size(t);
2734
- // 0.875 load factor
2735
- return t->count == (size - (size >> 3));
2736
- }
2767
+ static bool isfull(upb_table* t) { return upb_table_isfull(t); }
2737
2768
 
2738
2769
  static bool init(upb_table* t, uint8_t size_lg2, upb_Arena* a) {
2739
2770
  if (size_lg2 >= 32) {
@@ -2742,10 +2773,10 @@ static bool init(upb_table* t, uint8_t size_lg2, upb_Arena* a) {
2742
2773
  t->count = 0;
2743
2774
  uint32_t size = 1U << size_lg2;
2744
2775
  t->mask = size - 1; // 0 mask if size_lg2 is 0
2745
- if (upb_table_size(t) > (SIZE_MAX / sizeof(upb_tabent))) {
2776
+ size_t bytes;
2777
+ if (upb_MulOverflow(upb_table_size(t), sizeof(upb_tabent), &bytes)) {
2746
2778
  return false;
2747
2779
  }
2748
- size_t bytes = upb_table_size(t) * sizeof(upb_tabent);
2749
2780
  if (bytes > 0) {
2750
2781
  t->entries = upb_Arena_Malloc(a, bytes);
2751
2782
  if (!t->entries) return false;
@@ -3173,14 +3204,6 @@ static bool streql(upb_key k1, upb_value v1, lookupkey_t k2) {
3173
3204
  (k1s->size == 0 || memcmp(k1s->data, k2s.data, k1s->size) == 0);
3174
3205
  }
3175
3206
 
3176
- /** Calculates the number of entries required to hold an expected number of
3177
- * values, within the table's load factor. */
3178
- static size_t _upb_entries_needed_for(size_t expected_size) {
3179
- size_t need_entries = expected_size + 1 + expected_size / 7;
3180
- UPB_ASSERT(need_entries - (need_entries >> 3) >= expected_size);
3181
- return need_entries;
3182
- }
3183
-
3184
3207
  bool upb_strtable_init(upb_strtable* t, size_t expected_size, upb_Arena* a) {
3185
3208
  int size_lg2 = upb_Log2Ceiling(_upb_entries_needed_for(expected_size));
3186
3209
  return init(&t->t, size_lg2, a);
@@ -3193,34 +3216,78 @@ void upb_strtable_clear(upb_strtable* t) {
3193
3216
  }
3194
3217
 
3195
3218
  bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a) {
3219
+ if (t->t.entries != NULL && _upb_log2_table_size(&t->t) >= size_lg2) {
3220
+ return true;
3221
+ }
3196
3222
  upb_strtable new_table;
3197
3223
  if (!init(&new_table.t, size_lg2, a)) return false;
3198
3224
 
3199
- intptr_t iter = UPB_STRTABLE_BEGIN;
3200
- upb_StringView sv;
3201
- upb_value val;
3202
- while (upb_strtable_next2(t, &sv, &val, &iter)) {
3203
- // Unlike normal insert, does not copy string data or possibly reallocate
3204
- // the table
3205
- // The data pointer used in the table is guaranteed to point at a
3206
- // upb_SizePrefixString, we just need to back up by the size of the uint32_t
3207
- // length prefix.
3208
- const upb_SizePrefixString* keystr =
3209
- (const upb_SizePrefixString*)(sv.data - sizeof(uint32_t));
3210
- UPB_ASSERT(keystr->data == sv.data);
3211
- UPB_ASSERT(keystr->size == sv.size);
3212
-
3213
- lookupkey_t lookupkey = {.str = sv};
3214
- upb_key tabkey = {.str = keystr};
3215
- uint32_t hash = _upb_Hash_NoSeed(sv.data, sv.size);
3216
- insert(&new_table.t, lookupkey, tabkey, val, hash, &strhash, &streql);
3225
+ if (t->t.count > 0) {
3226
+ intptr_t iter = UPB_STRTABLE_BEGIN;
3227
+ upb_StringView sv;
3228
+ upb_value val;
3229
+ while (upb_strtable_next2(t, &sv, &val, &iter)) {
3230
+ // Unlike normal insert, does not copy string data or possibly reallocate
3231
+ // the table
3232
+ // The data pointer used in the table is guaranteed to point at a
3233
+ // upb_SizePrefixString, we just need to back up by the size of the
3234
+ // uint32_t length prefix.
3235
+ const upb_SizePrefixString* keystr =
3236
+ (const upb_SizePrefixString*)(sv.data - sizeof(uint32_t));
3237
+ UPB_ASSERT(keystr->data == sv.data);
3238
+ UPB_ASSERT(keystr->size == sv.size);
3239
+
3240
+ lookupkey_t lookupkey = {.str = sv};
3241
+ upb_key tabkey = {.str = keystr};
3242
+ uint32_t hash = _upb_Hash_NoSeed(sv.data, sv.size);
3243
+ insert(&new_table.t, lookupkey, tabkey, val, hash, &strhash, &streql);
3244
+ }
3217
3245
  }
3218
3246
  *t = new_table;
3219
3247
  return true;
3220
3248
  }
3221
3249
 
3222
- bool upb_strtable_insert(upb_strtable* t, const char* k, size_t len,
3223
- upb_value v, upb_Arena* a) {
3250
+ bool upb_strtable_copy(upb_strtable* dest, const upb_strtable* src,
3251
+ upb_Arena* a) {
3252
+ if (src->t.count == 0) {
3253
+ return upb_strtable_init(dest, 0, a);
3254
+ }
3255
+ dest->t.count = src->t.count;
3256
+ dest->t.mask = src->t.mask;
3257
+ dest->t.entries =
3258
+ upb_Arena_Malloc(a, upb_table_size(&src->t) * sizeof(upb_tabent));
3259
+ if (!dest->t.entries) return false;
3260
+ upb_tabent* restrict dest_entries = dest->t.entries;
3261
+ const upb_tabent* restrict src_entries = src->t.entries;
3262
+ size_t table_size = upb_table_size(&src->t);
3263
+ for (size_t i = 0; i < table_size; i++) {
3264
+ upb_tabent* dest_ent = &dest_entries[i];
3265
+ const upb_tabent* src_ent = &src_entries[i];
3266
+ if (!upb_tabent_isempty(src_ent)) {
3267
+ upb_StringView sv = upb_key_strview(src_ent->key);
3268
+ upb_SizePrefixString* size_prefix_string =
3269
+ upb_SizePrefixString_Copy(sv, a);
3270
+ if (!size_prefix_string) return false;
3271
+ dest_ent->key.str = size_prefix_string;
3272
+ // The caller is responsible for cloning values if they are not
3273
+ // primitives.
3274
+ dest_ent->val = src_ent->val;
3275
+ if (UPB_UNPREDICTABLE(upb_tabent_hasnext(src_ent))) {
3276
+ size_t offset = upb_tabent_next(src_ent) - src_entries;
3277
+ upb_tabent_setnext(dest_ent, dest_entries + offset);
3278
+ } else {
3279
+ upb_tabent_clearnext(dest_ent);
3280
+ }
3281
+ } else {
3282
+ *dest_ent = (upb_tabent){};
3283
+ }
3284
+ }
3285
+ return true;
3286
+ }
3287
+
3288
+ // Inserts `k`, whose hash is `hash`, which must not already be in the table.
3289
+ UPB_FORCEINLINE bool strtable_insert(upb_strtable* t, const char* k, size_t len,
3290
+ upb_value v, uint32_t hash, upb_Arena* a) {
3224
3291
  if (isfull(&t->t)) {
3225
3292
  /* Need to resize. New table of double the size, add old elements to it. */
3226
3293
  if (!upb_strtable_resize(t, _upb_log2_table_size(&t->t) + 1, a)) {
@@ -3234,11 +3301,29 @@ bool upb_strtable_insert(upb_strtable* t, const char* k, size_t len,
3234
3301
 
3235
3302
  lookupkey_t lookupkey = {.str = sv};
3236
3303
  upb_key key = {.str = size_prefix_string};
3237
- uint32_t hash = _upb_Hash_NoSeed(k, len);
3238
3304
  insert(&t->t, lookupkey, key, v, hash, &strhash, &streql);
3239
3305
  return true;
3240
3306
  }
3241
3307
 
3308
+ bool upb_strtable_insert(upb_strtable* t, const char* k, size_t len,
3309
+ upb_value v, upb_Arena* a) {
3310
+ return strtable_insert(t, k, len, v, _upb_Hash_NoSeed(k, len), a);
3311
+ }
3312
+
3313
+ bool upb_strtable_insert_or_replace(upb_strtable* t, const char* k, size_t len,
3314
+ upb_value v, bool* replaced, upb_Arena* a) {
3315
+ uint32_t hash = _upb_Hash_NoSeed(k, len);
3316
+ upb_tabent* e = findentry_mutable(&t->t, strkey2(k, len), hash, &streql);
3317
+ if (e) {
3318
+ e->val = v;
3319
+ *replaced = true;
3320
+ return true;
3321
+ }
3322
+ *replaced = false;
3323
+ if (UPB_UNLIKELY(t->t.entries == NULL) && !init(&t->t, 3, a)) return false;
3324
+ return strtable_insert(t, k, len, v, hash, a);
3325
+ }
3326
+
3242
3327
  bool upb_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
3243
3328
  upb_value* v) {
3244
3329
  uint32_t hash = _upb_Hash_NoSeed(key, len);
@@ -3411,8 +3496,6 @@ static bool inteql(upb_key k1, upb_value v1, lookupkey_t k2) {
3411
3496
  return k1.num == k2.num;
3412
3497
  }
3413
3498
 
3414
- size_t upb_inttable_count(const upb_inttable* t) { return t->t.count; }
3415
-
3416
3499
  static void check(upb_inttable* t) {
3417
3500
  UPB_UNUSED(t);
3418
3501
  #if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
@@ -3442,25 +3525,161 @@ bool upb_inttable_init(upb_inttable* t, upb_Arena* a) {
3442
3525
  return upb_inttable_sizedinit(t, 3, a);
3443
3526
  }
3444
3527
 
3445
- bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
3446
- upb_Arena* a) {
3447
- if (isfull(&t->t)) {
3448
- upb_table new_table;
3528
+ bool upb_inttable_copy(upb_inttable* dest, const upb_inttable* src,
3529
+ upb_Arena* a) {
3530
+ if (src->t.count == 0) {
3531
+ return upb_inttable_sizedinit(dest, 0, a);
3532
+ }
3449
3533
 
3450
- if (!init(&new_table, _upb_log2_table_size(&t->t) + 1, a)) {
3451
- return false;
3534
+ if (!upb_inttable_sizedinit(
3535
+ dest, src->t.mask ? _upb_log2_table_size(&src->t) : 0, a)) {
3536
+ return false;
3537
+ }
3538
+ dest->t.count = src->t.count;
3539
+
3540
+ upb_tabent* restrict dest_entries = dest->t.entries;
3541
+ const upb_tabent* restrict src_entries = src->t.entries;
3542
+ size_t table_size = upb_table_size(&src->t);
3543
+ for (size_t i = 0; i < table_size; i++) {
3544
+ upb_tabent* dest_ent = &dest_entries[i];
3545
+ const upb_tabent* src_ent = &src_entries[i];
3546
+ if (!upb_tabent_isempty(src_ent)) {
3547
+ // The caller is responsible for cloning these if they are not primitives.
3548
+ dest_ent->key = src_ent->key;
3549
+ dest_ent->val = src_ent->val;
3550
+ if (UPB_UNPREDICTABLE(upb_tabent_hasnext(src_ent))) {
3551
+ size_t offset = upb_tabent_next(src_ent) - src_entries;
3552
+ upb_tabent_setnext(dest_ent, dest_entries + offset);
3553
+ } else {
3554
+ upb_tabent_clearnext(dest_ent);
3555
+ }
3556
+ } else {
3557
+ *dest_ent = (upb_tabent){};
3452
3558
  }
3559
+ }
3560
+ return true;
3561
+ }
3562
+
3563
+ // Attempts to grow the inttable in-place. If a table has primitive keys and
3564
+ // values, insertions generally don't allocate anything in between the table's
3565
+ // allocations; in that case, growing the table in place uses half the total
3566
+ // memory compared to allocating new chunks and copying over.
3567
+ static bool upb_inttable_trygrow(upb_inttable* t, size_t size_lg2,
3568
+ upb_Arena* a) {
3569
+ if (size_lg2 >= 32) {
3570
+ return false;
3571
+ }
3572
+ size_t old_size = upb_table_size(&t->t);
3573
+ size_t old_bytes = old_size * sizeof(upb_tabent);
3574
+ size_t new_size = (size_t)1 << size_lg2;
3575
+ size_t new_bytes = new_size * sizeof(upb_tabent);
3576
+ if (new_bytes <= old_bytes || !t->t.entries) {
3577
+ return false;
3578
+ }
3579
+
3580
+ if (!upb_Arena_TryExtend(a, t->t.entries, old_bytes, new_bytes)) {
3581
+ return false;
3582
+ }
3583
+
3584
+ // Zero out the newly extended region of the table buffer.
3585
+ memset(t->t.entries + old_size, 0,
3586
+ (new_size - old_size) * sizeof(upb_tabent));
3453
3587
 
3588
+ // This one-past-the-end pointer is guaranteed to be distinct from NULL and
3589
+ // any valid internal collision chain pointer in the entire table.
3590
+ upb_tabent* unhashed_marker = t->t.entries + new_size;
3591
+
3592
+ // Mark all existing occupied entries as UNHASHED using the distinct
3593
+ // marker. Because e->next != NULL, these pending slots are fully protected
3594
+ // from being claimed by emptyent() during collision chain formation.
3595
+ for (size_t i = 0; i < old_size; i++) {
3596
+ upb_tabent* e = &t->t.entries[i];
3597
+ if (!upb_tabent_isempty(e)) {
3598
+ upb_tabent_setnext(e, unhashed_marker);
3599
+ }
3600
+ }
3601
+
3602
+ const uint32_t mask = new_size - 1;
3603
+ t->t.mask = mask;
3604
+ t->t.count = 0; // Reset count as insert will increment it back up
3605
+
3606
+ // Trace and resolve all destinations.
3607
+ for (size_t i = 0; i < old_size; i++) {
3608
+ upb_tabent* current = &t->t.entries[i];
3609
+ if (!upb_tabent_hasnext(current) ||
3610
+ upb_tabent_next(current) != unhashed_marker) {
3611
+ continue; // Slot is already hashed or empty.
3612
+ }
3613
+
3614
+ // Pop the leading unhashed entry to begin our trace cycle.
3615
+ upb_key tabkey = current->key;
3616
+ upb_value val = current->val;
3617
+ upb_tabent_clear(current);
3618
+
3619
+ // This inner loop clears at least one unhashed slot per iteration, for
3620
+ // total O(n) time across the whole rehash.
3621
+ while (true) {
3622
+ uint32_t hash = inthash(tabkey, val);
3623
+ upb_tabent* target_bucket = &t->t.entries[hash & mask];
3624
+
3625
+ if (upb_tabent_hasnext(target_bucket) &&
3626
+ upb_tabent_next(target_bucket) == unhashed_marker) {
3627
+ // Primary bucket contains a pending unhashed entry. Extract it, clear
3628
+ // the bucket, place our entry, and trace the evicted one.
3629
+ upb_key next_tabkey = target_bucket->key;
3630
+ upb_value next_val = target_bucket->val;
3631
+
3632
+ upb_tabent_clear(target_bucket);
3633
+
3634
+ insert(&t->t, intkey(tabkey.num), tabkey, val, hash, &inthash, &inteql);
3635
+
3636
+ tabkey = next_tabkey;
3637
+ val = next_val;
3638
+ } else {
3639
+ // Primary bucket is either empty or holds an already-hashed chain.
3640
+ // The standard insert() function perfectly resolves both cases.
3641
+ insert(&t->t, intkey(tabkey.num), tabkey, val, hash, &inthash, &inteql);
3642
+ break;
3643
+ }
3644
+ }
3645
+ }
3646
+ return true;
3647
+ }
3648
+
3649
+ bool upb_inttable_resize(upb_inttable* t, size_t size_lg2, upb_Arena* a) {
3650
+ if (t->t.entries != NULL && _upb_log2_table_size(&t->t) >= size_lg2) {
3651
+ return true;
3652
+ }
3653
+ if (t->t.entries != NULL && upb_inttable_trygrow(t, size_lg2, a)) {
3654
+ return true;
3655
+ }
3656
+
3657
+ upb_table new_table;
3658
+ if (!init(&new_table, size_lg2, a)) return false;
3659
+
3660
+ if (t->t.count > 0) {
3454
3661
  for (size_t i = begin(&t->t); i < upb_table_size(&t->t);
3455
3662
  i = next(&t->t, i)) {
3456
3663
  const upb_tabent* e = &t->t.entries[i];
3457
3664
  insert(&new_table, intkey(e->key.num), e->key, e->val,
3458
3665
  inthash(e->key, e->val), &inthash, &inteql);
3459
3666
  }
3667
+ }
3460
3668
 
3461
- UPB_ASSERT(t->t.count == new_table.count);
3669
+ UPB_ASSERT(t->t.count == new_table.count);
3670
+ t->t = new_table;
3671
+ return true;
3672
+ }
3673
+
3674
+ UPB_NOINLINE static bool upb_inttable_grow(upb_inttable* t, upb_Arena* a) {
3675
+ size_t new_size = _upb_log2_table_size(&t->t) + 1;
3676
+ return upb_inttable_resize(t, new_size, a);
3677
+ }
3462
3678
 
3463
- t->t = new_table;
3679
+ bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
3680
+ upb_Arena* a) {
3681
+ if (UPB_UNLIKELY(isfull(&t->t))) {
3682
+ if (!upb_inttable_grow(t, a)) return false;
3464
3683
  }
3465
3684
  upb_key tabkey = {.num = key};
3466
3685
  insert(&t->t, intkey(key), tabkey, val, upb_inthash(key), &inthash, &inteql);
@@ -3468,6 +3687,23 @@ bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
3468
3687
  return true;
3469
3688
  }
3470
3689
 
3690
+ bool upb_inttable_insert_or_replace_slow(upb_inttable* t, uintptr_t key,
3691
+ upb_value val, bool* replaced,
3692
+ upb_Arena* a) {
3693
+ upb_tabent* e =
3694
+ findentry_mutable(&t->t, intkey(key), upb_inthash(key), &inteql);
3695
+ if (e) {
3696
+ e->val = val;
3697
+ *replaced = true;
3698
+ return true;
3699
+ }
3700
+ *replaced = false;
3701
+ if (UPB_UNLIKELY(t->t.entries == NULL) && !upb_inttable_init(t, a)) {
3702
+ return false;
3703
+ }
3704
+ return upb_inttable_insert(t, key, val, a);
3705
+ }
3706
+
3471
3707
  bool upb_inttable_lookup(const upb_inttable* t, uintptr_t key, upb_value* v) {
3472
3708
  return lookup(&t->t, intkey(key), v, upb_inthash(key), &inteql);
3473
3709
  }
@@ -3536,9 +3772,11 @@ upb_value upb_inttable_iter_value(const upb_inttable* t, intptr_t iter) {
3536
3772
  #include <stdarg.h>
3537
3773
  #include <stddef.h>
3538
3774
  #include <stdint.h>
3775
+ #include <stdio.h>
3539
3776
  #include <stdlib.h>
3540
3777
  #include <string.h>
3541
3778
 
3779
+ #include "utf8_range.h"
3542
3780
 
3543
3781
  // Must be last.
3544
3782
 
@@ -3938,8 +4176,9 @@ static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) {
3938
4176
  size_t oldsize = *buf_end - *buf;
3939
4177
  size_t len = *end - *buf;
3940
4178
 
3941
- jsondec_checkoom(d, oldsize <= SIZE_MAX / 2);
3942
- size_t size = UPB_MAX(8, 2 * oldsize);
4179
+ size_t size;
4180
+ jsondec_checkoom(d, !upb_MulOverflow(oldsize, (size_t)2, &size));
4181
+ size = UPB_MAX(8, size);
3943
4182
 
3944
4183
  *buf = upb_Arena_Realloc(d->arena, *buf, len, size);
3945
4184
  jsondec_checkoom(d, *buf);
@@ -4849,7 +5088,7 @@ static upb_StringView jsondec_mask(jsondec* d, const char* buf,
4849
5088
  }
4850
5089
 
4851
5090
  out = upb_Arena_Malloc(d->arena, ret.size);
4852
- jsondec_checkoom(d, out || ret.size == 0);
5091
+ jsondec_checkoom(d, out);
4853
5092
  ptr = buf;
4854
5093
  ret.data = out;
4855
5094
 
@@ -5097,6 +5336,23 @@ int upb_JsonDecodeDetectingNonconformance(const char* buf, size_t size,
5097
5336
 
5098
5337
  if (size == 0) return true;
5099
5338
 
5339
+ UPB_ASSERT(!((options & upb_JsonDecode_ValidateUtf8_Disable) &&
5340
+ (options & upb_JsonDecode_ValidateUtf8_Enforce)));
5341
+
5342
+ if (!(options & upb_JsonDecode_ValidateUtf8_Disable)) {
5343
+ if (!utf8_range_IsValid(buf, size)) {
5344
+ if (options & upb_JsonDecode_ValidateUtf8_Enforce) {
5345
+ upb_Status_SetErrorMessage(status, "Invalid UTF-8 in JSON input");
5346
+ return kUpb_JsonDecodeResult_Error;
5347
+ } else {
5348
+ fprintf(
5349
+ stderr,
5350
+ "Invalid UTF-8 in JSON input. This will be rejected starting in "
5351
+ "the 2027-Q1 breaking change\n");
5352
+ }
5353
+ }
5354
+ }
5355
+
5100
5356
  d.ptr = buf;
5101
5357
  d.end = buf + size;
5102
5358
  d.arena = arena;
@@ -5166,6 +5422,9 @@ static upb_Arena* jsonenc_arena(jsonenc* e) {
5166
5422
  /* Create lazily, since it's only needed for Any */
5167
5423
  if (!e->arena) {
5168
5424
  e->arena = upb_Arena_New();
5425
+ if (!e->arena) {
5426
+ jsonenc_err(e, "Out of memory");
5427
+ }
5169
5428
  }
5170
5429
  return e->arena;
5171
5430
  }
@@ -5317,9 +5576,14 @@ static void jsonenc_enum(int32_t val, const upb_FieldDef* f, jsonenc* e) {
5317
5576
  }
5318
5577
 
5319
5578
  static void jsonenc_bytes(jsonenc* e, upb_StringView str) {
5320
- /* This is the regular base64, not the "web-safe" version. */
5321
- static const char base64[] =
5579
+ /* Regular base64 (RFC 4648 section 4) by default; the URL- and filename-safe
5580
+ * alphabet (RFC 4648 section 5) when upb_JsonEncode_WebSafeBase64 is set. */
5581
+ static const char kBase64[] =
5322
5582
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
5583
+ static const char kWebSafeBase64[] =
5584
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
5585
+ const char* base64 =
5586
+ (e->options & upb_JsonEncode_WebSafeBase64) ? kWebSafeBase64 : kBase64;
5323
5587
  const unsigned char* ptr = (unsigned char*)str.data;
5324
5588
  const unsigned char* end = UPB_PTRADD(ptr, str.size);
5325
5589
  char buf[4];
@@ -5355,43 +5619,47 @@ static void jsonenc_bytes(jsonenc* e, upb_StringView str) {
5355
5619
  jsonenc_putstr(e, "\"");
5356
5620
  }
5357
5621
 
5622
+ static void jsonenc_put_escaped_char(jsonenc* e, char ch) {
5623
+ switch (ch) {
5624
+ case '\n':
5625
+ jsonenc_putstr(e, "\\n");
5626
+ break;
5627
+ case '\r':
5628
+ jsonenc_putstr(e, "\\r");
5629
+ break;
5630
+ case '\t':
5631
+ jsonenc_putstr(e, "\\t");
5632
+ break;
5633
+ case '\"':
5634
+ jsonenc_putstr(e, "\\\"");
5635
+ break;
5636
+ case '\f':
5637
+ jsonenc_putstr(e, "\\f");
5638
+ break;
5639
+ case '\b':
5640
+ jsonenc_putstr(e, "\\b");
5641
+ break;
5642
+ case '\\':
5643
+ jsonenc_putstr(e, "\\\\");
5644
+ break;
5645
+ default:
5646
+ if ((uint8_t)ch < 0x20) {
5647
+ jsonenc_printf(e, "\\u%04x", (int)(uint8_t)ch);
5648
+ } else {
5649
+ /* This could be a non-ASCII byte. We rely on the string being valid
5650
+ * UTF-8. */
5651
+ jsonenc_putbytes(e, &ch, 1);
5652
+ }
5653
+ break;
5654
+ }
5655
+ }
5656
+
5358
5657
  static void jsonenc_stringbody(jsonenc* e, upb_StringView str) {
5359
5658
  const char* ptr = str.data;
5360
5659
  const char* end = UPB_PTRADD(ptr, str.size);
5361
5660
 
5362
5661
  while (ptr < end) {
5363
- switch (*ptr) {
5364
- case '\n':
5365
- jsonenc_putstr(e, "\\n");
5366
- break;
5367
- case '\r':
5368
- jsonenc_putstr(e, "\\r");
5369
- break;
5370
- case '\t':
5371
- jsonenc_putstr(e, "\\t");
5372
- break;
5373
- case '\"':
5374
- jsonenc_putstr(e, "\\\"");
5375
- break;
5376
- case '\f':
5377
- jsonenc_putstr(e, "\\f");
5378
- break;
5379
- case '\b':
5380
- jsonenc_putstr(e, "\\b");
5381
- break;
5382
- case '\\':
5383
- jsonenc_putstr(e, "\\\\");
5384
- break;
5385
- default:
5386
- if ((uint8_t)*ptr < 0x20) {
5387
- jsonenc_printf(e, "\\u%04x", (int)(uint8_t)*ptr);
5388
- } else {
5389
- /* This could be a non-ASCII byte. We rely on the string being valid
5390
- * UTF-8. */
5391
- jsonenc_putbytes(e, ptr, 1);
5392
- }
5393
- break;
5394
- }
5662
+ jsonenc_put_escaped_char(e, *ptr);
5395
5663
  ptr++;
5396
5664
  }
5397
5665
  }
@@ -5483,6 +5751,10 @@ static void jsonenc_any(jsonenc* e, const upb_Message* msg,
5483
5751
  const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
5484
5752
  upb_Arena* arena = jsonenc_arena(e);
5485
5753
  upb_Message* any = upb_Message_New(any_layout, arena);
5754
+ if (!any) {
5755
+ jsonenc_err(e, "Out of memory");
5756
+ return;
5757
+ }
5486
5758
 
5487
5759
  if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) !=
5488
5760
  kUpb_DecodeStatus_Ok) {
@@ -5535,7 +5807,7 @@ static void jsonenc_fieldpath(jsonenc* e, upb_StringView path) {
5535
5807
  ch = *++ptr - 32;
5536
5808
  }
5537
5809
 
5538
- jsonenc_putbytes(e, &ch, 1);
5810
+ jsonenc_put_escaped_char(e, ch);
5539
5811
  ptr++;
5540
5812
  }
5541
5813
  }
@@ -6013,6 +6285,7 @@ int upb_Unicode_ToUTF8(uint32_t cp, char* out) {
6013
6285
  }
6014
6286
 
6015
6287
 
6288
+ #include <stdint.h>
6016
6289
  #include <stdlib.h>
6017
6290
 
6018
6291
  // Must be last.
@@ -6030,9 +6303,58 @@ static void* upb_global_allocfunc(upb_alloc* alloc, void* ptr, size_t oldsize,
6030
6303
  }
6031
6304
  }
6032
6305
 
6033
- upb_alloc upb_alloc_global = {&upb_global_allocfunc};
6306
+ #ifdef UPB_ALLOCATION_COUNT
6307
+ #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
6308
+ !defined(__STDC_NO_THREADS__)) || \
6309
+ UPB_HAS_EXTENSION(c_thread_local)
6310
+ #define UPB_THREAD_LOCAL _Thread_local
6311
+ #elif defined(_MSC_VER)
6312
+ #define UPB_THREAD_LOCAL __declspec(thread)
6313
+ #elif defined(__GNUC__) || defined(__clang__)
6314
+ #define UPB_THREAD_LOCAL __thread
6315
+ #else
6316
+ #define UPB_THREAD_LOCAL
6317
+ #endif
6318
+
6319
+ UPB_THREAD_LOCAL size_t upb_arena_alloc_count = 0;
6320
+ UPB_THREAD_LOCAL size_t upb_arena_alloc_fail_on = SIZE_MAX;
6321
+
6322
+ #undef UPB_THREAD_LOCAL
6323
+ #endif
6324
+
6325
+ UPB_NODISCARD bool upb_AllocationCount_IsAvailable(void) {
6326
+ #ifdef UPB_ALLOCATION_COUNT
6327
+ return true;
6328
+ #else
6329
+ return false;
6330
+ #endif
6331
+ }
6332
+
6333
+ UPB_NODISCARD size_t upb_AllocationCount_Get(void) {
6334
+ #ifdef UPB_ALLOCATION_COUNT
6335
+ return upb_arena_alloc_count;
6336
+ #else
6337
+ return 0;
6338
+ #endif
6339
+ }
6340
+
6341
+ void upb_AllocationCount_Reset(void) {
6342
+ #ifdef UPB_ALLOCATION_COUNT
6343
+ upb_arena_alloc_count = 0;
6344
+ upb_arena_alloc_fail_on = SIZE_MAX;
6345
+ #endif
6346
+ }
6347
+
6348
+ void upb_AllocationCount_FailOn(size_t n) {
6349
+ #ifdef UPB_ALLOCATION_COUNT
6350
+ upb_arena_alloc_fail_on = n;
6351
+ #endif
6352
+ }
6353
+
6354
+ upb_alloc upb_alloc_global = {&upb_global_allocfunc, NULL};
6034
6355
 
6035
6356
 
6357
+ #include <limits.h>
6036
6358
  #include <string.h>
6037
6359
 
6038
6360
 
@@ -6102,10 +6424,6 @@ typedef struct upb_ArenaInternal {
6102
6424
  // Total space allocated in blocks, atomic only for SpaceAllocated
6103
6425
  UPB_ATOMIC(uintptr_t) space_allocated;
6104
6426
 
6105
- // The cleanup for the allocator. This is called after all the blocks are
6106
- // freed in an arena.
6107
- upb_AllocCleanupFunc* upb_alloc_cleanup;
6108
-
6109
6427
  // When multiple arenas are fused together, each arena points to a parent
6110
6428
  // arena (root points to itself). The root tracks how many live arenas
6111
6429
  // reference it.
@@ -6440,6 +6758,17 @@ void UPB_PRIVATE(_upb_Arena_UseBlock)(upb_Arena* a, void* ptr, size_t size) {
6440
6758
  size = UPB_ALIGN_DOWN(size, UPB_MALLOC_ALIGN);
6441
6759
  #endif
6442
6760
  if (size <= UPB_PRIVATE(_upb_ArenaHas)(a)) return;
6761
+
6762
+ // Harvest remaining space from the retired active block into power-of-2
6763
+ // pool bins.
6764
+ if (a->UPB_ONLYBITS(ptr) && a->UPB_ONLYBITS(end)) {
6765
+ char* curr = (char*)a->UPB_ONLYBITS(ptr);
6766
+ char* end = (char*)a->UPB_ONLYBITS(end);
6767
+ if (end > curr) {
6768
+ UPB_PRIVATE(_upb_Arena_Harvest)(a, curr, end - curr);
6769
+ }
6770
+ }
6771
+
6443
6772
  a->UPB_ONLYBITS(ptr) = ptr;
6444
6773
  a->UPB_ONLYBITS(end) = UPB_PTR_AT(ptr, size, char);
6445
6774
  UPB_PRIVATE(upb_Xsan_PoisonRegion)(ptr, size);
@@ -6524,11 +6853,62 @@ void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t span) {
6524
6853
  } else {
6525
6854
  UPB_PRIVATE(_upb_Arena_UseBlock)(a, block, block_size);
6526
6855
  UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= span);
6527
- return upb_Arena_Malloc(a, size);
6856
+ return _upb_Arena_Malloc_Unchecked(a, size);
6857
+ }
6858
+ }
6859
+
6860
+ // Having a sentinel empty pool allows us to unconditionally load the bin count,
6861
+ // avoiding a branch to check for null on the hot path.
6862
+ const UPB_PRIVATE(_upb_ArenaPool) UPB_PRIVATE(_upb_Arena_EmptyPool) = {0};
6863
+
6864
+ static size_t _upb_Arena_PoolCapacity(size_t size) {
6865
+ UPB_ASSERT(size >= sizeof(UPB_PRIVATE(_upb_ArenaPool)));
6866
+ return (size - offsetof(UPB_PRIVATE(_upb_ArenaPool), UPB_PRIVATE(bins)[0])) /
6867
+ sizeof(void*);
6868
+ }
6869
+
6870
+ void UPB_PRIVATE(_upb_Arena_GrowPool)(upb_Arena* a, void* ptr, size_t size) {
6871
+ UPB_ASSERT(a);
6872
+ UPB_ASSERT(ptr);
6873
+ UPB_PRIVATE(upb_Xsan_PoisonRegion)(ptr, size);
6874
+ UPB_ASSERT(size >= UPB_PRIVATE(kUpb_Arena_MinPoolBlockSize));
6875
+
6876
+ const size_t kMaxBins =
6877
+ (sizeof(size_t) * CHAR_BIT) - _UPB_ARENA_MIN_POOL_BIN_LG2;
6878
+ size_t new_cap = UPB_MIN(kMaxBins, _upb_Arena_PoolCapacity(size));
6879
+
6880
+ UPB_PRIVATE(_upb_ArenaPool)* new_pool =
6881
+ (UPB_PRIVATE(_upb_ArenaPool)*)UPB_PRIVATE(upb_Xsan_NewUnpoisonedRegion)(
6882
+ UPB_XSAN(a), ptr,
6883
+ UPB_SIZEOF_FLEX(UPB_PRIVATE(_upb_ArenaPool), UPB_PRIVATE(bins),
6884
+ new_cap));
6885
+ UPB_PRIVATE(_upb_ArenaPool)* old_pool = a->UPB_ONLYBITS(pool);
6886
+ size_t old_num_bins = old_pool->UPB_PRIVATE(num_bins);
6887
+
6888
+ UPB_PRIVATE(_upb_ArenaFreeBlock)** dst = new_pool->UPB_PRIVATE(bins);
6889
+ UPB_PRIVATE(_upb_ArenaFreeBlock)** src = old_pool->UPB_PRIVATE(bins);
6890
+
6891
+ size_t i;
6892
+ for (i = 0; i < old_num_bins; i++) {
6893
+ *dst++ = *src++;
6894
+ }
6895
+ if (old_pool != &UPB_PRIVATE(_upb_Arena_EmptyPool)) {
6896
+ UPB_PRIVATE(upb_Xsan_PoisonRegion)(
6897
+ old_pool, UPB_SIZEOF_FLEX(UPB_PRIVATE(_upb_ArenaPool),
6898
+ UPB_PRIVATE(bins), old_num_bins));
6899
+ }
6900
+ for (i = old_num_bins; i < new_cap; i++) {
6901
+ *dst++ = NULL;
6528
6902
  }
6903
+
6904
+ new_pool->UPB_PRIVATE(num_bins) = new_cap;
6905
+ a->UPB_ONLYBITS(pool) = new_pool;
6529
6906
  }
6530
6907
 
6531
6908
  static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6909
+ if (!upb_AllocationCount_IncrementAndCheck()) {
6910
+ return NULL;
6911
+ }
6532
6912
  if (!alloc) return NULL;
6533
6913
 
6534
6914
  // We need to malloc the initial block.
@@ -6546,6 +6926,8 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6546
6926
  a->body.size_hint = UPB_MIN(block_size, UINT32_MAX);
6547
6927
  a->head.UPB_ONLYBITS(ptr) = NULL;
6548
6928
  a->head.UPB_ONLYBITS(end) = NULL;
6929
+ a->head.UPB_ONLYBITS(pool) =
6930
+ (UPB_PRIVATE(_upb_ArenaPool)*)&UPB_PRIVATE(_upb_Arena_EmptyPool);
6549
6931
 
6550
6932
  upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1));
6551
6933
  upb_Atomic_Init(&a->body.next, NULL);
@@ -6556,7 +6938,6 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6556
6938
  #ifndef NDEBUG
6557
6939
  a->body.refs = NULL;
6558
6940
  #endif
6559
- a->body.upb_alloc_cleanup = NULL;
6560
6941
  UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(&a->body));
6561
6942
 
6562
6943
  UPB_PRIVATE(_upb_Arena_AddBlock)(&a->head, block);
@@ -6601,10 +6982,11 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
6601
6982
  #endif
6602
6983
  a->body.size_hint = 128;
6603
6984
  a->body.last_block_size = 128;
6604
- a->body.upb_alloc_cleanup = NULL;
6605
6985
  a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1);
6606
6986
  a->head.UPB_PRIVATE(ptr) = (void*)UPB_ALIGN_MALLOC((uintptr_t)(a + 1));
6607
6987
  a->head.UPB_PRIVATE(end) = UPB_PTR_AT(mem, n, char);
6988
+ a->head.UPB_ONLYBITS(pool) =
6989
+ (UPB_PRIVATE(_upb_ArenaPool)*)&UPB_PRIVATE(_upb_Arena_EmptyPool);
6608
6990
  UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(&a->body));
6609
6991
  #ifdef UPB_TRACING_ENABLED
6610
6992
  upb_Arena_LogInit(&a->head, n);
@@ -6628,7 +7010,6 @@ static void _upb_Arena_DoFree(upb_ArenaInternal* ai) {
6628
7010
  }
6629
7011
  upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai);
6630
7012
  upb_MemBlock* block = ai->blocks;
6631
- upb_AllocCleanupFunc* alloc_cleanup = ai->upb_alloc_cleanup;
6632
7013
  while (block != NULL) {
6633
7014
  // Load first since we are deleting block.
6634
7015
  upb_MemBlock* next_block = block->next;
@@ -6642,8 +7023,8 @@ static void _upb_Arena_DoFree(upb_ArenaInternal* ai) {
6642
7023
  }
6643
7024
  block = next_block;
6644
7025
  }
6645
- if (alloc_cleanup != NULL) {
6646
- alloc_cleanup(block_alloc);
7026
+ if (block_alloc && block_alloc->cleanup != NULL) {
7027
+ block_alloc->cleanup(block_alloc);
6647
7028
  }
6648
7029
  ai = next_arena;
6649
7030
  }
@@ -6795,13 +7176,6 @@ static void _upb_Arena_DoFuseArenaLists(upb_ArenaInternal* const parent,
6795
7176
  _upb_Arena_LinkBackward(child, old_parent_tail);
6796
7177
  }
6797
7178
 
6798
- void upb_Arena_SetAllocCleanup(upb_Arena* a, upb_AllocCleanupFunc* func) {
6799
- UPB_PRIVATE(upb_Xsan_AccessReadWrite)(UPB_XSAN(a));
6800
- upb_ArenaInternal* ai = upb_Arena_Internal(a);
6801
- UPB_ASSERT(ai->upb_alloc_cleanup == NULL);
6802
- ai->upb_alloc_cleanup = func;
6803
- }
6804
-
6805
7179
  // Thread safe.
6806
7180
  static upb_ArenaInternal* _upb_Arena_DoFuse(upb_ArenaInternal** ai1,
6807
7181
  upb_ArenaInternal** ai2,
@@ -7124,7 +7498,7 @@ upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
7124
7498
  upb_MessageValue ret;
7125
7499
  const char* data = upb_Array_DataPtr(arr);
7126
7500
  const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
7127
- memcpy(&ret, data + (i << lg2), 1 << lg2);
7501
+ UPB_PRIVATE(_upb_Array_CopyElem)(&ret, data + (i << lg2), lg2);
7128
7502
  return ret;
7129
7503
  }
7130
7504
 
@@ -7144,7 +7518,7 @@ void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
7144
7518
  UPB_ASSERT(i < upb_Array_Size(arr));
7145
7519
  char* data = upb_Array_MutableDataPtr(arr);
7146
7520
  const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(arr);
7147
- memcpy(data + (i << lg2), &val, 1 << lg2);
7521
+ UPB_PRIVATE(_upb_Array_CopyElem)(data + (i << lg2), &val, lg2);
7148
7522
  }
7149
7523
 
7150
7524
  bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
@@ -7184,8 +7558,8 @@ bool upb_Array_AppendAll(upb_Array* dst, const upb_Array* src,
7184
7558
  size_t src_len = upb_Array_Size(src);
7185
7559
  if (src_len == 0) return true;
7186
7560
  size_t dst_len = upb_Array_Size(dst);
7187
- size_t len = dst_len + src_len;
7188
- if (UPB_UNLIKELY(len < dst_len)) return false;
7561
+ size_t len;
7562
+ if (UPB_UNLIKELY(upb_AddOverflow(dst_len, src_len, &len))) return false;
7189
7563
  if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(dst, len, arena)) {
7190
7564
  return false;
7191
7565
  }
@@ -7211,10 +7585,11 @@ bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
7211
7585
  UPB_ASSERT(!upb_Array_IsFrozen(arr));
7212
7586
  UPB_ASSERT(arena);
7213
7587
  UPB_ASSERT(i <= arr->UPB_PRIVATE(size));
7214
- UPB_ASSERT(count + arr->UPB_PRIVATE(size) >= count);
7588
+ size_t new_size;
7589
+ const bool ok = !upb_AddOverflow(arr->UPB_PRIVATE(size), count, &new_size);
7590
+ UPB_ASSERT(ok);
7215
7591
  const size_t oldsize = arr->UPB_PRIVATE(size);
7216
- if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(
7217
- arr, arr->UPB_PRIVATE(size) + count, arena)) {
7592
+ if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(arr, new_size, arena)) {
7218
7593
  return false;
7219
7594
  }
7220
7595
  upb_Array_Move(arr, i + count, i, oldsize - i);
@@ -7227,8 +7602,9 @@ bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
7227
7602
  */
7228
7603
  void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
7229
7604
  UPB_ASSERT(!upb_Array_IsFrozen(arr));
7230
- const size_t end = i + count;
7231
- UPB_ASSERT(i <= end);
7605
+ size_t end;
7606
+ const bool ok = !upb_AddOverflow(i, count, &end);
7607
+ UPB_ASSERT(ok);
7232
7608
  UPB_ASSERT(end <= arr->UPB_PRIVATE(size));
7233
7609
  upb_Array_Move(arr, i, end, arr->UPB_PRIVATE(size) - end);
7234
7610
  arr->UPB_PRIVATE(size) -= count;
@@ -7252,32 +7628,43 @@ bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
7252
7628
 
7253
7629
  bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity,
7254
7630
  upb_Arena* arena) {
7255
- size_t new_capacity = UPB_MAX(array->UPB_PRIVATE(capacity), 4);
7631
+ size_t target_capacity = UPB_MAX(min_capacity, 4);
7632
+ size_t new_capacity = upb_RoundUpToPowerOfTwo(target_capacity);
7633
+ if (new_capacity == SIZE_MAX) return false;
7634
+
7256
7635
  const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(array);
7257
7636
  size_t old_bytes = array->UPB_PRIVATE(capacity) << lg2;
7258
7637
  void* ptr = upb_Array_MutableDataPtr(array);
7259
-
7260
- // Log2 ceiling of size.
7261
- while (new_capacity < min_capacity) {
7262
- if (upb_ShlOverflow(&new_capacity, 1)) {
7263
- new_capacity = SIZE_MAX;
7264
- break;
7265
- }
7266
- }
7267
-
7268
- // If capacity doubling overflowed to SIZE_MAX, fail. No valid array can hold
7269
- // SIZE_MAX elements, and downstream size calculations would overflow.
7270
- if (new_capacity == SIZE_MAX) return false;
7638
+ UPB_ASSERT(ptr);
7271
7639
 
7272
7640
  size_t new_bytes = new_capacity;
7273
7641
  if (upb_ShlOverflow(&new_bytes, lg2)) {
7274
7642
  return false;
7275
7643
  }
7276
- ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes);
7277
- if (!ptr) return false;
7644
+ if (upb_Arena_TryExtend(arena, ptr, old_bytes, new_bytes)) {
7645
+ array->UPB_PRIVATE(capacity) = new_capacity;
7646
+ } else {
7647
+ size_t pool_bytes =
7648
+ UPB_MAX(new_bytes, UPB_PRIVATE(kUpb_Arena_MinPoolBlockSize));
7649
+
7650
+ void* new_ptr = upb_Arena_AllocPool(arena, pool_bytes);
7651
+ if (!new_ptr) return false;
7652
+
7653
+ if (old_bytes > 0) {
7654
+ memcpy(new_ptr, ptr, old_bytes);
7655
+ }
7656
+
7657
+ const size_t array_size =
7658
+ UPB_ALIGN_UP(sizeof(struct upb_Array), UPB_MALLOC_ALIGN);
7659
+ bool is_contiguous = (ptr == UPB_PTR_AT(array, array_size, void));
7660
+ if (!is_contiguous) {
7661
+ UPB_PRIVATE(_upb_Arena_Harvest)(arena, ptr, old_bytes);
7662
+ }
7278
7663
 
7279
- UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2);
7280
- array->UPB_PRIVATE(capacity) = new_capacity;
7664
+ ptr = new_ptr;
7665
+ UPB_PRIVATE(_upb_Array_SetTaggedPtr)(array, ptr, lg2);
7666
+ array->UPB_PRIVATE(capacity) = pool_bytes >> lg2;
7667
+ }
7281
7668
  return true;
7282
7669
  }
7283
7670
 
@@ -7376,12 +7763,13 @@ upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
7376
7763
  bool upb_Map_Delete(upb_Map* map, upb_MessageValue key, upb_MessageValue* val) {
7377
7764
  upb_value v;
7378
7765
  const bool removed = _upb_Map_Delete(map, &key, map->key_size, &v);
7379
- if (val) _upb_map_fromvalue(v, val, map->val_size);
7766
+ if (removed && val) _upb_map_fromvalue(v, val, map->val_size);
7380
7767
  return removed;
7381
7768
  }
7382
7769
 
7383
7770
  bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
7384
7771
  upb_MessageValue* val, size_t* iter) {
7772
+ if (_upb_Map_Size(map) == 0) return false;
7385
7773
  upb_value v;
7386
7774
  bool ret;
7387
7775
  if (map->UPB_PRIVATE(is_strtable)) {
@@ -7394,7 +7782,7 @@ bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
7394
7782
  uintptr_t intkey;
7395
7783
  ret = upb_inttable_next(&map->t.inttable, &intkey, &v, (intptr_t*)iter);
7396
7784
  if (ret) {
7397
- memcpy(key, &intkey, map->key_size);
7785
+ _upb_map_memcpy(key, &intkey, map->key_size);
7398
7786
  }
7399
7787
  }
7400
7788
  if (ret) {
@@ -7418,18 +7806,6 @@ bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
7418
7806
  return _upb_map_next(map, iter);
7419
7807
  }
7420
7808
 
7421
- bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
7422
- UPB_ASSERT(iter != kUpb_Map_Begin);
7423
- if (map->UPB_PRIVATE(is_strtable)) {
7424
- upb_strtable_iter i;
7425
- i.t = &map->t.strtable;
7426
- i.index = iter;
7427
- return upb_strtable_done(&i);
7428
- } else {
7429
- return upb_inttable_done(&map->t.inttable, iter);
7430
- }
7431
- }
7432
-
7433
7809
  // Returns the key and value for this entry of the map.
7434
7810
  upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
7435
7811
  upb_MessageValue ret;
@@ -7440,7 +7816,7 @@ upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
7440
7816
  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
7441
7817
  } else {
7442
7818
  uintptr_t intkey = upb_inttable_iter_key(&map->t.inttable, iter);
7443
- memcpy(&ret, &intkey, map->key_size);
7819
+ _upb_map_memcpy(&ret, &intkey, map->key_size);
7444
7820
  }
7445
7821
  return ret;
7446
7822
  }
@@ -7465,7 +7841,7 @@ void upb_Map_Freeze(upb_Map* map, const upb_MiniTable* m) {
7465
7841
  if (upb_Map_IsFrozen(map)) return;
7466
7842
  UPB_PRIVATE(_upb_Map_ShallowFreeze)(map);
7467
7843
 
7468
- if (m) {
7844
+ if (m && _upb_Map_Size(map) > 0) {
7469
7845
  size_t iter = kUpb_Map_Begin;
7470
7846
  upb_MessageValue key, val;
7471
7847
 
@@ -7481,11 +7857,10 @@ upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
7481
7857
  upb_Map* map = upb_Arena_Malloc(a, sizeof(upb_Map));
7482
7858
  if (!map) return NULL;
7483
7859
 
7860
+ memset(&map->t, 0, sizeof(map->t));
7484
7861
  if (key_size <= sizeof(uintptr_t) && key_size != UPB_MAPTYPE_STRING) {
7485
- if (!upb_inttable_init(&map->t.inttable, a)) return NULL;
7486
7862
  map->UPB_PRIVATE(is_strtable) = false;
7487
7863
  } else {
7488
- if (!upb_strtable_init(&map->t.strtable, 4, a)) return NULL;
7489
7864
  map->UPB_PRIVATE(is_strtable) = true;
7490
7865
  }
7491
7866
  map->key_size = key_size;
@@ -7495,6 +7870,29 @@ upb_Map* _upb_Map_New(upb_Arena* a, size_t key_size, size_t value_size) {
7495
7870
  return map;
7496
7871
  }
7497
7872
 
7873
+ bool _upb_Map_Reserve(upb_Map* map, size_t size, upb_Arena* arena) {
7874
+ UPB_ASSERT(!upb_Map_IsFrozen(map));
7875
+ if (size == 0) return true;
7876
+
7877
+ size_t target = _upb_entries_needed_for(size);
7878
+ if (target < 8) target = 8;
7879
+ int size_lg2 = upb_Log2Ceiling(target);
7880
+
7881
+ if (_upb_Map_Capacity(map) >= ((size_t)1 << size_lg2)) {
7882
+ return true;
7883
+ }
7884
+
7885
+ if (map->UPB_PRIVATE(is_strtable)) {
7886
+ return upb_strtable_resize(&map->t.strtable, size_lg2, arena);
7887
+ } else {
7888
+ return upb_inttable_resize(&map->t.inttable, size_lg2, arena);
7889
+ }
7890
+ }
7891
+
7892
+ bool upb_Map_Reserve(upb_Map* map, size_t size, upb_Arena* arena) {
7893
+ return _upb_Map_Reserve(map, size, arena);
7894
+ }
7895
+
7498
7896
 
7499
7897
  #include <stdint.h>
7500
7898
  #include <stdlib.h>
@@ -7635,8 +8033,8 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
7635
8033
  static int _upb_mapsorter_cmpext(const void* _a, const void* _b) {
7636
8034
  const upb_Extension* const* a = _a;
7637
8035
  const upb_Extension* const* b = _b;
7638
- uint32_t a_num = upb_MiniTableExtension_Number((*a)->ext);
7639
- uint32_t b_num = upb_MiniTableExtension_Number((*b)->ext);
8036
+ uint32_t a_num = upb_MiniTableField_Number(upb_Extension_MiniTableField(*a));
8037
+ uint32_t b_num = upb_MiniTableField_Number(upb_Extension_MiniTableField(*b));
7640
8038
  UPB_ASSERT(a_num != b_num);
7641
8039
  return a_num < b_num ? -1 : 1;
7642
8040
  }
@@ -7698,8 +8096,8 @@ UPB_NOINLINE bool UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(upb_Message* msg,
7698
8096
  // represents the end of that allocation.
7699
8097
  size_t prev_alloc_size =
7700
8098
  (existing->data + existing->size) - (char*)existing;
7701
- if (SIZE_MAX - prev_alloc_size >= len) {
7702
- size_t new_alloc_size = prev_alloc_size + len;
8099
+ size_t new_alloc_size;
8100
+ if (!upb_AddOverflow(prev_alloc_size, len, &new_alloc_size)) {
7703
8101
  if (upb_Arena_TryExtend(arena, existing, prev_alloc_size,
7704
8102
  new_alloc_size)) {
7705
8103
  memcpy(UPB_PTR_AT(existing, prev_alloc_size, void), data, len);
@@ -7722,8 +8120,9 @@ UPB_NOINLINE bool UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(upb_Message* msg,
7722
8120
  if (!view) return false;
7723
8121
  view->data = data;
7724
8122
  } else {
7725
- if (SIZE_MAX - sizeof(upb_StringView) < len) return false;
7726
- view = upb_Arena_Malloc(arena, sizeof(upb_StringView) + len);
8123
+ size_t total_size;
8124
+ if (upb_AddOverflow(sizeof(upb_StringView), len, &total_size)) return false;
8125
+ view = upb_Arena_Malloc(arena, total_size);
7727
8126
  if (!view) return false;
7728
8127
  char* copy = UPB_PTR_AT(view, sizeof(upb_StringView), char);
7729
8128
  memcpy(copy, data, len);
@@ -7745,10 +8144,9 @@ bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg,
7745
8144
  UPB_ASSERT(count > 0);
7746
8145
  size_t total_len = 0;
7747
8146
  for (size_t i = 0; i < count; i++) {
7748
- if (SIZE_MAX - total_len < data[i].size) {
8147
+ if (upb_AddOverflow(total_len, data[i].size, &total_len)) {
7749
8148
  return false;
7750
8149
  }
7751
- total_len += data[i].size;
7752
8150
  }
7753
8151
 
7754
8152
  {
@@ -7760,8 +8158,8 @@ bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg,
7760
8158
  if (!upb_TaggedAuxPtr_IsUnknownAliased(ptr)) {
7761
8159
  size_t prev_alloc_size =
7762
8160
  (existing->data + existing->size) - (char*)existing;
7763
- if (SIZE_MAX - prev_alloc_size >= total_len) {
7764
- size_t new_alloc_size = prev_alloc_size + total_len;
8161
+ size_t new_alloc_size;
8162
+ if (!upb_AddOverflow(prev_alloc_size, total_len, &new_alloc_size)) {
7765
8163
  if (upb_Arena_TryExtend(arena, existing, prev_alloc_size,
7766
8164
  new_alloc_size)) {
7767
8165
  char* copy = UPB_PTR_AT(existing, prev_alloc_size, char);
@@ -7778,11 +8176,13 @@ bool UPB_PRIVATE(_upb_Message_AddUnknownV)(struct upb_Message* msg,
7778
8176
  }
7779
8177
  }
7780
8178
 
7781
- if (SIZE_MAX - sizeof(upb_StringView) < total_len) return false;
8179
+ size_t total_size;
8180
+ if (upb_AddOverflow(sizeof(upb_StringView), total_len, &total_size)) {
8181
+ return false;
8182
+ }
7782
8183
  if (!UPB_PRIVATE(_upb_Message_ReserveSlot)(msg, arena)) return false;
7783
8184
 
7784
- upb_StringView* view =
7785
- upb_Arena_Malloc(arena, sizeof(upb_StringView) + total_len);
8185
+ upb_StringView* view = upb_Arena_Malloc(arena, total_size);
7786
8186
  if (!view) return false;
7787
8187
  char* copy = UPB_PTR_AT(view, sizeof(upb_StringView), char);
7788
8188
  view->data = copy;
@@ -7805,6 +8205,7 @@ void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
7805
8205
  uint32_t size = 0;
7806
8206
  for (uint32_t i = 0; i < in->size; i++) {
7807
8207
  upb_TaggedAuxPtr tagged_ptr = in->aux_data[i];
8208
+ // Only keep semantically known fields (i.e., canonical extensions).
7808
8209
  if (upb_TaggedAuxPtr_IsSemanticallyKnown(tagged_ptr)) {
7809
8210
  in->aux_data[size++] = tagged_ptr;
7810
8211
  }
@@ -7812,26 +8213,6 @@ void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
7812
8213
  in->size = size;
7813
8214
  }
7814
8215
 
7815
- upb_Message_DeleteUnknownStatus upb_Message_DeleteUnknown(upb_Message* msg,
7816
- upb_StringView* data,
7817
- uintptr_t* iter,
7818
- upb_Arena* arena) {
7819
- upb_MessageUnknown unknown;
7820
- unknown.type = kUpb_MessageUnknownType_StringView;
7821
- unknown.value.bytes = *data;
7822
-
7823
- upb_Message_DeleteUnknownStatus res =
7824
- upb_Message_DeleteUnknown2(msg, &unknown, iter, arena);
7825
- UPB_ASSERT(unknown.type == kUpb_MessageUnknownType_StringView);
7826
- if (res == kUpb_DeleteUnknown_IterUpdated ||
7827
- res == kUpb_DeleteUnknown_DeletedLast) {
7828
- // the unknown data remains the same on the result of
7829
- // kUpb_DeleteUnknown_AllocFail.
7830
- *data = unknown.value.bytes;
7831
- }
7832
- return res;
7833
- }
7834
-
7835
8216
  size_t upb_Message_ExtensionCount(const upb_Message* msg) {
7836
8217
  upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
7837
8218
  if (!in) return 0;
@@ -7886,20 +8267,13 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
7886
8267
  // TODO: b/376969853 - use iterator API
7887
8268
  uint32_t size = in ? in->size : 0;
7888
8269
  for (size_t i = 0; i < size; i++) {
7889
- upb_TaggedAuxPtr tagged_ptr = in->aux_data[i];
7890
- upb_TaggedAux aux;
7891
- upb_TaggedAuxType type = upb_TaggedAux_Get(tagged_ptr, &aux);
7892
- if (type != kUpb_TaggedAuxType_CanonicalExtension &&
7893
- type != kUpb_TaggedAuxType_NonCanonicalExtension) {
7894
- continue;
7895
- }
7896
- const upb_Extension* ext = aux.extension;
7897
- const upb_MiniTableExtension* e = ext->ext;
7898
- const upb_MiniTableField* f = &e->UPB_PRIVATE(field);
7899
- const upb_MiniTable* m2 = upb_MiniTableExtension_GetSubMessage(e);
8270
+ const upb_Extension* ext =
8271
+ upb_TaggedAuxPtr_TryGetExtension(in->aux_data[i]);
8272
+ if (!ext) continue;
8273
+ const upb_MiniTableField* f = upb_Extension_MiniTableField(ext);
8274
+ const upb_MiniTable* m2 = upb_MiniTable_SubMessage(f);
7900
8275
 
7901
- upb_MessageValue val;
7902
- memcpy(&val, &(ext->data), sizeof(upb_MessageValue));
8276
+ upb_MessageValue val = upb_Extension_GetValue(ext);
7903
8277
 
7904
8278
  switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f)) {
7905
8279
  case kUpb_FieldMode_Array: {
@@ -7920,6 +8294,25 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
7920
8294
  }
7921
8295
  }
7922
8296
 
8297
+ bool upb_Message_NextSerializableField(const upb_Message* msg,
8298
+ const upb_MiniTable* mt,
8299
+ const upb_MiniTableField** f,
8300
+ uintptr_t* iter) {
8301
+ const size_t field_count = upb_MiniTable_FieldCount(mt);
8302
+ uintptr_t i = *iter;
8303
+ while (i < field_count) {
8304
+ const upb_MiniTableField* field = upb_MiniTable_GetFieldByIndex(mt, i);
8305
+ if (UPB_PRIVATE(_upb_Message_FieldIsSet)(msg, field)) {
8306
+ *f = field;
8307
+ *iter = i + 1;
8308
+ return true;
8309
+ }
8310
+ i++;
8311
+ }
8312
+ *iter = i;
8313
+ return false;
8314
+ }
8315
+
7923
8316
 
7924
8317
  #include <stddef.h>
7925
8318
  #include <stdint.h>
@@ -7928,6 +8321,33 @@ void upb_Message_Freeze(upb_Message* msg, const upb_MiniTable* m) {
7928
8321
 
7929
8322
  // Must be last.
7930
8323
 
8324
+ bool upb_Message_NextWireFormatUnknown(const struct upb_Message* msg,
8325
+ struct upb_Arena** arena,
8326
+ upb_StringView* data, uintptr_t* iter) {
8327
+ upb_MessageUnknown unknown;
8328
+ if (!upb_Message_NextUnknown2(msg, &unknown, iter)) {
8329
+ return false;
8330
+ }
8331
+ if (unknown.type == kUpb_MessageUnknownType_StringView) {
8332
+ *data = unknown.value.bytes;
8333
+ return true;
8334
+ }
8335
+ UPB_ASSERT(unknown.type == kUpb_MessageUnknownType_NonCanonicalExtension);
8336
+ if (!*arena) {
8337
+ *arena = upb_Arena_New();
8338
+ if (!*arena) {
8339
+ return false;
8340
+ }
8341
+ }
8342
+ upb_EncodeStatus status =
8343
+ upb_EncodeExtension(unknown.value.extension, *arena, data,
8344
+ /*encode_options=*/0);
8345
+ if (status != kUpb_EncodeStatus_Ok) {
8346
+ return false;
8347
+ }
8348
+ return true;
8349
+ }
8350
+
7931
8351
  static upb_FindUnknownRet2 upb_FindUnknownRet2_ParseError(void) {
7932
8352
  return (upb_FindUnknownRet2){.status = kUpb_FindUnknown_ParseError};
7933
8353
  }
@@ -7967,8 +8387,8 @@ upb_FindUnknownRet2 upb_Message_FindUnknown2(const struct upb_Message* msg,
7967
8387
  }
7968
8388
  } else if (ret.unknown.type ==
7969
8389
  kUpb_MessageUnknownType_NonCanonicalExtension) {
7970
- uint32_t ext_field_number =
7971
- upb_MiniTableExtension_Number(ret.unknown.value.extension->ext);
8390
+ uint32_t ext_field_number = upb_MiniTableField_Number(
8391
+ upb_Extension_MiniTableField(ret.unknown.value.extension));
7972
8392
  if (ext_field_number == field_number) {
7973
8393
  ret.status = kUpb_FindUnknown_Ok;
7974
8394
  return ret;
@@ -8052,9 +8472,28 @@ upb_Message_DeleteUnknownStatus upb_Message_DeleteUnknown2(
8052
8472
  suffix->size = (prefix->data + prefix->size) - suffix->data;
8053
8473
  prefix->size = data_bytes->data - prefix->data;
8054
8474
  }
8055
- return upb_Message_NextUnknown2(msg, data, iter)
8056
- ? kUpb_DeleteUnknown_IterUpdated
8057
- : kUpb_DeleteUnknown_DeletedLast;
8475
+ return upb_Message_NextUnknown2(msg, data, iter)
8476
+ ? kUpb_DeleteUnknown_IterUpdated
8477
+ : kUpb_DeleteUnknown_DeletedLast;
8478
+ }
8479
+
8480
+ upb_Message_DeleteUnknownStatus upb_Message_DeleteUnknown(
8481
+ struct upb_Message* msg, upb_StringView* data, uintptr_t* iter,
8482
+ struct upb_Arena* arena) {
8483
+ upb_MessageUnknown unknown;
8484
+ unknown.type = kUpb_MessageUnknownType_StringView;
8485
+ unknown.value.bytes = *data;
8486
+
8487
+ upb_Message_DeleteUnknownStatus res =
8488
+ upb_Message_DeleteUnknown2(msg, &unknown, iter, arena);
8489
+ UPB_ASSERT(unknown.type == kUpb_MessageUnknownType_StringView);
8490
+ if (res == kUpb_DeleteUnknown_IterUpdated ||
8491
+ res == kUpb_DeleteUnknown_DeletedLast) {
8492
+ // the unknown data remains the same on the result of
8493
+ // kUpb_DeleteUnknown_AllocFail.
8494
+ *data = unknown.value.bytes;
8495
+ }
8496
+ return res;
8058
8497
  }
8059
8498
 
8060
8499
 
@@ -8104,10 +8543,15 @@ static bool _upb_Map_IsEqual(const upb_Map* map1, const upb_Map* map2,
8104
8543
  // Check for trivial equality.
8105
8544
  if (map1 == map2) return true;
8106
8545
 
8107
- // Must have identical element counts.
8546
+ // Must have identical element counts, unless we are doing a partial
8547
+ // comparison.
8108
8548
  size_t size1 = map1 ? upb_Map_Size(map1) : 0;
8109
8549
  size_t size2 = map2 ? upb_Map_Size(map2) : 0;
8110
- if (size1 != size2) return false;
8550
+ if (options & kUpb_CompareOption_Partial) {
8551
+ if (size1 < size2) return false;
8552
+ } else {
8553
+ if (size1 != size2) return false;
8554
+ }
8111
8555
 
8112
8556
  const upb_MiniTableField* f = upb_MiniTable_MapValue(m);
8113
8557
  const upb_MiniTable* m2_value = upb_MiniTable_SubMessage(f);
@@ -8115,8 +8559,8 @@ static bool _upb_Map_IsEqual(const upb_Map* map1, const upb_Map* map2,
8115
8559
 
8116
8560
  upb_MessageValue key, val1, val2;
8117
8561
  size_t iter = kUpb_Map_Begin;
8118
- while (upb_Map_Next(map1, &key, &val1, &iter)) {
8119
- if (!upb_Map_Get(map2, key, &val2)) return false;
8562
+ while (upb_Map_Next(map2, &key, &val2, &iter)) {
8563
+ if (!upb_Map_Get(map1, key, &val1)) return false;
8120
8564
  if (!upb_MessageValue_IsEqual(val1, val2, ctype, m2_value, options))
8121
8565
  return false;
8122
8566
  }
@@ -8124,10 +8568,65 @@ static bool _upb_Map_IsEqual(const upb_Map* map1, const upb_Map* map2,
8124
8568
  return true;
8125
8569
  }
8126
8570
 
8571
+ static bool _upb_Message_BaseFieldsArePartiallyEqual(const upb_Message* msg1,
8572
+ const upb_Message* msg2,
8573
+ const upb_MiniTable* m,
8574
+ int options) {
8575
+ size_t iter2 = kUpb_BaseField_Begin;
8576
+ const upb_MiniTableField* f2;
8577
+ upb_MessageValue val2;
8578
+
8579
+ // Iterate through all base fields present/set in msg2 (expected).
8580
+ while (UPB_PRIVATE(_upb_Message_NextBaseField)(msg2, m, &f2, &val2, &iter2)) {
8581
+ // Get the corresponding field data from msg1 (actual).
8582
+ const void* src1 = UPB_PRIVATE(_upb_Message_DataPtr)(msg1, f2);
8583
+ upb_MessageValue val1;
8584
+ UPB_PRIVATE(_upb_MiniTableField_DataCopy)(f2, &val1, src1);
8585
+
8586
+ // Verify presence in msg1 (actual):
8587
+ // - For fields with explicit presence, msg1 must also have the field set.
8588
+ // - For non-presence fields (proto3 scalars), msg1's field must not be
8589
+ // zero/default.
8590
+ if (upb_MiniTableField_HasPresence(f2)) {
8591
+ if (!upb_Message_HasBaseField(msg1, f2)) return false;
8592
+ } else {
8593
+ if (UPB_PRIVATE(_upb_MiniTableField_DataIsZero)(f2, src1)) return false;
8594
+ }
8595
+
8596
+ const upb_MiniTable* subm = upb_MiniTable_SubMessage(f2);
8597
+ const upb_CType ctype = upb_MiniTableField_CType(f2);
8598
+
8599
+ // Compare field values according to the field mode (array, map, or
8600
+ // scalar), passing comparison options recursively for submessages.
8601
+ bool eq;
8602
+ switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(f2)) {
8603
+ case kUpb_FieldMode_Array:
8604
+ eq = _upb_Array_IsEqual(val1.array_val, val2.array_val, ctype, subm,
8605
+ options);
8606
+ break;
8607
+ case kUpb_FieldMode_Map:
8608
+ eq = _upb_Map_IsEqual(val1.map_val, val2.map_val, subm, options);
8609
+ break;
8610
+ case kUpb_FieldMode_Scalar:
8611
+ eq = upb_MessageValue_IsEqual(val1, val2, ctype, subm, options);
8612
+ break;
8613
+ }
8614
+ if (!eq) return false;
8615
+ }
8616
+ return true;
8617
+ }
8618
+
8127
8619
  static bool _upb_Message_BaseFieldsAreEqual(const upb_Message* msg1,
8128
8620
  const upb_Message* msg2,
8129
8621
  const upb_MiniTable* m,
8130
8622
  int options) {
8623
+ // In partial comparison mode, we only check fields that are present in msg2
8624
+ // (the expected message). Any extra fields present in msg1 (the actual
8625
+ // message) are ignored.
8626
+ if (options & kUpb_CompareOption_Partial) {
8627
+ return _upb_Message_BaseFieldsArePartiallyEqual(msg1, msg2, m, options);
8628
+ }
8629
+
8131
8630
  // Iterate over all base fields for each message.
8132
8631
  // The order will always match if the messages are equal.
8133
8632
  size_t iter1 = kUpb_BaseField_Begin;
@@ -8171,18 +8670,18 @@ static bool _upb_Message_ExtensionsAreEqual(const upb_Message* msg1,
8171
8670
  const upb_MiniTable* m,
8172
8671
  int options) {
8173
8672
  const upb_MiniTableExtension* e;
8174
- upb_MessageValue val1;
8673
+ upb_MessageValue val2;
8175
8674
 
8176
- // Iterate over all extensions for msg1, and search msg2 for each extension.
8675
+ // Iterate over all extensions for msg2, and search msg1 for each extension.
8177
8676
  size_t count1 = 0;
8178
- size_t iter1 = kUpb_Message_ExtensionBegin;
8179
- while (upb_Message_NextExtension(msg1, &e, &val1, &iter1)) {
8180
- const upb_Extension* ext2 = UPB_PRIVATE(_upb_Message_Getext)(msg2, e);
8181
- if (!ext2) return false;
8677
+ size_t iter2 = kUpb_Message_ExtensionBegin;
8678
+ while (upb_Message_NextExtension(msg2, &e, &val2, &iter2)) {
8679
+ const upb_Extension* ext1 = UPB_PRIVATE(_upb_Message_Getext)(msg1, e);
8680
+ if (!ext1) return false;
8182
8681
 
8183
8682
  count1++;
8184
8683
 
8185
- const upb_MessageValue val2 = ext2->data;
8684
+ const upb_MessageValue val1 = upb_Extension_GetValue(ext1);
8186
8685
  const upb_MiniTableField* f = &e->UPB_PRIVATE(field);
8187
8686
  const upb_MiniTable* subm = upb_MiniTableField_IsSubMessage(f)
8188
8687
  ? upb_MiniTableExtension_GetSubMessage(e)
@@ -8206,9 +8705,11 @@ static bool _upb_Message_ExtensionsAreEqual(const upb_Message* msg1,
8206
8705
  if (!eq) return false;
8207
8706
  }
8208
8707
 
8209
- // Must have identical extension counts (this catches the case where msg2
8210
- // has extensions that msg1 doesn't).
8211
- if (count1 != upb_Message_ExtensionCount(msg2)) return false;
8708
+ if (!(options & kUpb_CompareOption_Partial)) {
8709
+ // Must have identical extension counts (this catches the case where msg1
8710
+ // has extensions that msg2 doesn't).
8711
+ if (count1 != upb_Message_ExtensionCount(msg1)) return false;
8712
+ }
8212
8713
 
8213
8714
  return true;
8214
8715
  }
@@ -8223,13 +8724,16 @@ bool upb_Message_IsEqual(const upb_Message* msg1, const upb_Message* msg2,
8223
8724
  if (!(options & kUpb_CompareOption_IncludeUnknownFields)) return true;
8224
8725
 
8225
8726
  // The wire encoder enforces a maximum depth of 100 so we match that here.
8226
- return UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)(msg1, msg2, 100) ==
8727
+ return _upb_Message_UnknownFieldsAreEqual(msg1, msg2, 100) ==
8227
8728
  kUpb_UnknownCompareResult_Equal;
8228
8729
  }
8229
8730
 
8230
8731
 
8732
+ #include <setjmp.h>
8231
8733
  #include <stdint.h>
8734
+ #include <stdio.h>
8232
8735
  #include <stdlib.h>
8736
+ #include <string.h>
8233
8737
 
8234
8738
 
8235
8739
  // Must be last.
@@ -8255,6 +8759,7 @@ struct upb_UnknownFields {
8255
8759
 
8256
8760
  typedef struct {
8257
8761
  upb_EpsCopyInputStream stream;
8762
+ upb_encstate encoder; // For encoding non-canonical extensions.
8258
8763
  upb_Arena* arena;
8259
8764
  upb_UnknownField* tmp;
8260
8765
  size_t tmp_size;
@@ -8282,10 +8787,17 @@ static void upb_UnknownFields_Grow(upb_UnknownField_Context* ctx,
8282
8787
  upb_UnknownField** ptr,
8283
8788
  upb_UnknownField** end) {
8284
8789
  size_t old = (*ptr - *base);
8285
- size_t new = UPB_MAX(4, old * 2);
8790
+ size_t new;
8791
+ if (upb_MulOverflow((uint32_t)2, old, &new)) {
8792
+ upb_UnknownFields_OutOfMemory(ctx);
8793
+ }
8794
+ new = UPB_MAX(4, new);
8795
+ size_t new_bytes;
8796
+ if (upb_MulOverflow(new, sizeof(**base), &new_bytes)) {
8797
+ upb_UnknownFields_OutOfMemory(ctx);
8798
+ }
8286
8799
 
8287
- *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base),
8288
- new * sizeof(**base));
8800
+ *base = upb_Arena_Realloc(ctx->arena, *base, old * sizeof(**base), new_bytes);
8289
8801
  if (!*base) upb_UnknownFields_OutOfMemory(ctx);
8290
8802
 
8291
8803
  *ptr = *base + old;
@@ -8333,11 +8845,25 @@ static void upb_UnknownFields_SortRecursive(upb_UnknownField* arr, size_t start,
8333
8845
  static void upb_UnknownFields_Sort(upb_UnknownField_Context* ctx,
8334
8846
  upb_UnknownFields* fields) {
8335
8847
  if (ctx->tmp_size < fields->size) {
8336
- const int oldsize = ctx->tmp_size * sizeof(*ctx->tmp);
8848
+ size_t oldsize;
8849
+ if (upb_MulOverflow(sizeof(*ctx->tmp), ctx->tmp_size, &oldsize)) {
8850
+ upb_UnknownFields_OutOfMemory(ctx);
8851
+ }
8337
8852
  ctx->tmp_size = UPB_MAX(8, ctx->tmp_size);
8338
- while (ctx->tmp_size < fields->size) ctx->tmp_size *= 2;
8339
- const int newsize = ctx->tmp_size * sizeof(*ctx->tmp);
8340
- ctx->tmp = upb_grealloc(ctx->tmp, oldsize, newsize);
8853
+ while (ctx->tmp_size < fields->size) {
8854
+ if (upb_MulOverflow((uint32_t)2, ctx->tmp_size, &ctx->tmp_size)) {
8855
+ upb_UnknownFields_OutOfMemory(ctx);
8856
+ }
8857
+ }
8858
+ size_t newsize;
8859
+ if (upb_MulOverflow(ctx->tmp_size, sizeof(*ctx->tmp), &newsize)) {
8860
+ upb_UnknownFields_OutOfMemory(ctx);
8861
+ }
8862
+ upb_UnknownField* tmp = upb_grealloc(ctx->tmp, oldsize, newsize);
8863
+ if (!tmp) {
8864
+ upb_UnknownFields_OutOfMemory(ctx);
8865
+ }
8866
+ ctx->tmp = tmp;
8341
8867
  }
8342
8868
  upb_UnknownFields_SortRecursive(fields->fields, 0, fields->size, ctx->tmp);
8343
8869
  }
@@ -8463,11 +8989,37 @@ static upb_UnknownFields* upb_UnknownFields_Build(upb_UnknownField_Context* ctx,
8463
8989
  .last_tag = 0,
8464
8990
  };
8465
8991
  uintptr_t iter = kUpb_Message_UnknownBegin;
8466
- upb_StringView view;
8467
- while (upb_Message_NextUnknown(msg, &view, &iter)) {
8468
- upb_EpsCopyInputStream_Init(&ctx->stream, &view.data, view.size);
8469
- upb_CombineUnknownFields(ctx, &builder, &view.data);
8470
- UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &view.data) &&
8992
+ upb_MessageUnknown data;
8993
+ while (upb_Message_NextUnknown2(msg, &data, &iter)) {
8994
+ const char* ptr;
8995
+ size_t size;
8996
+ if (data.type == kUpb_MessageUnknownType_StringView) {
8997
+ upb_StringView view = data.value.bytes;
8998
+ ptr = view.data;
8999
+ size = view.size;
9000
+ } else {
9001
+ UPB_ASSERT(data.type == kUpb_MessageUnknownType_NonCanonicalExtension);
9002
+ char* enc_buf = upb_BackAlloc_Init(&ctx->encoder.alloc, ctx->arena);
9003
+ ctx->encoder.status = kUpb_EncodeStatus_Ok;
9004
+ // Encode non-canonical extension to buffer.
9005
+ const upb_Extension* ext = (const upb_Extension*)data.value.extension;
9006
+ bool is_message_set = false;
9007
+ const upb_MiniTableExtension* ext_mt =
9008
+ upb_Extension_MiniTableExtension(ext);
9009
+ const upb_MiniTable* extendee = upb_MiniTableExtension_Extendee(ext_mt);
9010
+ if (extendee) {
9011
+ is_message_set = upb_MiniTable_IsMessageSet(extendee);
9012
+ }
9013
+ UPB_PRIVATE(_upb_Encode_Extension)(&ctx->encoder, ext_mt,
9014
+ upb_Extension_GetValue(ext),
9015
+ is_message_set, &enc_buf, &size,
9016
+ /*options=*/0);
9017
+ ptr = enc_buf;
9018
+ }
9019
+
9020
+ upb_EpsCopyInputStream_Init(&ctx->stream, &ptr, size);
9021
+ upb_CombineUnknownFields(ctx, &builder, &ptr);
9022
+ UPB_ASSERT(upb_EpsCopyInputStream_IsDone(&ctx->stream, &ptr) &&
8471
9023
  !upb_EpsCopyInputStream_IsError(&ctx->stream));
8472
9024
  }
8473
9025
  upb_UnknownFields* fields = upb_UnknownFields_DoBuild(ctx, &builder);
@@ -8535,16 +9087,30 @@ static upb_UnknownCompareResult upb_UnknownField_Compare(
8535
9087
  if (UPB_SETJMP(ctx->err) == 0) {
8536
9088
  ret = upb_UnknownField_DoCompare(ctx, msg1, msg2);
8537
9089
  } else {
9090
+ // If status is still Equal, the jump must have originated from the Encoder
9091
+ // (which only updates ctx->encoder.status). We must map it to a context
9092
+ // error.
9093
+ if (ctx->status == kUpb_UnknownCompareResult_Equal) {
9094
+ if (ctx->encoder.status == kUpb_EncodeStatus_OutOfMemory) {
9095
+ ctx->status = kUpb_UnknownCompareResult_OutOfMemory;
9096
+ } else if (ctx->encoder.status == kUpb_EncodeStatus_MaxDepthExceeded) {
9097
+ ctx->status = kUpb_UnknownCompareResult_MaxDepthExceeded;
9098
+ } else {
9099
+ ctx->status = kUpb_UnknownCompareResult_OutOfMemory;
9100
+ }
9101
+ upb_BackAlloc_Abort(&ctx->encoder.alloc);
9102
+ }
8538
9103
  ret = ctx->status;
8539
9104
  UPB_ASSERT(ret != kUpb_UnknownCompareResult_Equal);
8540
9105
  }
8541
9106
 
9107
+ UPB_PRIVATE(_upb_encstate_destroy)(&ctx->encoder);
8542
9108
  upb_Arena_Free(ctx->arena);
8543
9109
  upb_gfree(ctx->tmp);
8544
9110
  return ret;
8545
9111
  }
8546
9112
 
8547
- upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)(
9113
+ upb_UnknownCompareResult _upb_Message_UnknownFieldsAreEqual(
8548
9114
  const upb_Message* msg1, const upb_Message* msg2, int max_depth) {
8549
9115
  bool msg1_empty = !upb_Message_HasUnknown(msg1);
8550
9116
  bool msg2_empty = !upb_Message_HasUnknown(msg2);
@@ -8560,6 +9126,7 @@ upb_UnknownCompareResult UPB_PRIVATE(_upb_Message_UnknownFieldsAreEqual)(
8560
9126
  };
8561
9127
 
8562
9128
  if (!ctx.arena) return kUpb_UnknownCompareResult_OutOfMemory;
9129
+ UPB_PRIVATE(_upb_encstate_init)(&ctx.encoder, &ctx.err, ctx.arena);
8563
9130
 
8564
9131
  return upb_UnknownField_Compare(&ctx, msg1, msg2);
8565
9132
  }
@@ -8578,10 +9145,11 @@ static upb_StringView upb_Clone_StringView(upb_StringView str,
8578
9145
  return upb_StringView_FromDataAndSize(NULL, 0);
8579
9146
  }
8580
9147
  void* cloned_data = upb_Arena_Malloc(arena, str.size);
8581
- upb_StringView cloned_str =
8582
- upb_StringView_FromDataAndSize(cloned_data, str.size);
9148
+ if (cloned_data == NULL) {
9149
+ return upb_StringView_FromDataAndSize(NULL, 0);
9150
+ }
8583
9151
  memcpy(cloned_data, str.data, str.size);
8584
- return cloned_str;
9152
+ return upb_StringView_FromDataAndSize(cloned_data, str.size);
8585
9153
  }
8586
9154
 
8587
9155
  static bool upb_Clone_MessageValue(void* value, upb_CType value_type,
@@ -8621,30 +9189,81 @@ static bool upb_Clone_MessageValue(void* value, upb_CType value_type,
8621
9189
  UPB_UNREACHABLE();
8622
9190
  }
8623
9191
 
9192
+ static bool upb_Clone_MapValue(upb_value* tabval, size_t map_val_size,
9193
+ upb_CType value_field_type,
9194
+ const upb_MiniTable* value_sub, upb_Arena* arena,
9195
+ upb_value* cloned_tabval) {
9196
+ upb_MessageValue val;
9197
+ _upb_map_fromvalue(*tabval, &val, map_val_size);
9198
+ if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) {
9199
+ return false;
9200
+ }
9201
+ *cloned_tabval = (upb_value){0}; // Initialize
9202
+ if (!_upb_map_tovalue(&val, map_val_size, cloned_tabval, arena)) {
9203
+ return false;
9204
+ }
9205
+ return true;
9206
+ }
9207
+
8624
9208
  upb_Map* upb_Map_DeepClone(const upb_Map* map, upb_CType key_type,
8625
9209
  upb_CType value_type,
8626
9210
  const upb_MiniTable* map_entry_table,
8627
9211
  upb_Arena* arena) {
8628
- upb_Map* cloned_map = _upb_Map_New(arena, map->key_size, map->val_size);
9212
+ upb_Map* cloned_map = upb_Arena_Malloc(arena, sizeof(upb_Map));
8629
9213
  if (cloned_map == NULL) {
8630
9214
  return NULL;
8631
9215
  }
8632
- upb_MessageValue key, val;
8633
- size_t iter = kUpb_Map_Begin;
8634
- while (upb_Map_Next(map, &key, &val, &iter)) {
8635
- const upb_MiniTableField* value_field =
8636
- upb_MiniTable_MapValue(map_entry_table);
8637
- const upb_MiniTable* value_sub =
8638
- upb_MiniTableField_CType(value_field) == kUpb_CType_Message
8639
- ? upb_MiniTable_GetSubMessageTable(value_field)
8640
- : NULL;
8641
- upb_CType value_field_type = upb_MiniTableField_CType(value_field);
8642
- if (!upb_Clone_MessageValue(&val, value_field_type, value_sub, arena)) {
9216
+ cloned_map->key_size = map->key_size;
9217
+ cloned_map->val_size = map->val_size;
9218
+ cloned_map->UPB_PRIVATE(is_frozen) = false;
9219
+ cloned_map->UPB_PRIVATE(is_strtable) = map->UPB_PRIVATE(is_strtable);
9220
+
9221
+ const upb_MiniTableField* value_field =
9222
+ upb_MiniTable_MapValue(map_entry_table);
9223
+ const upb_MiniTable* value_sub = upb_MiniTable_SubMessage(value_field);
9224
+ upb_CType value_field_type = upb_MiniTableField_CType(value_field);
9225
+
9226
+ bool is_primitive = value_field_type != kUpb_CType_Message &&
9227
+ value_field_type != kUpb_CType_String &&
9228
+ value_field_type != kUpb_CType_Bytes;
9229
+
9230
+ if (map->UPB_PRIVATE(is_strtable)) {
9231
+ if (!upb_strtable_copy(&cloned_map->t.strtable, &map->t.strtable, arena)) {
8643
9232
  return NULL;
8644
9233
  }
8645
- if (!upb_Map_Set(cloned_map, key, val, arena)) {
9234
+ if (!is_primitive) {
9235
+ intptr_t iter = UPB_STRTABLE_BEGIN;
9236
+ upb_StringView key;
9237
+ upb_value tabval;
9238
+ while (
9239
+ upb_strtable_next2(&cloned_map->t.strtable, &key, &tabval, &iter)) {
9240
+ upb_value cloned_tabval;
9241
+ if (!upb_Clone_MapValue(&tabval, map->val_size, value_field_type,
9242
+ value_sub, arena, &cloned_tabval)) {
9243
+ return NULL;
9244
+ }
9245
+ upb_strtable_setentryvalue(&cloned_map->t.strtable, iter,
9246
+ cloned_tabval);
9247
+ }
9248
+ }
9249
+ } else {
9250
+ if (!upb_inttable_copy(&cloned_map->t.inttable, &map->t.inttable, arena)) {
8646
9251
  return NULL;
8647
9252
  }
9253
+ if (!is_primitive) {
9254
+ intptr_t iter = UPB_INTTABLE_BEGIN;
9255
+ uintptr_t key;
9256
+ upb_value tabval;
9257
+ while (upb_inttable_next(&cloned_map->t.inttable, &key, &tabval, &iter)) {
9258
+ upb_value cloned_tabval;
9259
+ if (!upb_Clone_MapValue(&tabval, map->val_size, value_field_type,
9260
+ value_sub, arena, &cloned_tabval)) {
9261
+ return NULL;
9262
+ }
9263
+ upb_inttable_setentryvalue(&cloned_map->t.inttable, iter,
9264
+ cloned_tabval);
9265
+ }
9266
+ }
8648
9267
  }
8649
9268
  return cloned_map;
8650
9269
  }
@@ -8705,19 +9324,23 @@ static bool upb_Message_Array_DeepClone(const upb_Array* array,
8705
9324
  ? upb_MiniTable_GetSubMessageTable(field)
8706
9325
  : NULL,
8707
9326
  arena);
9327
+ if (!cloned_array) return false;
8708
9328
 
8709
9329
  // Clear out upb_Array* due to parent memcpy.
8710
9330
  upb_Message_SetBaseField(clone, field, &cloned_array);
8711
9331
  return true;
8712
9332
  }
8713
9333
 
8714
- static bool upb_Clone_ExtensionValue(
8715
- const upb_MiniTableExtension* mini_table_ext, const upb_Extension* source,
8716
- upb_Extension* dest, upb_Arena* arena) {
8717
- dest->data = source->data;
8718
- return upb_Clone_MessageValue(
8719
- &dest->data, upb_MiniTableExtension_CType(mini_table_ext),
8720
- upb_MiniTableExtension_GetSubMessage(mini_table_ext), arena);
9334
+ static bool upb_Clone_ExtensionValue(const upb_MiniTableField* field,
9335
+ const upb_Extension* source,
9336
+ upb_Extension* dest, upb_Arena* arena) {
9337
+ upb_MessageValue val = upb_Extension_GetValue(source);
9338
+ if (!upb_Clone_MessageValue(&val, upb_MiniTableField_CType(field),
9339
+ upb_MiniTable_SubMessage(field), arena)) {
9340
+ return false;
9341
+ }
9342
+ upb_Extension_SetValue(dest, val);
9343
+ return true;
8721
9344
  }
8722
9345
 
8723
9346
  upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
@@ -8739,9 +9362,8 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
8739
9362
  upb_MiniTable_GetSubMessageTable(field);
8740
9363
  upb_Message* dst_sub_message =
8741
9364
  upb_Message_DeepClone(sub_message, sub_message_table, arena);
8742
- if (dst_sub_message == NULL) {
8743
- return NULL;
8744
- }
9365
+ if (dst_sub_message == NULL) goto err;
9366
+
8745
9367
  upb_Message_SetBaseFieldMessage(dst, field, dst_sub_message);
8746
9368
  }
8747
9369
  } break;
@@ -8749,10 +9371,10 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
8749
9371
  case kUpb_CType_Bytes: {
8750
9372
  upb_StringView str = upb_Message_GetString(src, field, empty_string);
8751
9373
  if (str.size != 0) {
8752
- if (!upb_Message_SetString(
8753
- dst, field, upb_Clone_StringView(str, arena), arena)) {
8754
- return NULL;
8755
- }
9374
+ upb_StringView cloned_str = upb_Clone_StringView(str, arena);
9375
+ if (cloned_str.data == NULL) goto err;
9376
+
9377
+ if (!upb_Message_SetString(dst, field, cloned_str, arena)) goto err;
8756
9378
  }
8757
9379
  } break;
8758
9380
  default:
@@ -8764,7 +9386,7 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
8764
9386
  const upb_Map* map = upb_Message_GetMap(src, field);
8765
9387
  if (map != NULL) {
8766
9388
  if (!upb_Message_Map_DeepClone(map, mini_table, field, dst, arena)) {
8767
- return NULL;
9389
+ goto err;
8768
9390
  }
8769
9391
  }
8770
9392
  } else {
@@ -8772,7 +9394,7 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
8772
9394
  if (array != NULL) {
8773
9395
  if (!upb_Message_Array_DeepClone(array, mini_table, field, dst,
8774
9396
  arena)) {
8775
- return NULL;
9397
+ goto err;
8776
9398
  }
8777
9399
  }
8778
9400
  }
@@ -8784,41 +9406,45 @@ upb_Message* _upb_Message_Copy(upb_Message* dst, const upb_Message* src,
8784
9406
 
8785
9407
  for (size_t i = 0; i < in->size; i++) {
8786
9408
  upb_TaggedAuxPtr tagged_ptr = in->aux_data[i];
8787
- if (upb_TaggedAuxPtr_IsCanonicalExtension(tagged_ptr)) {
8788
- // Clone extension
8789
- const upb_Extension* msg_ext =
8790
- upb_TaggedAuxPtr_CanonicalExtension(tagged_ptr);
8791
- const upb_MiniTableField* field = &msg_ext->ext->UPB_PRIVATE(field);
8792
- upb_Extension* dst_ext = UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(
8793
- dst, msg_ext->ext, arena);
8794
- if (!dst_ext) return NULL;
9409
+ if (upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
9410
+ // Clone a canonical or non-canonical upb_Extension*.
9411
+ const upb_Extension* msg_ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
9412
+ const upb_MiniTableField* field = upb_Extension_MiniTableField(msg_ext);
9413
+ upb_Extension* dst_ext =
9414
+ UPB_PRIVATE(_upb_Message_GetOrCreateExtensionWithTag)(
9415
+ dst, upb_Extension_MiniTableExtension(msg_ext), arena,
9416
+ upb_TaggedAuxPtr_Type(tagged_ptr));
9417
+ if (!dst_ext) goto err;
9418
+
8795
9419
  if (upb_MiniTableField_IsScalar(field)) {
8796
- if (!upb_Clone_ExtensionValue(msg_ext->ext, msg_ext, dst_ext, arena)) {
8797
- return NULL;
9420
+ if (!upb_Clone_ExtensionValue(field, msg_ext, dst_ext, arena)) {
9421
+ goto err;
8798
9422
  }
8799
9423
  } else {
8800
- upb_Array* msg_array = (upb_Array*)msg_ext->data.array_val;
9424
+ const upb_Array* msg_array = upb_Extension_GetArray(msg_ext);
8801
9425
  UPB_ASSERT(msg_array);
8802
- upb_Array* cloned_array = upb_Array_DeepClone(
8803
- msg_array, upb_MiniTableField_CType(field),
8804
- upb_MiniTableExtension_GetSubMessage(msg_ext->ext), arena);
8805
- if (!cloned_array) {
8806
- return NULL;
8807
- }
8808
- dst_ext->data.array_val = cloned_array;
9426
+ upb_Array* cloned_array =
9427
+ upb_Array_DeepClone(msg_array, upb_MiniTableField_CType(field),
9428
+ upb_MiniTable_SubMessage(field), arena);
9429
+ if (!cloned_array) goto err;
9430
+
9431
+ upb_Extension_SetArray(dst_ext, cloned_array);
8809
9432
  }
8810
9433
  } else if (upb_TaggedAuxPtr_IsUnknownStringView(tagged_ptr)) {
8811
- // Clone unknown
9434
+ // Clone an aliased or non-aliased unknown upb_StringView.
8812
9435
  upb_StringView* unknown = upb_TaggedPtrAux_StringViewRepr(tagged_ptr);
8813
9436
  // Make a copy into destination arena.
8814
9437
  if (!UPB_PRIVATE(_upb_Message_AddUnknown)(
8815
9438
  dst, unknown->data, unknown->size, arena, kUpb_AddUnknown_Copy)) {
8816
- return NULL;
9439
+ goto err;
8817
9440
  }
8818
9441
  }
8819
9442
  }
8820
-
8821
9443
  return dst;
9444
+
9445
+ err:
9446
+ upb_Message_Clear(dst, mini_table);
9447
+ return NULL;
8822
9448
  }
8823
9449
 
8824
9450
  bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src,
@@ -8834,6 +9460,7 @@ bool upb_Message_DeepCopy(upb_Message* dst, const upb_Message* src,
8834
9460
  upb_Message* upb_Message_DeepClone(const upb_Message* msg,
8835
9461
  const upb_MiniTable* m, upb_Arena* arena) {
8836
9462
  upb_Message* clone = upb_Message_New(m, arena);
9463
+ if (!clone) return NULL;
8837
9464
  return _upb_Message_Copy(clone, msg, m, arena);
8838
9465
  }
8839
9466
 
@@ -8843,50 +9470,7 @@ bool upb_Message_ShallowCopy(upb_Message* dst, const upb_Message* src,
8843
9470
  UPB_ASSERT(!upb_Message_IsFrozen(dst));
8844
9471
  memcpy(dst, src, m->UPB_PRIVATE(size));
8845
9472
 
8846
- const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(src);
8847
- if (!in) return true;
8848
-
8849
- size_t size = UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, in->size);
8850
- upb_Message_Internal* dst_in = upb_Arena_Malloc(arena, size);
8851
- if (!dst_in) return false;
8852
-
8853
- dst_in->size = in->size;
8854
- dst_in->capacity = in->size;
8855
-
8856
- for (size_t i = 0; i < in->size; i++) {
8857
- upb_TaggedAux aux;
8858
- switch (upb_TaggedAux_Get(in->aux_data[i], &aux)) {
8859
- case kUpb_TaggedAuxType_CanonicalExtension: {
8860
- const upb_Extension* msg_ext = aux.extension;
8861
- upb_Extension* dst_ext = upb_Arena_Malloc(arena, sizeof(upb_Extension));
8862
- if (!dst_ext) return false;
8863
- *dst_ext = *msg_ext;
8864
- dst_in->aux_data[i] = upb_TaggedAuxPtr_MakeCanonicalExtension(dst_ext);
8865
- break;
8866
- }
8867
- case kUpb_TaggedAuxType_Unknown:
8868
- case kUpb_TaggedAuxType_AliasedUnknown: {
8869
- upb_StringView* dst_sv =
8870
- upb_Arena_Malloc(arena, sizeof(upb_StringView));
8871
- if (!dst_sv) return false;
8872
- *dst_sv = *aux.unknown_data;
8873
- dst_in->aux_data[i] = upb_TaggedAuxPtr_MakeUnknownDataAliased(dst_sv);
8874
- break;
8875
- }
8876
- case kUpb_TaggedAuxType_NonCanonicalExtension: {
8877
- const upb_Extension* msg_ext = aux.extension;
8878
- upb_Extension* dst_ext = upb_Arena_Malloc(arena, sizeof(upb_Extension));
8879
- if (!dst_ext) return false;
8880
- *dst_ext = *msg_ext;
8881
- dst_in->aux_data[i] =
8882
- upb_TaggedAuxPtr_MakeNonCanonicalExtension(dst_ext);
8883
- break;
8884
- }
8885
- }
8886
- }
8887
-
8888
- UPB_PRIVATE(_upb_Message_SetInternal)(dst, dst_in);
8889
- return true;
9473
+ return UPB_PRIVATE(_upb_Message_CopyInternal)(dst, src, arena);
8890
9474
  }
8891
9475
 
8892
9476
  // Performs a shallow clone.
@@ -8915,6 +9499,7 @@ bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src,
8915
9499
  // so we don't want to unnecessarily have the bad API or bloat the passed-in
8916
9500
  // arena with this very-short-term allocation.
8917
9501
  upb_Arena* encode_arena = upb_Arena_New();
9502
+ if (!encode_arena) return false;
8918
9503
  upb_EncodeStatus e_status = upb_Encode(src, mt, 0, encode_arena, &buf, &size);
8919
9504
  if (e_status != kUpb_EncodeStatus_Ok) {
8920
9505
  upb_Arena_Free(encode_arena);
@@ -8931,7 +9516,6 @@ bool upb_Message_MergeFrom(upb_Message* dst, const upb_Message* src,
8931
9516
 
8932
9517
 
8933
9518
  #include <stdint.h>
8934
- #include <string.h>
8935
9519
 
8936
9520
 
8937
9521
  // Must be last.
@@ -8946,7 +9530,7 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)(
8946
9530
  if (upb_TaggedAuxPtr_IsCanonicalExtension(tagged_ptr)) {
8947
9531
  const upb_Extension* ext =
8948
9532
  upb_TaggedAuxPtr_CanonicalExtension(tagged_ptr);
8949
- if (ext->ext == e) {
9533
+ if (upb_Extension_MiniTableExtension(ext) == e) {
8950
9534
  return ext;
8951
9535
  }
8952
9536
  }
@@ -8955,35 +9539,40 @@ const upb_Extension* UPB_PRIVATE(_upb_Message_Getext)(
8955
9539
  return NULL;
8956
9540
  }
8957
9541
 
8958
- UPB_INLINE upb_Extension* _upb_Message_GetOrCreateExtensionInternal(
9542
+ upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtensionWithTag)(
8959
9543
  struct upb_Message* msg, const upb_MiniTableExtension* e, upb_Arena* a,
8960
- bool canonical) {
9544
+ upb_TaggedAuxType tag) {
8961
9545
  UPB_ASSERT(!upb_Message_IsFrozen(msg));
8962
- upb_Extension* ext = (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e);
8963
- if (ext) return ext;
8964
-
9546
+ // For Canonical Extensions, we check whether the extension has already been
9547
+ // set. If we find an extension with the same pointer and tag, we reuse it to
9548
+ // prevent duplicate entries for the same extension.
9549
+ //
9550
+ // For Non-Canonical Extensions, we do NOT reuse them, matching the behavior
9551
+ // of adding a unknown StringView (through `_upb_Message_AddUnknown`) which
9552
+ // accumulates.
9553
+ if (tag == kUpb_TaggedAuxType_CanonicalExtension) {
9554
+ upb_Extension* ext =
9555
+ (upb_Extension*)UPB_PRIVATE(_upb_Message_Getext)(msg, e);
9556
+ if (ext) return ext;
9557
+ }
8965
9558
  if (!UPB_PRIVATE(_upb_Message_ReserveSlot)(msg, a)) return NULL;
8966
9559
  upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
8967
- ext = upb_Arena_Malloc(a, sizeof(upb_Extension));
9560
+ upb_Extension* ext = UPB_PRIVATE(_upb_Extension_New)(e, a);
8968
9561
  if (!ext) return NULL;
8969
- memset(ext, 0, sizeof(upb_Extension));
8970
- ext->ext = e;
8971
- in->aux_data[in->size++] =
8972
- canonical ? upb_TaggedAuxPtr_MakeCanonicalExtension(ext)
8973
- : upb_TaggedAuxPtr_MakeNonCanonicalExtension(ext);
9562
+ in->aux_data[in->size++] = upb_TaggedAuxPtr_MakeExtension(ext, tag);
8974
9563
  return ext;
8975
9564
  }
8976
9565
 
8977
9566
  upb_Extension* UPB_PRIVATE(_upb_Message_GetOrCreateExtension)(
8978
9567
  struct upb_Message* msg, const upb_MiniTableExtension* e, upb_Arena* a) {
8979
- return _upb_Message_GetOrCreateExtensionInternal(msg, e, a,
8980
- /*canonical=*/true);
9568
+ return UPB_PRIVATE(_upb_Message_GetOrCreateExtensionWithTag)(
9569
+ msg, e, a, kUpb_TaggedAuxType_CanonicalExtension);
8981
9570
  }
8982
9571
 
8983
9572
  upb_Extension* UPB_PRIVATE(_upb_Message_CreateNonCanonicalExtension)(
8984
9573
  struct upb_Message* msg, const upb_MiniTableExtension* e, upb_Arena* a) {
8985
- return _upb_Message_GetOrCreateExtensionInternal(msg, e, a,
8986
- /*canonical=*/false);
9574
+ return UPB_PRIVATE(_upb_Message_GetOrCreateExtensionWithTag)(
9575
+ msg, e, a, kUpb_TaggedAuxType_NonCanonicalExtension);
8987
9576
  }
8988
9577
 
8989
9578
 
@@ -9025,8 +9614,19 @@ const float kUpb_FltInfinity = UPB_INFINITY;
9025
9614
  const double kUpb_Infinity = UPB_INFINITY;
9026
9615
  const double kUpb_NaN = UPB_NAN;
9027
9616
 
9028
- static size_t _upb_Message_SizeOfInternal(uint32_t count) {
9029
- return UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, count);
9617
+ UPB_INLINE size_t _upb_Message_InternalBlockSize(uint32_t count) {
9618
+ size_t bytes = UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, count);
9619
+ return upb_RoundUpToPowerOfTwo(
9620
+ UPB_MAX(bytes, UPB_PRIVATE(kUpb_Arena_MinPoolBlockSize)));
9621
+ }
9622
+
9623
+ UPB_INLINE uint32_t _upb_Message_InternalCapacity(size_t block_bytes) {
9624
+ size_t capacity =
9625
+ UPB_FLEX_CAPACITY(upb_Message_Internal, aux_data, block_bytes);
9626
+ if (capacity > UINT32_MAX) {
9627
+ return UINT32_MAX;
9628
+ }
9629
+ return (uint32_t)capacity;
9030
9630
  }
9031
9631
 
9032
9632
  bool UPB_PRIVATE(_upb_Message_ReserveSlot)(struct upb_Message* msg,
@@ -9035,32 +9635,88 @@ bool UPB_PRIVATE(_upb_Message_ReserveSlot)(struct upb_Message* msg,
9035
9635
  upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
9036
9636
  if (!in) {
9037
9637
  // No internal data, allocate from scratch.
9038
- uint32_t capacity = 4;
9039
- in = upb_Arena_Malloc(a, _upb_Message_SizeOfInternal(capacity));
9638
+ size_t block_bytes = _upb_Message_InternalBlockSize(1);
9639
+ in = (upb_Message_Internal*)upb_Arena_AllocPool(a, block_bytes);
9040
9640
  if (!in) return false;
9041
9641
  in->size = 0;
9042
- in->capacity = capacity;
9642
+ in->capacity = _upb_Message_InternalCapacity(block_bytes);
9043
9643
  UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
9044
9644
  } else if (in->capacity == in->size) {
9045
9645
  if (in->size == UINT32_MAX) return false;
9046
9646
  // Internal data is too small, reallocate.
9047
- size_t needed_pow2 = upb_RoundUpToPowerOfTwo(in->size + 1);
9048
- if (needed_pow2 > UINT32_MAX) return false;
9049
- uint32_t new_capacity = needed_pow2;
9050
9647
  if (UPB_SIZEOF_FLEX_WOULD_OVERFLOW(upb_Message_Internal, aux_data,
9051
- new_capacity)) {
9648
+ in->size + 1)) {
9052
9649
  return false;
9053
9650
  }
9054
- in = upb_Arena_Realloc(a, in, _upb_Message_SizeOfInternal(in->capacity),
9055
- _upb_Message_SizeOfInternal(new_capacity));
9056
- if (!in) return false;
9057
- in->capacity = new_capacity;
9058
- UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
9651
+ size_t old_bytes =
9652
+ UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, in->capacity);
9653
+ size_t new_bytes = _upb_Message_InternalBlockSize(in->size + 1);
9654
+ if (new_bytes == SIZE_MAX ||
9655
+ _upb_Message_InternalCapacity(new_bytes) > UINT32_MAX) {
9656
+ return false;
9657
+ }
9658
+ if (upb_Arena_TryExtend(a, in, old_bytes, new_bytes)) {
9659
+ in->capacity = _upb_Message_InternalCapacity(new_bytes);
9660
+ } else {
9661
+ upb_Message_Internal* new_in =
9662
+ (upb_Message_Internal*)upb_Arena_AllocPool(a, new_bytes);
9663
+ if (!new_in) return false;
9664
+ memcpy(new_in, in,
9665
+ UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, in->size));
9666
+ new_in->capacity = _upb_Message_InternalCapacity(new_bytes);
9667
+ UPB_PRIVATE(_upb_Arena_Harvest)(a, in, old_bytes);
9668
+ in = new_in;
9669
+ UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
9670
+ }
9059
9671
  }
9060
9672
  UPB_ASSERT(in->capacity - in->size >= 1);
9061
9673
  return true;
9062
9674
  }
9063
9675
 
9676
+ bool UPB_PRIVATE(_upb_Message_CopyInternal)(struct upb_Message* dst,
9677
+ const struct upb_Message* src,
9678
+ upb_Arena* arena) {
9679
+ const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(src);
9680
+ if (!in) return true;
9681
+
9682
+ size_t needed_bytes =
9683
+ UPB_SIZEOF_FLEX(upb_Message_Internal, aux_data, in->size);
9684
+ size_t block_bytes = _upb_Message_InternalBlockSize(in->size);
9685
+ upb_Message_Internal* dst_in = NULL;
9686
+ if (block_bytes != SIZE_MAX) {
9687
+ dst_in = (upb_Message_Internal*)upb_Arena_TryAllocPool(arena, block_bytes);
9688
+ }
9689
+ if (!dst_in) {
9690
+ block_bytes = needed_bytes;
9691
+ dst_in = upb_Arena_Malloc(arena, block_bytes);
9692
+ if (!dst_in) return false;
9693
+ }
9694
+
9695
+ dst_in->size = 0;
9696
+ dst_in->capacity = _upb_Message_InternalCapacity(block_bytes);
9697
+
9698
+ for (size_t i = 0; i < in->size; i++) {
9699
+ upb_TaggedAuxPtr tagged_ptr = in->aux_data[i];
9700
+ if (upb_TaggedAuxPtr_IsExtension(tagged_ptr)) {
9701
+ const upb_Extension* msg_ext = upb_TaggedAuxPtr_Extension(tagged_ptr);
9702
+ upb_Extension* dst_ext =
9703
+ UPB_PRIVATE(_upb_Extension_Clone)(msg_ext, arena);
9704
+ if (!dst_ext) return false;
9705
+ dst_in->aux_data[dst_in->size++] = upb_TaggedAuxPtr_MakeExtension(
9706
+ dst_ext, upb_TaggedAuxPtr_Type(tagged_ptr));
9707
+ } else if (upb_TaggedAuxPtr_IsUnknownStringView(tagged_ptr)) {
9708
+ upb_StringView* dst_sv = upb_Arena_Malloc(arena, sizeof(upb_StringView));
9709
+ if (!dst_sv) return false;
9710
+ *dst_sv = *upb_TaggedPtrAux_StringViewRepr(tagged_ptr);
9711
+ dst_in->aux_data[dst_in->size++] =
9712
+ upb_TaggedAuxPtr_MakeUnknownDataAliased(dst_sv);
9713
+ }
9714
+ }
9715
+
9716
+ UPB_PRIVATE(_upb_Message_SetInternal)(dst, dst_in);
9717
+ return true;
9718
+ }
9719
+
9064
9720
  #ifdef UPB_TRACING_ENABLED
9065
9721
  static void (*_message_trace_handler)(const upb_MiniTable*, const upb_Arena*);
9066
9722
 
@@ -9678,7 +10334,9 @@ static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d,
9678
10334
  size_t u32_ofs = ofs / kUpb_SubmsgOffsetBytes;
9679
10335
  UPB_ASSERT((ofs % 4) == 0);
9680
10336
  UPB_ASSERT((i * sizeof(upb_MiniTableField) + ofs) % ptr_size == 0);
9681
- if (u32_ofs > UINT16_MAX) {
10337
+ // u32_ofs must be strictly less than UINT16_MAX: UINT16_MAX is reserved as
10338
+ // kUpb_NoSub, the sentinel meaning "this field has no submessage".
10339
+ if (u32_ofs >= UINT16_MAX) {
9682
10340
  upb_MdDecoder_ErrorJmp(&d->base, "Submessage offset overflow");
9683
10341
  }
9684
10342
  f->UPB_PRIVATE(submsg_ofs) = u32_ofs;
@@ -9743,6 +10401,9 @@ static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr,
9743
10401
  if (skip == 0) {
9744
10402
  upb_MdDecoder_ErrorJmp(&d->base, "Invalid skip value: 0");
9745
10403
  }
10404
+ if (skip > UINT32_MAX - last_field_number) {
10405
+ upb_MdDecoder_ErrorJmp(&d->base, "Field number overflow");
10406
+ }
9746
10407
  last_field_number += skip;
9747
10408
  last_field_number--; // Next field seen will increment.
9748
10409
  } else {
@@ -9763,7 +10424,9 @@ static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
9763
10424
  sizeof(upb_MiniTableField) + sizeof(upb_MiniTableSubInternal);
9764
10425
  // Buffer length is an upper bound on the number of fields. We will return
9765
10426
  // what we don't use.
9766
- if ((SIZE_MAX - 4) / bytes_per_field < len) {
10427
+ size_t initial_bytes;
10428
+ if (upb_MulOverflow(bytes_per_field, len, &initial_bytes) ||
10429
+ upb_AddOverflow(initial_bytes, (size_t)4, &initial_bytes)) {
9767
10430
  upb_MdDecoder_ErrorJmp(&d->base, "MiniDescriptor is too large");
9768
10431
  }
9769
10432
  // Max size used per field is a upb_MiniTableField and a
@@ -9774,7 +10437,6 @@ static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
9774
10437
  UPB_ALIGN_OF(upb_MiniTableField) <=
9775
10438
  4,
9776
10439
  "alignment difference is too large");
9777
- const size_t initial_bytes = bytes_per_field * len + 4;
9778
10440
  d->fields = upb_Arena_Malloc(d->arena, initial_bytes);
9779
10441
  upb_MdDecoder_CheckOutOfMemory(&d->base, d->fields);
9780
10442
 
@@ -9866,6 +10528,9 @@ static void upb_MtDecoder_AssignHasbits(upb_MtDecoder* d) {
9866
10528
  upb_MiniTableField* field =
9867
10529
  (upb_MiniTableField*)&d->table.UPB_PRIVATE(fields)[i];
9868
10530
  if (field->UPB_PRIVATE(offset) == kHasbitPresence) {
10531
+ if (last_hasbit >= INT16_MAX) {
10532
+ upb_MdDecoder_ErrorJmp(&d->base, "Too many fields with presence");
10533
+ }
9869
10534
  field->presence = ++last_hasbit;
9870
10535
  }
9871
10536
  }
@@ -9895,6 +10560,12 @@ static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
9895
10560
  for (upb_OneOfLayoutItem* item = d->oneofs.data; item < oneof_end; item++) {
9896
10561
  upb_MiniTableField* f = &d->fields[item->field_index];
9897
10562
  uint16_t case_offset = upb_MtDecoder_Place(d, kUpb_OneOf_CaseFieldRep);
10563
+ // The case offset is stored negated in the int16_t presence field, so it
10564
+ // must fit in the positive int16_t range or it would alias a hasbit index.
10565
+ if (case_offset > INT16_MAX) {
10566
+ upb_MdDecoder_ErrorJmp(&d->base,
10567
+ "Message size exceeded maximum size for oneofs");
10568
+ }
9898
10569
  uint16_t data_offset = upb_MtDecoder_Place(d, item->rep);
9899
10570
  while (true) {
9900
10571
  f->presence = ~case_offset;
@@ -10036,11 +10707,15 @@ done:
10036
10707
 
10037
10708
  #if UPB_FASTTABLE
10038
10709
  upb_DecodeFast_TableEntry fasttable[32];
10039
- int fasttable_size = upb_DecodeFast_BuildTable(&decoder->table, fasttable);
10040
- mt_size += fasttable_size * sizeof(fasttable[0]);
10710
+ int fasttable_size = 0;
10711
+ if (decoder->platform == kUpb_MiniTablePlatform_64Bit) {
10712
+ fasttable_size = upb_DecodeFast_BuildTable(&decoder->table, fasttable);
10713
+ mt_size += fasttable_size * sizeof(fasttable[0]);
10714
+ }
10041
10715
  #endif
10042
10716
 
10043
10717
  upb_MiniTable* ret = upb_Arena_Malloc(decoder->arena, mt_size);
10718
+ upb_MdDecoder_CheckOutOfMemory(&decoder->base, ret);
10044
10719
  memcpy(ret, &decoder->table, sizeof(*ret));
10045
10720
 
10046
10721
  #if UPB_FASTTABLE
@@ -10240,41 +10915,63 @@ bool upb_MiniTable_SetSubMessage(upb_MiniTable* table,
10240
10915
  UPB_ASSERT(sub);
10241
10916
 
10242
10917
  const bool sub_is_map = sub->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry;
10918
+ const bool table_is_map = table->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry;
10243
10919
 
10244
10920
  switch (field->UPB_PRIVATE(descriptortype)) {
10245
10921
  case kUpb_FieldType_Message:
10246
10922
  if (sub_is_map) {
10247
- const bool table_is_map =
10248
- table->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry;
10249
10923
  if (UPB_UNLIKELY(table_is_map)) return false;
10250
10924
 
10925
+ // A map field on the parent table must be repeated, and cannot be in a
10926
+ // oneof or an extension.
10927
+ UPB_ASSERT(!upb_MiniTableField_IsMap(field));
10928
+ if (UPB_UNLIKELY(!upb_MiniTableField_IsArray(field) ||
10929
+ upb_MiniTableField_IsInOneof(field) ||
10930
+ upb_MiniTableField_IsExtension(field))) {
10931
+ return false;
10932
+ }
10933
+
10251
10934
  field->UPB_PRIVATE(mode) =
10252
10935
  (field->UPB_PRIVATE(mode) & ~kUpb_FieldMode_Mask) |
10253
10936
  kUpb_FieldMode_Map;
10254
10937
 
10255
10938
  #if UPB_FASTTABLE
10256
- // The fasttable decoder cannot decode maps. Unfortunately we do not
10257
- // know until this moment that the field is a map, so we have to
10258
- // overwrite the fasttable entry (if any) that we built for this field
10259
- // previously.
10939
+ // Update fasttable entry with specialized map decoder function pointer
10940
+ // and metadata.
10260
10941
  int size = table->UPB_PRIVATE(table_mask) == 0xff
10261
10942
  ? 0
10262
10943
  : ((table->UPB_PRIVATE(table_mask) >> 3) + 1);
10263
10944
  for (int i = 0; i < size; i++) {
10264
10945
  _upb_FastTable_Entry* entry = &table->UPB_PRIVATE(fasttable)[i];
10265
- uint32_t field_number = (((int)entry->field_data >> 3) & 0xf) |
10266
- (((int)entry->field_data >> 4) & 0x7f0);
10946
+ uint32_t field_number =
10947
+ upb_DecodeFastData_GetFieldNumber(entry->field_data);
10267
10948
  if (field_number == upb_MiniTableField_Number(field)) {
10268
- entry->field_parser = &_upb_FastDecoder_DecodeGeneric;
10269
- entry->field_data = 0;
10949
+ uint16_t expected_tag =
10950
+ upb_DecodeFastData_GetExpectedTag(entry->field_data);
10951
+ uint64_t subofs = upb_DecodeFastData_GetSubofs(entry->field_data);
10952
+ upb_DecodeFast_TableEntry fast_entry;
10953
+ if (upb_DecodeFast_TryFillMapEntry(field, sub, expected_tag, subofs,
10954
+ &fast_entry)) {
10955
+ entry->field_parser =
10956
+ upb_DecodeFast_GetFunctionPointer(fast_entry.function_idx);
10957
+ entry->field_data = fast_entry.function_data;
10958
+ } else {
10959
+ entry->field_parser = &_upb_FastDecoder_DecodeGeneric;
10960
+ entry->field_data = 0;
10961
+ }
10270
10962
  }
10271
10963
  }
10272
10964
  #endif
10965
+ } else if (table_is_map) {
10966
+ // If table is a map entry, only field 2 (value) can be a submessage.
10967
+ if (UPB_UNLIKELY(upb_MiniTableField_Number(field) != 2)) {
10968
+ return false;
10969
+ }
10273
10970
  }
10274
10971
  break;
10275
10972
 
10276
10973
  case kUpb_FieldType_Group:
10277
- if (UPB_UNLIKELY(sub_is_map)) return false;
10974
+ if (UPB_UNLIKELY(sub_is_map || table_is_map)) return false;
10278
10975
  break;
10279
10976
 
10280
10977
  default:
@@ -10284,9 +10981,7 @@ bool upb_MiniTable_SetSubMessage(upb_MiniTable* table,
10284
10981
  upb_MiniTableSubInternal* table_sub =
10285
10982
  UPB_PTR_AT(field, field->UPB_PRIVATE(submsg_ofs) * kUpb_SubmsgOffsetBytes,
10286
10983
  upb_MiniTableSubInternal);
10287
- // TODO: Add this assert back once YouTube is updated to not call
10288
- // this function repeatedly.
10289
- // UPB_ASSERT(upb_MiniTable_GetSubMessageTable(table, field) == NULL);
10984
+ UPB_ASSERT(upb_MiniTable_GetSubMessageTable(field) == NULL);
10290
10985
  table_sub->UPB_PRIVATE(submsg) = sub;
10291
10986
  return true;
10292
10987
  }
@@ -10302,20 +10997,25 @@ bool upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
10302
10997
  return false;
10303
10998
  }
10304
10999
 
10305
- if ((table->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry) &&
10306
- !upb_MiniTableEnum_CheckValue(sub, 0)) {
10307
- // An enum used in a map must include 0 as a value. This matches a check
10308
- // performed in protoc ("Enum value in map must define 0 as the first
10309
- // value"). Protoc should ensure that we never get here.
10310
- //
10311
- // This ends up being important if we receive wire messages where a map
10312
- // entry omits the value (and thus defaults to 0).
10313
- return false;
11000
+ if (table->UPB_PRIVATE(ext) & kUpb_ExtMode_IsMapEntry) {
11001
+ if (UPB_UNLIKELY(upb_MiniTableField_Number(field) != 2)) {
11002
+ return false;
11003
+ }
11004
+ if (!upb_MiniTableEnum_CheckValue(sub, 0)) {
11005
+ // An enum used in a map must include 0 as a value. This matches a check
11006
+ // performed in protoc ("Enum value in map must define 0 as the first
11007
+ // value"). Protoc should ensure that we never get here.
11008
+ //
11009
+ // This ends up being important if we receive wire messages where a map
11010
+ // entry omits the value (and thus defaults to 0).
11011
+ return false;
11012
+ }
10314
11013
  }
10315
11014
 
10316
11015
  upb_MiniTableSubInternal* table_sub =
10317
11016
  UPB_PTR_AT(field, field->UPB_PRIVATE(submsg_ofs) * kUpb_SubmsgOffsetBytes,
10318
11017
  upb_MiniTableSubInternal);
11018
+ UPB_ASSERT(upb_MiniTable_GetSubEnumTable(field) == NULL);
10319
11019
  *table_sub = upb_MiniTableSub_FromEnum(sub);
10320
11020
  return true;
10321
11021
  }
@@ -10360,8 +11060,8 @@ bool upb_MiniTable_Link(upb_MiniTable* m, const upb_MiniTable** sub_tables,
10360
11060
  upb_MiniTableField* f =
10361
11061
  (upb_MiniTableField*)upb_MiniTable_GetFieldByIndex(m, i);
10362
11062
  if (upb_MiniTableField_CType(f) == kUpb_CType_Message) {
11063
+ if (msg_count >= sub_table_count) return false;
10363
11064
  const upb_MiniTable* sub = sub_tables[msg_count++];
10364
- if (msg_count > sub_table_count) return false;
10365
11065
  if (sub && !upb_MiniTable_SetSubMessage(m, f, sub)) return false;
10366
11066
  }
10367
11067
  }
@@ -10370,8 +11070,8 @@ bool upb_MiniTable_Link(upb_MiniTable* m, const upb_MiniTable** sub_tables,
10370
11070
  upb_MiniTableField* f =
10371
11071
  (upb_MiniTableField*)upb_MiniTable_GetFieldByIndex(m, i);
10372
11072
  if (upb_MiniTableField_IsClosedEnum(f)) {
11073
+ if (enum_count >= sub_enum_count) return false;
10373
11074
  const upb_MiniTableEnum* sub = sub_enums[enum_count++];
10374
- if (enum_count > sub_enum_count) return false;
10375
11075
  if (sub && !upb_MiniTable_SetSubEnum(m, f, sub)) return false;
10376
11076
  }
10377
11077
  }
@@ -11355,6 +12055,16 @@ const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
11355
12055
  }
11356
12056
 
11357
12057
  static void remove_filedef(upb_DefPool* s, upb_FileDef* file) {
12058
+ intptr_t ext_iter = UPB_INTTABLE_BEGIN;
12059
+ uintptr_t ext_key;
12060
+ upb_value ext_val;
12061
+ while (upb_inttable_next(&s->exts, &ext_key, &ext_val, &ext_iter)) {
12062
+ const upb_FieldDef* ext = upb_value_getconstptr(ext_val);
12063
+ if (upb_FieldDef_File(ext) == file) {
12064
+ upb_inttable_removeiter(&s->exts, &ext_iter);
12065
+ }
12066
+ }
12067
+
11358
12068
  intptr_t iter = UPB_INTTABLE_BEGIN;
11359
12069
  upb_StringView key;
11360
12070
  upb_value val;
@@ -12067,10 +12777,10 @@ static int _upb_EnumValueDef_Compare(const void* p1, const void* p2) {
12067
12777
 
12068
12778
  const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
12069
12779
  size_t n, upb_Arena* a) {
12070
- if (SIZE_MAX / sizeof(void*) < n) return NULL;
12780
+ size_t bytes;
12781
+ if (upb_MulOverflow(n, sizeof(void*), &bytes)) return NULL;
12071
12782
  // TODO: Try to replace this arena alloc with a persistent scratch buffer.
12072
- upb_EnumValueDef** out =
12073
- (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*));
12783
+ upb_EnumValueDef** out = (upb_EnumValueDef**)upb_Arena_Malloc(a, bytes);
12074
12784
  if (!out) return NULL;
12075
12785
 
12076
12786
  for (size_t i = 0; i < n; i++) {
@@ -13265,6 +13975,7 @@ struct upb_FileDef {
13265
13975
  const upb_FileDef** deps;
13266
13976
  const int32_t* public_deps;
13267
13977
  const int32_t* weak_deps;
13978
+ const char** option_deps;
13268
13979
  const upb_MessageDef* top_lvl_msgs;
13269
13980
  const upb_EnumDef* top_lvl_enums;
13270
13981
  const upb_FieldDef* top_lvl_exts;
@@ -13275,6 +13986,7 @@ struct upb_FileDef {
13275
13986
  int dep_count;
13276
13987
  int public_dep_count;
13277
13988
  int weak_dep_count;
13989
+ int option_dep_count;
13278
13990
  int top_lvl_msg_count;
13279
13991
  int top_lvl_enum_count;
13280
13992
  int top_lvl_ext_count;
@@ -13332,6 +14044,15 @@ int upb_FileDef_WeakDependencyCount(const upb_FileDef* f) {
13332
14044
  return f->weak_dep_count;
13333
14045
  }
13334
14046
 
14047
+ const char* upb_FileDef_OptionDependency(const upb_FileDef* f, int i) {
14048
+ UPB_ASSERT(0 <= i && i < f->option_dep_count);
14049
+ return f->option_deps[i];
14050
+ }
14051
+
14052
+ int upb_FileDef_OptionDependencyCount(const upb_FileDef* f) {
14053
+ return f->option_dep_count;
14054
+ }
14055
+
13335
14056
  const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f) {
13336
14057
  return f->public_deps;
13337
14058
  }
@@ -13633,6 +14354,17 @@ void _upb_FileDef_Create(upb_DefBuilder* ctx,
13633
14354
  mutable_weak_deps[i] = weak_deps[i];
13634
14355
  }
13635
14356
 
14357
+ const upb_StringView* option_deps;
14358
+ option_deps = google_protobuf_FileDescriptorProto_option_dependency(file_proto, &n);
14359
+ file->option_dep_count = n;
14360
+ file->option_deps = UPB_DEFBUILDER_ALLOCARRAY(ctx, const char*, n);
14361
+ for (size_t i = 0; i < n; i++) {
14362
+ file->option_deps[i] = _strviewdup(ctx, option_deps[i]);
14363
+ if (strlen(file->option_deps[i]) != option_deps[i].size) {
14364
+ _upb_DefBuilder_Errf(ctx, "option_dependency contained embedded NULL");
14365
+ }
14366
+ }
14367
+
13636
14368
  // Create enums.
13637
14369
  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
13638
14370
  file->top_lvl_enum_count = n;
@@ -13755,9 +14487,9 @@ static void _upb_DefBuilder_CheckIdentNotFull(upb_DefBuilder* ctx,
13755
14487
  const char c = name.data[i];
13756
14488
  const char d = c | 0x20; // force lowercase
13757
14489
  const bool is_alpha = (('a' <= d) & (d <= 'z')) | (c == '_');
13758
- const bool is_numer = ('0' <= c) & (c <= '9') & (i != 0);
14490
+ const bool is_number = ('0' <= c) & (c <= '9');
13759
14491
 
13760
- good &= is_alpha | is_numer;
14492
+ good &= is_alpha | is_number;
13761
14493
  }
13762
14494
 
13763
14495
  if (!good) _upb_DefBuilder_CheckIdentSlow(ctx, name, false);
@@ -13812,7 +14544,12 @@ const void* _upb_DefBuilder_ResolveAny(upb_DefBuilder* ctx,
13812
14544
  } else {
13813
14545
  // Remove components from base until we find an entry or run out.
13814
14546
  size_t baselen = base ? strlen(base) : 0;
13815
- char* tmp = upb_gmalloc(sym.size + baselen + 1);
14547
+ size_t alloc_size;
14548
+ if (upb_AddOverflow(sym.size, baselen + 1, &alloc_size)) {
14549
+ _upb_DefBuilder_OomErr(ctx);
14550
+ }
14551
+ char* tmp = upb_gmalloc(alloc_size);
14552
+ if (!tmp) _upb_DefBuilder_OomErr(ctx);
13816
14553
  while (1) {
13817
14554
  char* p = tmp;
13818
14555
  if (baselen) {
@@ -14004,10 +14741,10 @@ void _upb_DefBuilder_CheckIdentSlow(upb_DefBuilder* ctx, upb_StringView name,
14004
14741
  }
14005
14742
  start = true;
14006
14743
  } else if (start) {
14007
- if (!upb_isletter(c)) {
14744
+ if (!upb_isalphanum(c)) {
14008
14745
  _upb_DefBuilder_Errf(ctx,
14009
14746
  "invalid name: path components must start with a "
14010
- "letter (" UPB_STRINGVIEW_FORMAT ")",
14747
+ "letter or digit (" UPB_STRINGVIEW_FORMAT ")",
14011
14748
  UPB_STRINGVIEW_ARGS(name));
14012
14749
  }
14013
14750
  start = false;
@@ -14108,12 +14845,10 @@ char* upb_strdup2(const char* s, size_t len, upb_Arena* a) {
14108
14845
  size_t n;
14109
14846
  char* p;
14110
14847
 
14111
- // Prevent overflow errors.
14112
- if (len == SIZE_MAX) return NULL;
14848
+ if (upb_AddOverflow(len, (size_t)1, &n)) return NULL;
14113
14849
 
14114
14850
  // Always null-terminate, even if binary data; but don't rely on the input to
14115
14851
  // have a null-terminating byte since it may be a raw binary buffer.
14116
- n = len + 1;
14117
14852
  p = upb_Arena_Malloc(a, n);
14118
14853
  if (p) {
14119
14854
  if (len != 0) memcpy(p, s, len);
@@ -14281,8 +15016,9 @@ bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
14281
15016
  if (upb_TaggedAuxPtr_IsCanonicalExtension(tagged_ptr)) {
14282
15017
  const upb_Extension* ext =
14283
15018
  upb_TaggedAuxPtr_CanonicalExtension(tagged_ptr);
14284
- memcpy(out_val, &ext->data, sizeof(*out_val));
14285
- *out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
15019
+ *out_val = upb_Extension_GetValue(ext);
15020
+ *out_f = upb_DefPool_FindExtensionByMiniTable(
15021
+ ext_pool, upb_Extension_MiniTableExtension(ext));
14286
15022
  *iter = i;
14287
15023
  return true;
14288
15024
  }
@@ -14722,10 +15458,7 @@ void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
14722
15458
  const char* shortname = upb_FieldDef_Name(f);
14723
15459
  const size_t shortnamelen = strlen(shortname);
14724
15460
 
14725
- upb_value v = upb_value_constptr(f);
14726
-
14727
- upb_value existing_v;
14728
- if (upb_strtable_lookup(&m->ntof, shortname, &existing_v)) {
15461
+ if (upb_strtable_lookup(&m->ntof, shortname, NULL)) {
14729
15462
  _upb_DefBuilder_Errf(ctx, "duplicate field name (%s)", shortname);
14730
15463
  }
14731
15464
 
@@ -14740,13 +15473,13 @@ void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
14740
15473
  if (!skip_json_conflicts && strcmp(shortname, json_name) != 0 &&
14741
15474
  google_protobuf_FeatureSet_json_format(m->resolved_features) ==
14742
15475
  google_protobuf_FeatureSet_ALLOW &&
14743
- upb_strtable_lookup(&m->ntof, json_name, &v)) {
15476
+ upb_strtable_lookup(&m->ntof, json_name, NULL)) {
14744
15477
  _upb_DefBuilder_Errf(
14745
15478
  ctx, "duplicate json_name for (%s) with original field name (%s)",
14746
15479
  shortname, json_name);
14747
15480
  }
14748
15481
 
14749
- if (upb_strtable_lookup(&m->jtof, json_name, &v)) {
15482
+ if (upb_strtable_lookup(&m->jtof, json_name, NULL)) {
14750
15483
  if (!skip_json_conflicts) {
14751
15484
  _upb_DefBuilder_Errf(ctx, "duplicate json_name (%s)", json_name);
14752
15485
  }
@@ -14761,7 +15494,8 @@ void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
14761
15494
  _upb_DefBuilder_Errf(ctx, "duplicate field number (%u)", field_number);
14762
15495
  }
14763
15496
 
14764
- ok = upb_inttable_insert(&m->itof, field_number, v, ctx->arena);
15497
+ ok = upb_inttable_insert(&m->itof, field_number, upb_value_constptr(f),
15498
+ ctx->arena);
14765
15499
  if (!ok) _upb_DefBuilder_OomErr(ctx);
14766
15500
  }
14767
15501
 
@@ -15743,10 +16477,16 @@ static upb_StringView default_string(upb_ToProto_Context* ctx,
15743
16477
  return printf_dup(ctx, "%" PRId32, d.int32_val);
15744
16478
  case kUpb_CType_UInt32:
15745
16479
  return printf_dup(ctx, "%" PRIu32, d.uint32_val);
15746
- case kUpb_CType_Float:
15747
- return printf_dup(ctx, "%.9g", d.float_val);
15748
- case kUpb_CType_Double:
15749
- return printf_dup(ctx, "%.17g", d.double_val);
16480
+ case kUpb_CType_Float: {
16481
+ char buf[kUpb_RoundTripBufferSize];
16482
+ _upb_EncodeRoundTripFloat(d.float_val, buf, sizeof(buf));
16483
+ return strviewdup(ctx, buf);
16484
+ }
16485
+ case kUpb_CType_Double: {
16486
+ char buf[kUpb_RoundTripBufferSize];
16487
+ _upb_EncodeRoundTripDouble(d.double_val, buf, sizeof(buf));
16488
+ return strviewdup(ctx, buf);
16489
+ }
15750
16490
  case kUpb_CType_String:
15751
16491
  return strviewdup2(ctx, d.str_val);
15752
16492
  case kUpb_CType_Bytes:
@@ -16155,6 +16895,13 @@ static google_protobuf_FileDescriptorProto* filedef_toproto(upb_ToProto_Context*
16155
16895
  const int32_t* weak_dep_nums = _upb_FileDef_WeakDependencyIndexes(f);
16156
16896
  if (n) memcpy(weak_deps, weak_dep_nums, n * sizeof(int32_t));
16157
16897
 
16898
+ n = upb_FileDef_OptionDependencyCount(f);
16899
+ upb_StringView* option_deps =
16900
+ google_protobuf_FileDescriptorProto_resize_option_dependency(proto, n, ctx->arena);
16901
+ for (size_t i = 0; i < n; i++) {
16902
+ option_deps[i] = strviewdup(ctx, upb_FileDef_OptionDependency(f, i));
16903
+ }
16904
+
16158
16905
  n = upb_FileDef_TopLevelMessageCount(f);
16159
16906
  google_protobuf_DescriptorProto** msgs =
16160
16907
  google_protobuf_FileDescriptorProto_resize_message_type(proto, n, ctx->arena);
@@ -16390,16 +17137,12 @@ static void _upb_Decoder_Munge(const upb_MiniTableField* field, wireval* val) {
16390
17137
  case kUpb_FieldType_Bool:
16391
17138
  val->bool_val = val->uint64_val != 0;
16392
17139
  break;
16393
- case kUpb_FieldType_SInt32: {
16394
- uint32_t n = val->uint64_val;
16395
- val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
17140
+ case kUpb_FieldType_SInt32:
17141
+ val->uint32_val = _upb_Decoder_ZigZagDecode32(val->uint64_val);
16396
17142
  break;
16397
- }
16398
- case kUpb_FieldType_SInt64: {
16399
- uint64_t n = val->uint64_val;
16400
- val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
17143
+ case kUpb_FieldType_SInt64:
17144
+ val->uint64_val = _upb_Decoder_ZigZagDecode64(val->uint64_val);
16401
17145
  break;
16402
- }
16403
17146
  case kUpb_FieldType_Int32:
16404
17147
  case kUpb_FieldType_UInt32:
16405
17148
  _upb_Decoder_MungeInt32(val);
@@ -16576,7 +17319,8 @@ static const char* _upb_Decoder_DecodeEnumPacked(
16576
17319
  field->UPB_PRIVATE(mode) & kUpb_LabelFlags_IsExtension
16577
17320
  ? d->original_msg
16578
17321
  : msg;
16579
- if (!_upb_Encoder_AddEnumValueToUnknown(unknown_msg, field,
17322
+ if (!_upb_Encoder_AddEnumValueToUnknown(unknown_msg,
17323
+ field->UPB_PRIVATE(number),
16580
17324
  elem.uint64_val, &d->arena)) {
16581
17325
  upb_ErrorHandler_ThrowError(d->err, kUpb_DecodeStatus_OutOfMemory);
16582
17326
  }
@@ -16681,8 +17425,7 @@ static const char* _upb_Decoder_DecodeToArray(upb_Decoder* d, const char* ptr,
16681
17425
  }
16682
17426
  }
16683
17427
 
16684
- static upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d,
16685
- const upb_MiniTable* entry) {
17428
+ upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, const upb_MiniTable* entry) {
16686
17429
  // Maps descriptor type -> upb map size
16687
17430
  static const uint8_t kSizeInMap[] = {
16688
17431
  [0] = -1, // invalid descriptor type
@@ -16798,6 +17541,14 @@ static const char* _upb_Decoder_DecodeToSubMessage(
16798
17541
  } else if (upb_MiniTableField_IsInOneof(field)) {
16799
17542
  // Oneof case
16800
17543
  uint32_t* oneof_case = UPB_PRIVATE(_upb_Message_OneofCasePtr)(msg, field);
17544
+ if (op == kUpb_DecodeOp_String || op == kUpb_DecodeOp_Bytes) {
17545
+ // Read the string before setting the oneof case, so that if the read
17546
+ // fails the case still points to the previous member, which is intact.
17547
+ ptr = _upb_Decoder_ReadString2(d, ptr, val->size, mem,
17548
+ op == kUpb_DecodeOp_String);
17549
+ *oneof_case = field->UPB_PRIVATE(number);
17550
+ return ptr;
17551
+ }
16801
17552
  if (op == kUpb_DecodeOp_SubMessage &&
16802
17553
  *oneof_case != field->UPB_PRIVATE(number)) {
16803
17554
  memset(mem, 0, sizeof(void*));
@@ -16855,10 +17606,11 @@ static void upb_Decoder_AddKnownMessageSetItem(
16855
17606
  if (UPB_UNLIKELY(!ext)) {
16856
17607
  upb_ErrorHandler_ThrowError(d->err, kUpb_DecodeStatus_OutOfMemory);
16857
17608
  }
16858
- upb_Message** submsgp = (upb_Message**)&ext->data.msg_val;
16859
- upb_Message* submsg = _upb_Decoder_NewSubMessage2(
16860
- d, ext->ext->UPB_PRIVATE(sub).UPB_PRIVATE(submsg),
16861
- &ext->ext->UPB_PRIVATE(field), submsgp);
17609
+ upb_Message* submsg = upb_Extension_GetMutableMessage(ext);
17610
+ submsg = _upb_Decoder_NewSubMessage2(
17611
+ d, upb_MiniTableExtension_GetSubMessage(item_mt),
17612
+ &item_mt->UPB_PRIVATE(field), &submsg);
17613
+ upb_Extension_SetMessage(ext, submsg);
16862
17614
  // upb_Decode_LimitDepth() takes uint32_t, d->depth - 1 can not be negative.
16863
17615
  if (d->depth <= 1) {
16864
17616
  upb_ErrorHandler_ThrowError(d->err, kUpb_DecodeStatus_MaxDepthExceeded);
@@ -17199,7 +17951,7 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr,
17199
17951
  upb_ErrorHandler_ThrowError(d->err, kUpb_DecodeStatus_OutOfMemory);
17200
17952
  }
17201
17953
  d->original_msg = msg;
17202
- msg = &ext->data.UPB_PRIVATE(ext_msg_val);
17954
+ msg = UPB_PTR_AT(ext, UPB_ONLYBITS(kUpb_Extension_DataOffset), upb_Message);
17203
17955
  }
17204
17956
 
17205
17957
  switch (mode & kUpb_FieldMode_Mask) {
@@ -17683,6 +18435,51 @@ const char* upb_EncodeStatus_String(upb_EncodeStatus status) {
17683
18435
  }
17684
18436
 
17685
18437
 
18438
+ #include <setjmp.h>
18439
+ #include <stddef.h>
18440
+
18441
+
18442
+ // Must be last.
18443
+
18444
+ static upb_EncodeStatus upb_DoEncodeExtension(upb_encstate* encoder, char* ptr,
18445
+ const struct upb_Extension* ext,
18446
+ bool is_message_set,
18447
+ upb_StringView* view,
18448
+ int encode_options) {
18449
+ if (UPB_SETJMP(*encoder->err) == 0) {
18450
+ char* buf = ptr;
18451
+ size_t size = 0;
18452
+ UPB_PRIVATE(_upb_Encode_Extension)(
18453
+ encoder, upb_Extension_MiniTableExtension(ext),
18454
+ upb_Extension_GetValue(ext), is_message_set, &buf, &size,
18455
+ encode_options);
18456
+ view->data = buf;
18457
+ view->size = size;
18458
+ } else {
18459
+ UPB_ASSERT(encoder->status != kUpb_EncodeStatus_Ok);
18460
+ upb_BackAlloc_Abort(&encoder->alloc);
18461
+ view->data = NULL;
18462
+ view->size = 0;
18463
+ }
18464
+ UPB_PRIVATE(_upb_encstate_destroy)(encoder);
18465
+ return encoder->status;
18466
+ }
18467
+
18468
+ upb_EncodeStatus upb_EncodeExtension(const struct upb_Extension* ext,
18469
+ struct upb_Arena* arena,
18470
+ upb_StringView* view, int encode_options) {
18471
+ const upb_MiniTable* extendee =
18472
+ upb_MiniTableExtension_Extendee(upb_Extension_MiniTableExtension(ext));
18473
+ bool is_message_set =
18474
+ extendee != NULL && upb_MiniTable_IsMessageSet(extendee);
18475
+ upb_encstate e;
18476
+ jmp_buf err;
18477
+ char* ptr = UPB_PRIVATE(_upb_encstate_init)(&e, &err, arena);
18478
+ return upb_DoEncodeExtension(&e, ptr, ext, is_message_set, view,
18479
+ encode_options);
18480
+ }
18481
+
18482
+
17686
18483
  #include <stddef.h>
17687
18484
  #include <stdint.h>
17688
18485
  #include <string.h>
@@ -17726,12 +18523,12 @@ static size_t upb_BackAlloc_CalcBlockSize(upb_BackAlloc* a, size_t required,
17726
18523
 
17727
18524
  static char* upb_BackAlloc_Realloc(upb_BackAlloc* a, char* ptr, size_t n) {
17728
18525
  size_t copy = a->limit - ptr;
17729
- if (SIZE_MAX - copy < n) {
18526
+ size_t required_block_size;
18527
+ if (upb_AddOverflow(copy, n, &required_block_size)) {
17730
18528
  return NULL;
17731
18529
  }
17732
18530
 
17733
18531
  bool one_off = false;
17734
- size_t required_block_size = copy + n;
17735
18532
  size_t size = upb_BackAlloc_CalcBlockSize(a, required_block_size, &one_off);
17736
18533
 
17737
18534
  char* block = UPB_PRIVATE(_upb_Arena_AllocBlock)(a->arena, &size);
@@ -17765,6 +18562,9 @@ static char* upb_BackAlloc_Realloc(upb_BackAlloc* a, char* ptr, size_t n) {
17765
18562
  }
17766
18563
 
17767
18564
  char* upb_BackAlloc_Grow(upb_BackAlloc* a, char* ptr, size_t n) {
18565
+ if (!upb_AllocationCount_IncrementAndCheck()) {
18566
+ return NULL;
18567
+ }
17768
18568
  if (a->limit == a->buf) {
17769
18569
  // First allocation: try to steal a block.
17770
18570
  size_t size = n;
@@ -18341,21 +19141,23 @@ static char* encode_array(char* ptr, upb_encstate* e, const upb_Message* msg,
18341
19141
  return ptr;
18342
19142
  }
18343
19143
 
18344
- static char* encode_mapentry(char* ptr, upb_encstate* e, uint32_t number,
18345
- const upb_MiniTable* layout,
18346
- const upb_MapEntry* ent) {
18347
- const upb_MiniTableField* key_field = upb_MiniTable_MapKey(layout);
18348
- const upb_MiniTableField* val_field = upb_MiniTable_MapValue(layout);
19144
+ UPB_FORCEINLINE
19145
+ char* encode_mapentry(char* ptr, upb_encstate* e, uint32_t number,
19146
+ const upb_MiniTableField* key_field,
19147
+ const upb_MiniTableField* val_field,
19148
+ const upb_MapEntry* ent) {
18349
19149
  size_t pre_len = upb_BackAlloc_Size(&e->alloc, ptr);
18350
- size_t size;
19150
+ UPB_ASSUME(upb_MiniTableField_Number(val_field) == 2);
18351
19151
  ptr = encode_scalar(ptr, e, &ent->v, val_field);
19152
+ UPB_ASSUME(upb_MiniTableField_Number(key_field) == 1);
18352
19153
  ptr = encode_scalar(ptr, e, &ent->k, key_field);
18353
- size = upb_BackAlloc_Size(&e->alloc, ptr) - pre_len;
19154
+ size_t size = upb_BackAlloc_Size(&e->alloc, ptr) - pre_len;
18354
19155
  ptr = encode_length(ptr, e, size);
18355
19156
  ptr = encode_tag(ptr, e, number, kUpb_WireType_Delimited);
18356
19157
  return ptr;
18357
19158
  }
18358
19159
 
19160
+ UPB_NOINLINE
18359
19161
  static char* encode_map(char* ptr, upb_encstate* e, const upb_Message* msg,
18360
19162
  const upb_MiniTableField* f) {
18361
19163
  const upb_Map* map = *UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), const upb_Map*);
@@ -18364,14 +19166,20 @@ static char* encode_map(char* ptr, upb_encstate* e, const upb_Message* msg,
18364
19166
 
18365
19167
  if (!map || !upb_Map_Size(map)) return ptr;
18366
19168
 
19169
+ uint32_t number = upb_MiniTableField_Number(f);
19170
+ uint32_t key_size = map->key_size;
19171
+ uint32_t val_size = map->val_size;
19172
+ const upb_MiniTableField* key_field = upb_MiniTable_MapKey(layout);
19173
+ const upb_MiniTableField* val_field = upb_MiniTable_MapValue(layout);
18367
19174
  if (e->options & kUpb_EncodeOption_Deterministic) {
18368
19175
  _upb_sortedmap sorted;
18369
- _upb_mapsorter_pushmap(
18370
- &e->sorter, layout->UPB_PRIVATE(fields)[0].UPB_PRIVATE(descriptortype),
18371
- map, &sorted);
19176
+ if (!_upb_mapsorter_pushmap(
19177
+ &e->sorter, key_field->UPB_PRIVATE(descriptortype), map, &sorted)) {
19178
+ encode_err(e, kUpb_EncodeStatus_OutOfMemory);
19179
+ }
18372
19180
  upb_MapEntry ent;
18373
19181
  while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
18374
- ptr = encode_mapentry(ptr, e, upb_MiniTableField_Number(f), layout, &ent);
19182
+ ptr = encode_mapentry(ptr, e, number, key_field, val_field, &ent);
18375
19183
  }
18376
19184
  _upb_mapsorter_popmap(&e->sorter, &sorted);
18377
19185
  } else {
@@ -18381,20 +19189,19 @@ static char* encode_map(char* ptr, upb_encstate* e, const upb_Message* msg,
18381
19189
  upb_StringView strkey;
18382
19190
  while (upb_strtable_next2(&map->t.strtable, &strkey, &val, &iter)) {
18383
19191
  upb_MapEntry ent;
18384
- _upb_map_fromkey(strkey, &ent.k, map->key_size);
18385
- _upb_map_fromvalue(val, &ent.v, map->val_size);
18386
- ptr =
18387
- encode_mapentry(ptr, e, upb_MiniTableField_Number(f), layout, &ent);
19192
+ _upb_map_fromkey(strkey, &ent.k, key_size);
19193
+ _upb_map_fromvalue(val, &ent.v, val_size);
19194
+ ptr = encode_mapentry(ptr, e, number, key_field, val_field, &ent);
18388
19195
  }
18389
19196
  } else {
18390
19197
  intptr_t iter = UPB_INTTABLE_BEGIN;
18391
19198
  uintptr_t intkey = 0;
18392
19199
  while (upb_inttable_next(&map->t.inttable, &intkey, &val, &iter)) {
18393
19200
  upb_MapEntry ent;
18394
- memcpy(&ent.k, &intkey, map->key_size);
18395
- _upb_map_fromvalue(val, &ent.v, map->val_size);
18396
- ptr =
18397
- encode_mapentry(ptr, e, upb_MiniTableField_Number(f), layout, &ent);
19201
+ UPB_ASSUME(key_size != UPB_MAPTYPE_STRING);
19202
+ memcpy(&ent.k, &intkey, key_size);
19203
+ _upb_map_fromvalue(val, &ent.v, val_size);
19204
+ ptr = encode_mapentry(ptr, e, number, key_field, val_field, &ent);
18398
19205
  }
18399
19206
  }
18400
19207
  }
@@ -18403,52 +19210,19 @@ static char* encode_map(char* ptr, upb_encstate* e, const upb_Message* msg,
18403
19210
 
18404
19211
  static bool encode_shouldencode(const upb_Message* msg,
18405
19212
  const upb_MiniTableField* f) {
18406
- if (f->presence == 0) {
18407
- // Proto3 presence or map/array.
18408
- const void* mem = UPB_PTR_AT(msg, f->UPB_PRIVATE(offset), void);
18409
- switch (UPB_PRIVATE(_upb_MiniTableField_GetRep)(f)) {
18410
- case kUpb_FieldRep_1Byte: {
18411
- char ch;
18412
- memcpy(&ch, mem, 1);
18413
- return ch != 0;
18414
- }
18415
- case kUpb_FieldRep_4Byte: {
18416
- uint32_t u32;
18417
- memcpy(&u32, mem, 4);
18418
- return u32 != 0;
18419
- }
18420
- case kUpb_FieldRep_8Byte: {
18421
- uint64_t u64;
18422
- memcpy(&u64, mem, 8);
18423
- return u64 != 0;
18424
- }
18425
- case kUpb_FieldRep_StringView: {
18426
- const upb_StringView* str = (const upb_StringView*)mem;
18427
- return str->size != 0;
18428
- }
18429
- default:
18430
- UPB_UNREACHABLE();
18431
- }
18432
- } else if (UPB_PRIVATE(_upb_MiniTableField_HasHasbit)(f)) {
18433
- // Proto2 presence: hasbit.
18434
- return UPB_PRIVATE(_upb_Message_GetHasbit)(msg, f);
18435
- } else {
18436
- // Field is in a oneof.
18437
- return UPB_PRIVATE(_upb_Message_GetOneofCase)(msg, f) ==
18438
- upb_MiniTableField_Number(f);
18439
- }
19213
+ return UPB_PRIVATE(_upb_Message_FieldIsSet)(msg, f);
18440
19214
  }
18441
19215
 
18442
19216
  static char* encode_field(char* ptr, upb_encstate* e, const upb_Message* msg,
18443
19217
  const upb_MiniTableField* field) {
18444
19218
  switch (UPB_PRIVATE(_upb_MiniTableField_Mode)(field)) {
19219
+ case kUpb_FieldMode_Scalar:
19220
+ return encode_scalar(
19221
+ ptr, e, UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void), field);
18445
19222
  case kUpb_FieldMode_Array:
18446
19223
  return encode_array(ptr, e, msg, field);
18447
19224
  case kUpb_FieldMode_Map:
18448
19225
  return encode_map(ptr, e, msg, field);
18449
- case kUpb_FieldMode_Scalar:
18450
- return encode_scalar(
18451
- ptr, e, UPB_PTR_AT(msg, field->UPB_PRIVATE(offset), void), field);
18452
19226
  default:
18453
19227
  UPB_UNREACHABLE();
18454
19228
  }
@@ -18489,8 +19263,8 @@ static char* encode_exts(char* ptr, upb_encstate* e, const upb_MiniTable* m,
18489
19263
  upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
18490
19264
  if (!in) return ptr;
18491
19265
 
18492
- /* Encode all extensions together. Unlike C++, we do not attempt to keep
18493
- * these in field number order relative to normal fields or even to each
19266
+ /* Encode all canonical extensions together. Unlike C++, we do not attempt to
19267
+ * keep these in field number order relative to normal fields or even to each
18494
19268
  * other. */
18495
19269
  uintptr_t iter = kUpb_Message_ExtensionBegin;
18496
19270
  const upb_MiniTableExtension* ext;
@@ -18504,11 +19278,12 @@ static char* encode_exts(char* ptr, upb_encstate* e, const upb_MiniTable* m,
18504
19278
  if (e->options & kUpb_EncodeOption_Deterministic) {
18505
19279
  _upb_sortedmap sorted;
18506
19280
  if (!_upb_mapsorter_pushexts(&e->sorter, in, &sorted)) {
18507
- // TODO: b/378744096 - handle alloc failure
19281
+ encode_err(e, kUpb_EncodeStatus_OutOfMemory);
18508
19282
  }
18509
19283
  const upb_Extension* ext;
18510
19284
  while (_upb_sortedmap_nextext(&e->sorter, &sorted, &ext)) {
18511
- ptr = encode_ext(ptr, e, ext->ext, ext->data,
19285
+ ptr = encode_ext(ptr, e, upb_Extension_MiniTableExtension(ext),
19286
+ upb_Extension_GetValue(ext),
18512
19287
  UPB_PRIVATE(_upb_MiniTable_ExtModeBase)(m) ==
18513
19288
  kUpb_ExtMode_IsMessageSet);
18514
19289
  }
@@ -18535,22 +19310,27 @@ char* encode_message(char* ptr, upb_encstate* e, const upb_Message* msg,
18535
19310
  }
18536
19311
  }
18537
19312
 
18538
- if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) {
18539
- size_t unknown_size = 0;
18540
- uintptr_t iter = kUpb_Message_UnknownBegin;
18541
- upb_StringView unknown;
18542
- // Need to write in reverse order, but iteration is in-order; scan to
18543
- // reserve capacity up front, then write in-order
18544
- while (upb_Message_NextUnknown(msg, &unknown, &iter)) {
18545
- unknown_size += unknown.size;
18546
- }
18547
- if (unknown_size != 0) {
18548
- ptr = encode_reserve(ptr, e, unknown_size);
18549
- char* tmp_ptr = ptr;
18550
- iter = kUpb_Message_UnknownBegin;
18551
- while (upb_Message_NextUnknown(msg, &unknown, &iter)) {
18552
- memcpy(tmp_ptr, unknown.data, unknown.size);
18553
- tmp_ptr += unknown.size;
19313
+ bool skip_unknown = (e->options & kUpb_EncodeOption_SkipUnknown) != 0;
19314
+ const upb_Message_Internal* in = UPB_PRIVATE(_upb_Message_GetInternal)(msg);
19315
+ if (!skip_unknown && in) {
19316
+ // Iterate backwards because the encoder builds the buffer in reverse
19317
+ // (from end to start). This ensures that unknown fields and non-canonical
19318
+ // extensions are emitted in their original forward order.
19319
+ size_t i = in->size;
19320
+ while (i > 0) {
19321
+ i--;
19322
+ upb_TaggedAuxPtr tagged_ptr = in->aux_data[i];
19323
+ if (upb_TaggedAuxPtr_IsUnknownStringView(tagged_ptr)) {
19324
+ const upb_StringView* unknown =
19325
+ upb_TaggedPtrAux_StringViewRepr(tagged_ptr);
19326
+ ptr = encode_bytes(ptr, e, unknown->data, unknown->size);
19327
+ } else if (upb_TaggedAuxPtr_IsNonCanonicalExtension(tagged_ptr)) {
19328
+ const upb_Extension* ext =
19329
+ upb_TaggedAuxPtr_NonCanonicalExtension(tagged_ptr);
19330
+ ptr = encode_ext(ptr, e, upb_Extension_MiniTableExtension(ext),
19331
+ upb_Extension_GetValue(ext),
19332
+ UPB_PRIVATE(_upb_MiniTable_ExtModeBase)(m) ==
19333
+ kUpb_ExtMode_IsMessageSet);
18554
19334
  }
18555
19335
  }
18556
19336
  }
@@ -18617,6 +19397,12 @@ upb_EncodeStatus _upb_Encode(const upb_Message* msg, const upb_MiniTable* l,
18617
19397
  return upb_Encoder_Encode(ptr, &e, msg, l, buf, size, prepend_len);
18618
19398
  }
18619
19399
 
19400
+ char* UPB_PRIVATE(_upb_Encode_FieldToBuffer)(char* ptr, upb_encstate* e,
19401
+ const upb_Message* msg,
19402
+ const upb_MiniTableField* field) {
19403
+ return encode_field(ptr, e, msg, field);
19404
+ }
19405
+
18620
19406
  upb_EncodeStatus UPB_PRIVATE(_upb_Encode_Field)(upb_encstate* e,
18621
19407
  const upb_Message* msg,
18622
19408
  const upb_MiniTableField* field,
@@ -18675,7 +19461,8 @@ const char* UPB_PRIVATE(upb_EpsCopyInputStream_IsDoneFallback)(
18675
19461
  e->limit_ptr = e->end + e->limit;
18676
19462
  UPB_ASSERT(ptr < e->limit_ptr);
18677
19463
  e->input_delta = (uintptr_t)old_end - (uintptr_t)new_start;
18678
- UPB_PRIVATE(upb_EpsCopyInputStream_BoundsChecked)(e);
19464
+ UPB_PRIVATE(upb_EpsCopyInputStream_BoundsChecked)(
19465
+ e, kUpb_EpsCopyInputStream_SlopBytes);
18679
19466
  return new_start;
18680
19467
  } else {
18681
19468
  UPB_ASSERT(overrun > e->limit);
@@ -18758,6 +19545,7 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)(
18758
19545
  #undef UPB_SIZE
18759
19546
  #undef UPB_PTR_AT
18760
19547
  #undef UPB_SIZEOF_FLEX
19548
+ #undef UPB_FLEX_CAPACITY
18761
19549
  #undef UPB_SIZEOF_FLEX_WOULD_OVERFLOW
18762
19550
  #undef UPB_MAPTYPE_STRING
18763
19551
  #undef UPB_EXPORT
@@ -18811,6 +19599,8 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)(
18811
19599
  #undef UPB_MALLOC_ALIGN
18812
19600
  #undef UPB_TSAN
18813
19601
  #undef UPB_DEPRECATED
19602
+ #undef UPB_IGNORE_DEPRECATION_START
19603
+ #undef UPB_IGNORE_DEPRECATION_STOP
18814
19604
  #undef UPB_GNUC_MIN
18815
19605
  #undef UPB_CLANG_MIN
18816
19606
  #undef UPB_DESCRIPTOR_UPB_H_FILENAME
@@ -18828,6 +19618,7 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)(
18828
19618
  #undef UPB_HAS_ATTRIBUTE
18829
19619
  #undef UPB_HAS_CPP_ATTRIBUTE
18830
19620
  #undef UPB_HAS_BUILTIN
19621
+ #undef UPB_MEMCPY_INLINE
18831
19622
  #undef UPB_HAS_EXTENSION
18832
19623
  #undef UPB_HAS_FEATURE
18833
19624
  #undef UPB_XSAN_MEMBER
@@ -18842,3 +19633,5 @@ const char* UPB_PRIVATE(_upb_WireReader_SkipGroup)(
18842
19633
  #undef _UPB_STRINGIFY
18843
19634
  #undef _UPB_STRINGIFY2
18844
19635
  #undef UPB_CONSTRUCTOR
19636
+ #undef UPB_RETAIN
19637
+ #undef UPB_HIDDEN