google-protobuf 4.36.1 → 4.37.0.rc.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ae8e2614e9cacf778ac2e1bb24ef2152cb38eb1168677a15d64f092f2b2b299
4
- data.tar.gz: '009b898e9c01aacf8d4480a9fdc8e56d3747d1ec5d8ab3cbb0add814cc3a4a80'
3
+ metadata.gz: ab1ce42c452fd3c8f894377cbb9a0b69b7c93f9a727a34f5c9ab23e02aa83a06
4
+ data.tar.gz: 2c7a155321b661962a27423fd36d90f92b9ab1c6416f92d99359025d36ad91cb
5
5
  SHA512:
6
- metadata.gz: a15e4db4f6f4ca41b8fed8703a2aef797aa9cde23edbd3991afb62d59e08af7a8eafd10e562571293988e7b6c3dade0ec0fa0e5863f954c62a942a3a6cbbe4ca
7
- data.tar.gz: 964387b25c8d068569b5d8028b5fd4069af388ef07561a4a51a3ebe0395900d63dffd944cf5cf5d9b039d6eb1b2eada43eba65aad4db45fe5ef84a64eef238fa
6
+ metadata.gz: a5be52be43d1ef4ef0f17d201bda06c0162238a240a30270011697c1e62343d5c2bf98b0906a5febc68cf7f66b73350421f7d93da51cb195f619be4ced00ece7
7
+ data.tar.gz: 309ebaf8e2a1ed263b39604a8ef0e686a6285c8b1df7f8d24008990c9805bd693528809a29a5039c6f479f286fb67c40809052b1aa2fd1886c5924df732979b5
@@ -24,10 +24,16 @@ static upb_StringView Convert_StringData(VALUE str, upb_Arena* arena) {
24
24
  upb_StringView ret;
25
25
  if (arena) {
26
26
  char* ptr = upb_Arena_Malloc(arena, RSTRING_LEN(str));
27
+ if (!ptr) Arena_raise_oom();
27
28
  memcpy(ptr, RSTRING_PTR(str), RSTRING_LEN(str));
28
29
  ret.data = ptr;
29
30
  } else {
30
- // Data is only needed temporarily (within map lookup).
31
+ // Alias the Ruby String's bytes instead of copying them. Only valid when
32
+ // the result is consumed before anything can allocate: Convert_RubyToUpb
33
+ // may have converted `str` to a temporary that nothing else references, so
34
+ // any GC between here and the read can free or move it. The map lookup
35
+ // paths (Map_index, Map_has_key, Map_delete) satisfy this; insertion paths
36
+ // must pass an arena.
31
37
  ret.data = RSTRING_PTR(str);
32
38
  }
33
39
  ret.size = RSTRING_LEN(str);
@@ -292,6 +298,7 @@ upb_MessageValue Msgval_DeepCopy(upb_MessageValue msgval, TypeInfo type_info,
292
298
  case kUpb_CType_Bytes: {
293
299
  size_t n = msgval.str_val.size;
294
300
  char* mem = upb_Arena_Malloc(arena, n);
301
+ if (!mem) Arena_raise_oom();
295
302
  new_msgval.str_val.data = mem;
296
303
  new_msgval.str_val.size = n;
297
304
  memcpy(mem, msgval.str_val.data, n);
@@ -114,6 +114,7 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
114
114
 
115
115
  RB_OBJ_WRITE(ret, &self->def_to_descriptor, rb_hash_new());
116
116
  self->symtab = upb_DefPool_New();
117
+ if (!self->symtab) Arena_raise_oom();
117
118
 
118
119
  // Ruby treats all enums as open.
119
120
  upb_DefPool_DisableClosedEnumChecking(self->symtab);
@@ -485,13 +486,20 @@ static VALUE Descriptor_options(VALUE _self) {
485
486
  const google_protobuf_MessageOptions* opts =
486
487
  upb_MessageDef_Options(self->msgdef);
487
488
  upb_Arena* arena = upb_Arena_New();
489
+ if (!arena) goto err;
488
490
  size_t size;
489
491
  char* serialized =
490
492
  google_protobuf_MessageOptions_serialize(opts, arena, &size);
493
+ if (!serialized) goto err;
491
494
  VALUE message_options = decode_options(_self, "MessageOptions", size,
492
495
  serialized, self->descriptor_pool);
493
496
  upb_Arena_Free(arena);
494
497
  return message_options;
498
+
499
+ err:
500
+ if (arena) upb_Arena_Free(arena);
501
+ Arena_raise_oom();
502
+ return Qnil;
495
503
  }
496
504
 
497
505
  /*
@@ -506,16 +514,24 @@ static VALUE Descriptor_options(VALUE _self) {
506
514
  static VALUE Descriptor_to_proto(VALUE _self) {
507
515
  Descriptor* self = ruby_to_Descriptor(_self);
508
516
  upb_Arena* arena = upb_Arena_New();
517
+ if (!arena) goto err;
509
518
  google_protobuf_DescriptorProto* proto =
510
519
  upb_MessageDef_ToProto(self->msgdef, arena);
520
+ if (!proto) goto err;
511
521
  size_t size;
512
522
  const char* serialized =
513
523
  google_protobuf_DescriptorProto_serialize(proto, arena, &size);
524
+ if (!serialized) goto err;
514
525
  VALUE proto_class = rb_path2class("Google::Protobuf::DescriptorProto");
515
526
  VALUE proto_rb =
516
527
  Message_decode_bytes(size, serialized, 0, proto_class, false);
517
528
  upb_Arena_Free(arena);
518
529
  return proto_rb;
530
+
531
+ err:
532
+ if (arena) upb_Arena_Free(arena);
533
+ Arena_raise_oom();
534
+ return Qnil;
519
535
  }
520
536
 
521
537
  static void Descriptor_register(VALUE module) {
@@ -628,12 +644,19 @@ static VALUE FileDescriptor_options(VALUE _self) {
628
644
  FileDescriptor* self = ruby_to_FileDescriptor(_self);
629
645
  const google_protobuf_FileOptions* opts = upb_FileDef_Options(self->filedef);
630
646
  upb_Arena* arena = upb_Arena_New();
647
+ if (!arena) goto err;
631
648
  size_t size;
632
649
  char* serialized = google_protobuf_FileOptions_serialize(opts, arena, &size);
650
+ if (!serialized) goto err;
633
651
  VALUE file_options = decode_options(_self, "FileOptions", size, serialized,
634
652
  self->descriptor_pool);
635
653
  upb_Arena_Free(arena);
636
654
  return file_options;
655
+
656
+ err:
657
+ if (arena) upb_Arena_Free(arena);
658
+ Arena_raise_oom();
659
+ return Qnil;
637
660
  }
638
661
 
639
662
  /*
@@ -648,12 +671,15 @@ static VALUE FileDescriptor_options(VALUE _self) {
648
671
  static VALUE FileDescriptor_to_proto(VALUE _self) {
649
672
  FileDescriptor* self = ruby_to_FileDescriptor(_self);
650
673
  upb_Arena* arena = upb_Arena_New();
674
+ if (!arena) goto err;
651
675
  google_protobuf_FileDescriptorProto* file_proto =
652
676
  upb_FileDef_ToProto(self->filedef, arena);
677
+ if (!file_proto) goto err;
653
678
 
654
679
  size_t size;
655
680
  const char* serialized =
656
681
  google_protobuf_FileDescriptorProto_serialize(file_proto, arena, &size);
682
+ if (!serialized) goto err;
657
683
 
658
684
  VALUE file_proto_class =
659
685
  rb_path2class("Google::Protobuf::FileDescriptorProto");
@@ -661,6 +687,11 @@ static VALUE FileDescriptor_to_proto(VALUE _self) {
661
687
  Message_decode_bytes(size, serialized, 0, file_proto_class, false);
662
688
  upb_Arena_Free(arena);
663
689
  return proto_rb;
690
+
691
+ err:
692
+ if (arena) upb_Arena_Free(arena);
693
+ Arena_raise_oom();
694
+ return Qnil;
664
695
  }
665
696
 
666
697
  static void FileDescriptor_register(VALUE module) {
@@ -1085,7 +1116,9 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
1085
1116
 
1086
1117
  msgval = Convert_RubyToUpb(value, upb_FieldDef_Name(self->fielddef),
1087
1118
  TypeInfo_get(self->fielddef), arena);
1088
- upb_Message_SetFieldByDef(msg, self->fielddef, msgval, arena);
1119
+ if (!upb_Message_SetFieldByDef(msg, self->fielddef, msgval, arena)) {
1120
+ Arena_raise_oom();
1121
+ }
1089
1122
  return Qnil;
1090
1123
  }
1091
1124
 
@@ -1103,8 +1136,13 @@ static VALUE FieldDescriptor_options(VALUE _self) {
1103
1136
  const google_protobuf_FieldOptions* opts =
1104
1137
  upb_FieldDef_Options(self->fielddef);
1105
1138
  upb_Arena* arena = upb_Arena_New();
1139
+ if (!arena) Arena_raise_oom();
1106
1140
  size_t size;
1107
1141
  char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, &size);
1142
+ if (!serialized) {
1143
+ upb_Arena_Free(arena);
1144
+ Arena_raise_oom();
1145
+ }
1108
1146
  VALUE field_options = decode_options(_self, "FieldOptions", size, serialized,
1109
1147
  self->descriptor_pool);
1110
1148
  upb_Arena_Free(arena);
@@ -1123,11 +1161,20 @@ static VALUE FieldDescriptor_options(VALUE _self) {
1123
1161
  static VALUE FieldDescriptor_to_proto(VALUE _self) {
1124
1162
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
1125
1163
  upb_Arena* arena = upb_Arena_New();
1164
+ if (!arena) Arena_raise_oom();
1126
1165
  google_protobuf_FieldDescriptorProto* proto =
1127
1166
  upb_FieldDef_ToProto(self->fielddef, arena);
1167
+ if (!proto) {
1168
+ upb_Arena_Free(arena);
1169
+ Arena_raise_oom();
1170
+ }
1128
1171
  size_t size;
1129
1172
  const char* serialized =
1130
1173
  google_protobuf_FieldDescriptorProto_serialize(proto, arena, &size);
1174
+ if (!serialized) {
1175
+ upb_Arena_Free(arena);
1176
+ Arena_raise_oom();
1177
+ }
1131
1178
  VALUE proto_class = rb_path2class("Google::Protobuf::FieldDescriptorProto");
1132
1179
  VALUE proto_rb =
1133
1180
  Message_decode_bytes(size, serialized, 0, proto_class, false);
@@ -1279,8 +1326,13 @@ static VALUE OneOfDescriptor_options(VALUE _self) {
1279
1326
  const google_protobuf_OneofOptions* opts =
1280
1327
  upb_OneofDef_Options(self->oneofdef);
1281
1328
  upb_Arena* arena = upb_Arena_New();
1329
+ if (!arena) Arena_raise_oom();
1282
1330
  size_t size;
1283
1331
  char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, &size);
1332
+ if (!serialized) {
1333
+ upb_Arena_Free(arena);
1334
+ Arena_raise_oom();
1335
+ }
1284
1336
  VALUE oneof_options = decode_options(_self, "OneofOptions", size, serialized,
1285
1337
  self->descriptor_pool);
1286
1338
  upb_Arena_Free(arena);
@@ -1299,11 +1351,20 @@ static VALUE OneOfDescriptor_options(VALUE _self) {
1299
1351
  static VALUE OneOfDescriptor_to_proto(VALUE _self) {
1300
1352
  OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
1301
1353
  upb_Arena* arena = upb_Arena_New();
1354
+ if (!arena) Arena_raise_oom();
1302
1355
  google_protobuf_OneofDescriptorProto* proto =
1303
1356
  upb_OneofDef_ToProto(self->oneofdef, arena);
1357
+ if (!proto) {
1358
+ upb_Arena_Free(arena);
1359
+ Arena_raise_oom();
1360
+ }
1304
1361
  size_t size;
1305
1362
  const char* serialized =
1306
1363
  google_protobuf_OneofDescriptorProto_serialize(proto, arena, &size);
1364
+ if (!serialized) {
1365
+ upb_Arena_Free(arena);
1366
+ Arena_raise_oom();
1367
+ }
1307
1368
  VALUE proto_class = rb_path2class("Google::Protobuf::OneofDescriptorProto");
1308
1369
  VALUE proto_rb =
1309
1370
  Message_decode_bytes(size, serialized, 0, proto_class, false);
@@ -1529,8 +1590,13 @@ static VALUE EnumDescriptor_options(VALUE _self) {
1529
1590
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1530
1591
  const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(self->enumdef);
1531
1592
  upb_Arena* arena = upb_Arena_New();
1593
+ if (!arena) Arena_raise_oom();
1532
1594
  size_t size;
1533
1595
  char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, &size);
1596
+ if (!serialized) {
1597
+ upb_Arena_Free(arena);
1598
+ Arena_raise_oom();
1599
+ }
1534
1600
  VALUE enum_options = decode_options(_self, "EnumOptions", size, serialized,
1535
1601
  self->descriptor_pool);
1536
1602
  upb_Arena_Free(arena);
@@ -1548,12 +1614,21 @@ static VALUE EnumDescriptor_options(VALUE _self) {
1548
1614
  static VALUE EnumDescriptor_to_proto(VALUE _self) {
1549
1615
  EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
1550
1616
  upb_Arena* arena = upb_Arena_New();
1617
+ if (!arena) Arena_raise_oom();
1551
1618
  google_protobuf_EnumDescriptorProto* proto =
1552
1619
  upb_EnumDef_ToProto(self->enumdef, arena);
1620
+ if (!proto) {
1621
+ upb_Arena_Free(arena);
1622
+ Arena_raise_oom();
1623
+ }
1553
1624
 
1554
1625
  size_t size;
1555
1626
  const char* serialized =
1556
1627
  google_protobuf_EnumDescriptorProto_serialize(proto, arena, &size);
1628
+ if (!serialized) {
1629
+ upb_Arena_Free(arena);
1630
+ Arena_raise_oom();
1631
+ }
1557
1632
 
1558
1633
  VALUE proto_class = rb_path2class("Google::Protobuf::EnumDescriptorProto");
1559
1634
  VALUE proto_rb =
@@ -1707,9 +1782,14 @@ static VALUE ServiceDescriptor_options(VALUE _self) {
1707
1782
  const google_protobuf_ServiceOptions* opts =
1708
1783
  upb_ServiceDef_Options(self->servicedef);
1709
1784
  upb_Arena* arena = upb_Arena_New();
1785
+ if (!arena) Arena_raise_oom();
1710
1786
  size_t size;
1711
1787
  char* serialized =
1712
1788
  google_protobuf_ServiceOptions_serialize(opts, arena, &size);
1789
+ if (!serialized) {
1790
+ upb_Arena_Free(arena);
1791
+ Arena_raise_oom();
1792
+ }
1713
1793
  VALUE service_options = decode_options(_self, "ServiceOptions", size,
1714
1794
  serialized, self->descriptor_pool);
1715
1795
  upb_Arena_Free(arena);
@@ -1728,11 +1808,20 @@ static VALUE ServiceDescriptor_options(VALUE _self) {
1728
1808
  static VALUE ServiceDescriptor_to_proto(VALUE _self) {
1729
1809
  ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
1730
1810
  upb_Arena* arena = upb_Arena_New();
1811
+ if (!arena) Arena_raise_oom();
1731
1812
  google_protobuf_ServiceDescriptorProto* proto =
1732
1813
  upb_ServiceDef_ToProto(self->servicedef, arena);
1814
+ if (!proto) {
1815
+ upb_Arena_Free(arena);
1816
+ Arena_raise_oom();
1817
+ }
1733
1818
  size_t size;
1734
1819
  const char* serialized =
1735
1820
  google_protobuf_ServiceDescriptorProto_serialize(proto, arena, &size);
1821
+ if (!serialized) {
1822
+ upb_Arena_Free(arena);
1823
+ Arena_raise_oom();
1824
+ }
1736
1825
  VALUE proto_class = rb_path2class("Google::Protobuf::ServiceDescriptorProto");
1737
1826
  VALUE proto_rb =
1738
1827
  Message_decode_bytes(size, serialized, 0, proto_class, false);
@@ -1850,9 +1939,14 @@ static VALUE MethodDescriptor_options(VALUE _self) {
1850
1939
  const google_protobuf_MethodOptions* opts =
1851
1940
  upb_MethodDef_Options(self->methoddef);
1852
1941
  upb_Arena* arena = upb_Arena_New();
1942
+ if (!arena) Arena_raise_oom();
1853
1943
  size_t size;
1854
1944
  char* serialized =
1855
1945
  google_protobuf_MethodOptions_serialize(opts, arena, &size);
1946
+ if (!serialized) {
1947
+ upb_Arena_Free(arena);
1948
+ Arena_raise_oom();
1949
+ }
1856
1950
  VALUE method_options = decode_options(_self, "MethodOptions", size,
1857
1951
  serialized, self->descriptor_pool);
1858
1952
  upb_Arena_Free(arena);
@@ -1909,11 +2003,20 @@ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
1909
2003
  static VALUE MethodDescriptor_to_proto(VALUE _self) {
1910
2004
  MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
1911
2005
  upb_Arena* arena = upb_Arena_New();
2006
+ if (!arena) Arena_raise_oom();
1912
2007
  google_protobuf_MethodDescriptorProto* proto =
1913
2008
  upb_MethodDef_ToProto(self->methoddef, arena);
2009
+ if (!proto) {
2010
+ upb_Arena_Free(arena);
2011
+ Arena_raise_oom();
2012
+ }
1914
2013
  size_t size;
1915
2014
  const char* serialized =
1916
2015
  google_protobuf_MethodDescriptorProto_serialize(proto, arena, &size);
2016
+ if (!serialized) {
2017
+ upb_Arena_Free(arena);
2018
+ Arena_raise_oom();
2019
+ }
1917
2020
  VALUE proto_class = rb_path2class("Google::Protobuf::MethodDescriptorProto");
1918
2021
  VALUE proto_rb =
1919
2022
  Message_decode_bytes(size, serialized, 0, proto_class, false);
@@ -22,7 +22,12 @@ debug_enabled = ENV["PROTOBUF_CONFIG"] == "dbg"
22
22
 
23
23
  additional_c_flags = debug_enabled ? "-O0 -fno-omit-frame-pointer -fvisibility=default -g" : "-O3 -DNDEBUG -fvisibility=hidden"
24
24
 
25
- if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ || RUBY_PLATFORM =~ /freebsd/
25
+ if RUBY_PLATFORM =~ /mswin/
26
+ # cl.exe does not understand GCC-style flags. C11 or later is required
27
+ # for _Generic, which the upb MSVC atomics fall back on. c17 is the
28
+ # highest C standard mode cl.exe supports.
29
+ $CFLAGS += debug_enabled ? " -std:c17 -Od" : " -std:c17 -DNDEBUG"
30
+ elsif RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ || RUBY_PLATFORM =~ /freebsd/
26
31
  $CFLAGS += " -std=gnu99 -Wall -Wsign-compare -Wno-declaration-after-statement #{additional_c_flags}"
27
32
  else
28
33
  $CFLAGS += " -std=gnu99 #{additional_c_flags}"
@@ -91,6 +91,7 @@ static VALUE Map_new_this_type(Map* from) {
91
91
  VALUE arena_rb = Arena_new();
92
92
  upb_Map* map = upb_Map_New(Arena_get(arena_rb), from->key_type,
93
93
  from->value_type_info.type);
94
+ if (!map) Arena_raise_oom();
94
95
  VALUE ret =
95
96
  Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
96
97
  PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
@@ -110,8 +111,8 @@ static upb_Map* Map_GetMutable(VALUE _self) {
110
111
  return (upb_Map*)map;
111
112
  }
112
113
 
113
- VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
114
- TypeInfo val_info) {
114
+ VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type, TypeInfo val_info,
115
+ bool emit_defaults) {
115
116
  VALUE hash = rb_hash_new();
116
117
  TypeInfo key_info = TypeInfo_from_type(key_type);
117
118
 
@@ -121,7 +122,7 @@ VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
121
122
  upb_MessageValue key, val;
122
123
  while (upb_Map_Next(map, &key, &val, &iter)) {
123
124
  VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
124
- VALUE val_val = Scalar_CreateHash(val, val_info);
125
+ VALUE val_val = Scalar_CreateHash(val, val_info, emit_defaults);
125
126
  rb_hash_aset(hash, key_val, val_val);
126
127
  }
127
128
 
@@ -134,12 +135,15 @@ VALUE Map_deep_copy(VALUE obj) {
134
135
  upb_Arena* arena = Arena_get(new_arena_rb);
135
136
  upb_Map* new_map =
136
137
  upb_Map_New(arena, self->key_type, self->value_type_info.type);
138
+ if (!new_map) Arena_raise_oom();
137
139
  size_t iter = kUpb_Map_Begin;
138
140
  upb_MessageValue key, val;
139
141
  while (upb_Map_Next(self->map, &key, &val, &iter)) {
140
142
  upb_MessageValue val_copy =
141
143
  Msgval_DeepCopy(val, self->value_type_info, arena);
142
- upb_Map_Set(new_map, key, val_copy, arena);
144
+ if (!upb_Map_Set(new_map, key, val_copy, arena)) {
145
+ Arena_raise_oom();
146
+ }
143
147
  }
144
148
 
145
149
  return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
@@ -202,7 +206,9 @@ static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
202
206
  Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
203
207
  upb_MessageValue val_val =
204
208
  Convert_RubyToUpb(val, "", self->value_type_info, arena);
205
- upb_Map_Set(Map_GetMutable(_self), key_val, val_val, arena);
209
+ if (!upb_Map_Set(Map_GetMutable(_self), key_val, val_val, arena)) {
210
+ Arena_raise_oom();
211
+ }
206
212
  return ST_CONTINUE;
207
213
  }
208
214
 
@@ -228,7 +234,9 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
228
234
  size_t iter = kUpb_Map_Begin;
229
235
  upb_MessageValue key, val;
230
236
  while (upb_Map_Next(other->map, &key, &val, &iter)) {
231
- upb_Map_Set(self_map, key, val, arena);
237
+ if (!upb_Map_Set(self_map, key, val, arena)) {
238
+ Arena_raise_oom();
239
+ }
232
240
  }
233
241
  } else {
234
242
  rb_raise(rb_eArgError, "Unknown type merging into Map");
@@ -293,6 +301,7 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
293
301
  self->value_type_info =
294
302
  TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
295
303
  self->arena = Arena_new();
304
+ if (!self->arena) Arena_raise_oom();
296
305
 
297
306
  // Check that the key type is an allowed type.
298
307
  switch (self->key_type) {
@@ -311,6 +320,7 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
311
320
 
312
321
  self->map = upb_Map_New(Arena_get(self->arena), self->key_type,
313
322
  self->value_type_info.type);
323
+ if (!self->map) Arena_raise_oom();
314
324
  VALUE stored = ObjectCache_TryAdd(self->map, _self);
315
325
  (void)stored;
316
326
  PBRUBY_ASSERT(stored == _self);
@@ -424,12 +434,19 @@ static VALUE Map_index(VALUE _self, VALUE key) {
424
434
  static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
425
435
  Map* self = ruby_to_Map(_self);
426
436
  upb_Arena* arena = Arena_get(self->arena);
437
+ // The key must be copied into the arena, not aliased. Converting the value
438
+ // below can allocate a Ruby object and therefore trigger GC, which may free
439
+ // or move the String the key would otherwise point into. Passing NULL here is
440
+ // only safe when the key is consumed before any allocation, as in the lookup
441
+ // paths (Map_index, Map_has_key, Map_delete).
427
442
  upb_MessageValue key_upb =
428
- Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
443
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
429
444
  upb_MessageValue val_upb =
430
445
  Convert_RubyToUpb(val, "", self->value_type_info, arena);
431
446
 
432
- upb_Map_Set(Map_GetMutable(_self), key_upb, val_upb, arena);
447
+ if (!upb_Map_Set(Map_GetMutable(_self), key_upb, val_upb, arena)) {
448
+ Arena_raise_oom();
449
+ }
433
450
 
434
451
  return val;
435
452
  }
@@ -523,7 +540,9 @@ static VALUE Map_dup(VALUE _self) {
523
540
 
524
541
  upb_MessageValue key, val;
525
542
  while (upb_Map_Next(self->map, &key, &val, &iter)) {
526
- upb_Map_Set(new_map, key, val, arena);
543
+ if (!upb_Map_Set(new_map, key, val, arena)) {
544
+ Arena_raise_oom();
545
+ }
527
546
  }
528
547
 
529
548
  return new_map_rb;
@@ -655,6 +674,7 @@ VALUE Map_EmptyFrozen(const upb_FieldDef* f) {
655
674
  self->arena = Arena_new();
656
675
  self->map =
657
676
  upb_Map_New(Arena_get(self->arena), key_type, value_type_info.type);
677
+ if (!self->map) Arena_raise_oom();
658
678
  self->key_type = key_type;
659
679
  self->value_type_info = value_type_info;
660
680
  if (self->value_type_info.type == kUpb_CType_Message) {
@@ -699,7 +719,8 @@ VALUE Map_hash(VALUE _self) {
699
719
  */
700
720
  VALUE Map_to_h(VALUE _self) {
701
721
  Map* self = ruby_to_Map(_self);
702
- return Map_CreateHash(self->map, self->key_type, self->value_type_info);
722
+ return Map_CreateHash(self->map, self->key_type, self->value_type_info,
723
+ false);
703
724
  }
704
725
 
705
726
  /*
@@ -31,7 +31,8 @@ void Map_Inspect(StringBuilder* b, const upb_Map* map, upb_CType key_type,
31
31
  TypeInfo val_type);
32
32
 
33
33
  // Returns a new Hash object containing the contents of this Map.
34
- VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type, TypeInfo val_info);
34
+ VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type, TypeInfo val_info,
35
+ bool emit_defaults);
35
36
 
36
37
  // Returns a deep copy of this Map object.
37
38
  VALUE Map_deep_copy(VALUE obj);