google-protobuf 3.15.0-universal-darwin → 3.15.5-universal-darwin

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.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1c93443dc69dd5d213fe57808799dc537640e16bcd76a8b3ba267659369ce36
4
- data.tar.gz: ba1159f5396b4d599b112cc98318e2b55331828b11c1ea0c81654f38dfc614f6
3
+ metadata.gz: 152a419245524837e516b8041a033d25694b04aba29c011b50e789413bb077d1
4
+ data.tar.gz: b9dc4f70c168a6b094c7b2a968d720e5078d1a179579ea08a968ad03a1582bac
5
5
  SHA512:
6
- metadata.gz: 42547d98098e841cc62d429f09de5f00a9b8acd05ba695ff9efa540364abdd8c312d760106a3533aac5ca57ea52917cf594c6ddb5f05bf8229df71e3c9539f72
7
- data.tar.gz: 36feb9a133bc5fdc1993ee9ce4bae948bdb41225b247b34c69826e07c950cd41799ed74de909ada81ea21e053e0e4dbe319effd93ce81a4f8a79d57d9ffc8224
6
+ metadata.gz: d968106a49787d65a66dbe30f23b20fb356798d7b677330cde25d1739cb2431a4897a61419bf45d5eb3651f9798e10a1faaea2fa9e66e4d1c584974002a50a1b
7
+ data.tar.gz: 4db1dd5a86642ef34f712151fb8009a54329c2d380abf0e98e72f4db314425711a9837d12f19dfd4bec2351fb8d2b8268431f7cebeacc40993134a3c256b6014
@@ -295,7 +295,7 @@ static VALUE DescriptorPool_alloc(VALUE klass) {
295
295
 
296
296
  self->def_to_descriptor = rb_hash_new();
297
297
  self->symtab = upb_symtab_new();
298
- ObjectCache_Add(self->symtab, ret, _upb_symtab_arena(self->symtab));
298
+ ObjectCache_Add(self->symtab, ret);
299
299
 
300
300
  return ret;
301
301
  }
@@ -960,16 +960,14 @@ static VALUE FieldDescriptor_subtype(VALUE _self) {
960
960
  static VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
961
961
  FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
962
962
  const upb_msgdef *m;
963
- const upb_msgdef *msg = Message_Get(msg_rb, &m);
964
- VALUE arena = Message_GetArena(msg_rb);
965
- upb_msgval msgval;
963
+
964
+ Message_Get(msg_rb, &m);
966
965
 
967
966
  if (m != upb_fielddef_containingtype(self->fielddef)) {
968
967
  rb_raise(cTypeError, "get method called on wrong message type");
969
968
  }
970
969
 
971
- msgval = upb_msg_get(msg, self->fielddef);
972
- return Convert_UpbToRuby(msgval, TypeInfo_get(self->fielddef), arena);
970
+ return Message_getfield(msg_rb, self->fielddef);
973
971
  }
974
972
 
975
973
  /*
@@ -93,7 +93,7 @@ VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
93
93
  if (val == Qnil) {
94
94
  val = Map_alloc(cMap);
95
95
  Map* self;
96
- ObjectCache_Add(map, val, Arena_get(arena));
96
+ ObjectCache_Add(map, val);
97
97
  TypedData_Get_Struct(val, Map, &Map_type, self);
98
98
  self->map = map;
99
99
  self->arena = arena;
@@ -318,7 +318,7 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
318
318
 
319
319
  self->map = upb_map_new(Arena_get(self->arena), self->key_type,
320
320
  self->value_type_info.type);
321
- ObjectCache_Add(self->map, _self, Arena_get(self->arena));
321
+ ObjectCache_Add(self->map, _self);
322
322
 
323
323
  if (init_arg != Qnil) {
324
324
  Map_merge_into_self(_self, init_arg);
@@ -590,9 +590,10 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
590
590
  */
591
591
  static VALUE Map_freeze(VALUE _self) {
592
592
  Map* self = ruby_to_Map(_self);
593
-
594
- ObjectCache_Pin(self->map, _self, Arena_get(self->arena));
595
- RB_OBJ_FREEZE(_self);
593
+ if (!RB_OBJ_FROZEN(_self)) {
594
+ Arena_Pin(self->arena, _self);
595
+ RB_OBJ_FREEZE(_self);
596
+ }
596
597
  return _self;
597
598
  }
598
599
 
@@ -105,7 +105,7 @@ void Message_InitPtr(VALUE self_, upb_msg *msg, VALUE arena) {
105
105
  Message* self = ruby_to_Message(self_);
106
106
  self->msg = msg;
107
107
  self->arena = arena;
108
- ObjectCache_Add(msg, self_, Arena_get(arena));
108
+ ObjectCache_Add(msg, self_);
109
109
  }
110
110
 
111
111
  VALUE Message_GetArena(VALUE msg_rb) {
@@ -292,6 +292,35 @@ static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
292
292
  upb_msg_set(msg, f, msgval, arena);
293
293
  }
294
294
 
295
+ VALUE Message_getfield(VALUE _self, const upb_fielddef* f) {
296
+ Message* self = ruby_to_Message(_self);
297
+ // This is a special-case: upb_msg_mutable() for map & array are logically
298
+ // const (they will not change what is serialized) but physically
299
+ // non-const, as they do allocate a repeated field or map. The logical
300
+ // constness means it's ok to do even if the message is frozen.
301
+ upb_msg *msg = (upb_msg*)self->msg;
302
+ upb_arena *arena = Arena_get(self->arena);
303
+ if (upb_fielddef_ismap(f)) {
304
+ upb_map *map = upb_msg_mutable(msg, f, arena).map;
305
+ const upb_fielddef *key_f = map_field_key(f);
306
+ const upb_fielddef *val_f = map_field_value(f);
307
+ upb_fieldtype_t key_type = upb_fielddef_type(key_f);
308
+ TypeInfo value_type_info = TypeInfo_get(val_f);
309
+ return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
310
+ } else if (upb_fielddef_isseq(f)) {
311
+ upb_array *arr = upb_msg_mutable(msg, f, arena).array;
312
+ return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
313
+ } else if (upb_fielddef_issubmsg(f)) {
314
+ if (!upb_msg_has(self->msg, f)) return Qnil;
315
+ upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
316
+ const upb_msgdef *m = upb_fielddef_msgsubdef(f);
317
+ return Message_GetRubyWrapper(submsg, m, self->arena);
318
+ } else {
319
+ upb_msgval msgval = upb_msg_get(self->msg, f);
320
+ return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
321
+ }
322
+ }
323
+
295
324
  static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
296
325
  int accessor_type, int argc, VALUE* argv) {
297
326
  upb_arena *arena = Arena_get(Message_GetArena(_self));
@@ -350,36 +379,11 @@ static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
350
379
  return INT2NUM(msgval.int32_val);
351
380
  }
352
381
  }
353
- case METHOD_GETTER: {
354
- Message* self = ruby_to_Message(_self);
355
- // This is a special-case: upb_msg_mutable() for map & array are logically
356
- // const (they will not change what is serialized) but physically
357
- // non-const, as they do allocate a repeated field or map. The logical
358
- // constness means it's ok to do even if the message is frozen.
359
- upb_msg *msg = (upb_msg*)self->msg;
360
- if (upb_fielddef_ismap(f)) {
361
- upb_map *map = upb_msg_mutable(msg, f, arena).map;
362
- const upb_fielddef *key_f = map_field_key(f);
363
- const upb_fielddef *val_f = map_field_value(f);
364
- upb_fieldtype_t key_type = upb_fielddef_type(key_f);
365
- TypeInfo value_type_info = TypeInfo_get(val_f);
366
- return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
367
- } else if (upb_fielddef_isseq(f)) {
368
- upb_array *arr = upb_msg_mutable(msg, f, arena).array;
369
- return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
370
- } else if (upb_fielddef_issubmsg(f)) {
371
- if (!upb_msg_has(self->msg, f)) return Qnil;
372
- upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
373
- const upb_msgdef *m = upb_fielddef_msgsubdef(f);
374
- return Message_GetRubyWrapper(submsg, m, self->arena);
375
- } else {
376
- upb_msgval msgval = upb_msg_get(self->msg, f);
377
- return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
378
- }
382
+ case METHOD_GETTER:
383
+ return Message_getfield(_self, f);
379
384
  default:
380
385
  rb_raise(rb_eRuntimeError, "Internal error, no such accessor: %d",
381
386
  accessor_type);
382
- }
383
387
  }
384
388
  }
385
389
 
@@ -851,8 +855,10 @@ static VALUE Message_to_h(VALUE _self) {
851
855
  */
852
856
  static VALUE Message_freeze(VALUE _self) {
853
857
  Message* self = ruby_to_Message(_self);
854
- ObjectCache_Pin(self->msg, _self, Arena_get(self->arena));
855
- RB_OBJ_FREEZE(_self);
858
+ if (!RB_OBJ_FROZEN(_self)) {
859
+ Arena_Pin(self->arena, _self);
860
+ RB_OBJ_FREEZE(_self);
861
+ }
856
862
  return _self;
857
863
  }
858
864
 
@@ -866,7 +872,6 @@ static VALUE Message_freeze(VALUE _self) {
866
872
  static VALUE Message_index(VALUE _self, VALUE field_name) {
867
873
  Message* self = ruby_to_Message(_self);
868
874
  const upb_fielddef* field;
869
- upb_msgval val;
870
875
 
871
876
  Check_Type(field_name, T_STRING);
872
877
  field = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
@@ -875,8 +880,7 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
875
880
  return Qnil;
876
881
  }
877
882
 
878
- val = upb_msg_get(self->msg, field);
879
- return Convert_UpbToRuby(val, TypeInfo_get(field), self->arena);
883
+ return Message_getfield(_self, field);
880
884
  }
881
885
 
882
886
  /*
@@ -1246,7 +1250,9 @@ upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
1246
1250
 
1247
1251
  const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1248
1252
  const char* name, upb_arena* arena) {
1249
- if (value == Qnil) return NULL;
1253
+ if (value == Qnil) {
1254
+ rb_raise(cTypeError, "nil message not allowed here.");
1255
+ }
1250
1256
 
1251
1257
  VALUE klass = CLASS_OF(value);
1252
1258
  VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
@@ -1285,7 +1291,7 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1285
1291
  if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
1286
1292
 
1287
1293
  sec.int64_val = NUM2LL(value);
1288
- nsec.int32_val = (NUM2DBL(value) - NUM2LL(value)) * 1000000000;
1294
+ nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
1289
1295
  upb_msg_set(msg, sec_f, sec, arena);
1290
1296
  upb_msg_set(msg, nsec_f, nsec, arena);
1291
1297
  return msg;
@@ -63,6 +63,9 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
63
63
  // object will reference |arena| and ensure that it outlives this object.
64
64
  VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena);
65
65
 
66
+ // Gets the given field from this message.
67
+ VALUE Message_getfield(VALUE _self, const upb_fielddef* f);
68
+
66
69
  // Implements #inspect for this message, printing the text to |b|.
67
70
  void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
68
71
  const upb_msgdef* m);
@@ -167,30 +167,55 @@ void StringBuilder_PrintMsgval(StringBuilder* b, upb_msgval val,
167
167
  // Arena
168
168
  // -----------------------------------------------------------------------------
169
169
 
170
- void Arena_free(void* data) { upb_arena_free(data); }
170
+ typedef struct {
171
+ upb_arena *arena;
172
+ VALUE pinned_objs;
173
+ } Arena;
174
+
175
+ static void Arena_mark(void *data) {
176
+ Arena *arena = data;
177
+ rb_gc_mark(arena->pinned_objs);
178
+ }
179
+
180
+ static void Arena_free(void *data) {
181
+ Arena *arena = data;
182
+ upb_arena_free(arena->arena);
183
+ }
171
184
 
172
185
  static VALUE cArena;
173
186
 
174
187
  const rb_data_type_t Arena_type = {
175
188
  "Google::Protobuf::Internal::Arena",
176
- { NULL, Arena_free, NULL },
189
+ { Arena_mark, Arena_free, NULL },
190
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
177
191
  };
178
192
 
179
193
  static VALUE Arena_alloc(VALUE klass) {
180
- upb_arena *arena = upb_arena_new();
194
+ Arena *arena = ALLOC(Arena);
195
+ arena->arena = upb_arena_new();
196
+ arena->pinned_objs = Qnil;
181
197
  return TypedData_Wrap_Struct(klass, &Arena_type, arena);
182
198
  }
183
199
 
184
200
  upb_arena *Arena_get(VALUE _arena) {
185
- upb_arena *arena;
186
- TypedData_Get_Struct(_arena, upb_arena, &Arena_type, arena);
187
- return arena;
201
+ Arena *arena;
202
+ TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
203
+ return arena->arena;
188
204
  }
189
205
 
190
206
  VALUE Arena_new() {
191
207
  return Arena_alloc(cArena);
192
208
  }
193
209
 
210
+ void Arena_Pin(VALUE _arena, VALUE obj) {
211
+ Arena *arena;
212
+ TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
213
+ if (arena->pinned_objs == Qnil) {
214
+ arena->pinned_objs = rb_ary_new();
215
+ }
216
+ rb_ary_push(arena->pinned_objs, obj);
217
+ }
218
+
194
219
  void Arena_register(VALUE module) {
195
220
  VALUE internal = rb_define_module_under(module, "Internal");
196
221
  VALUE klass = rb_define_class_under(internal, "Arena", rb_cObject);
@@ -209,122 +234,79 @@ void Arena_register(VALUE module) {
209
234
  // different wrapper objects for the same C object, which saves memory and
210
235
  // preserves object identity.
211
236
  //
212
- // We use Hash and/or WeakMap for the cache. WeakMap is faster overall
213
- // (probably due to removal being integrated with GC) but doesn't work for Ruby
214
- // <2.7 (see note below). We need Hash for Ruby <2.7 and for cases where we
215
- // need to GC-root the object (notably when the object has been frozen).
237
+ // We use WeakMap for the cache. For Ruby <2.7 we also need a secondary Hash
238
+ // to store WeakMap keys because Ruby <2.7 WeakMap doesn't allow non-finalizable
239
+ // keys.
216
240
 
217
241
  #if RUBY_API_VERSION_CODE >= 20700
218
- #define USE_WEAK_MAP 1
242
+ #define USE_SECONDARY_MAP 0
219
243
  #else
220
- #define USE_WEAK_MAP 0
244
+ #define USE_SECONDARY_MAP 1
221
245
  #endif
222
246
 
223
- static VALUE ObjectCache_GetKey(const void* key) {
224
- char buf[sizeof(key)];
225
- memcpy(&buf, &key, sizeof(key));
226
- intptr_t key_int = (intptr_t)key;
227
- PBRUBY_ASSERT((key_int & 3) == 0);
228
- return LL2NUM(key_int >> 2);
229
- }
247
+ #if USE_SECONDARY_MAP
230
248
 
231
- // Strong object cache, uses regular Hash and GC-roots objects.
232
- // - For Ruby <2.7, used for all objects.
233
- // - For Ruby >=2.7, used only for frozen objects, so we preserve the "frozen"
234
- // bit (since this information is not preserved at the upb level).
249
+ // Maps Numeric -> Object. The object is then used as a key into the WeakMap.
250
+ // This is needed for Ruby <2.7 where a number cannot be a key to WeakMap.
251
+ // The object is used only for its identity; it does not contain any data.
252
+ VALUE secondary_map = Qnil;
235
253
 
236
- VALUE strong_obj_cache = Qnil;
237
-
238
- static void StrongObjectCache_Init() {
239
- rb_gc_register_address(&strong_obj_cache);
240
- strong_obj_cache = rb_hash_new();
254
+ static void SecondaryMap_Init() {
255
+ rb_gc_register_address(&secondary_map);
256
+ secondary_map = rb_hash_new();
241
257
  }
242
258
 
243
- static void StrongObjectCache_Remove(void* key) {
244
- VALUE key_rb = ObjectCache_GetKey(key);
245
- PBRUBY_ASSERT(rb_hash_lookup(strong_obj_cache, key_rb) != Qnil);
246
- rb_hash_delete(strong_obj_cache, key_rb);
259
+ static VALUE SecondaryMap_Get(VALUE key) {
260
+ VALUE ret = rb_hash_lookup(secondary_map, key);
261
+ if (ret == Qnil) {
262
+ ret = rb_eval_string("Object.new");
263
+ rb_hash_aset(secondary_map, key, ret);
264
+ }
265
+ return ret;
247
266
  }
248
267
 
249
- static VALUE StrongObjectCache_Get(const void* key) {
250
- VALUE key_rb = ObjectCache_GetKey(key);
251
- return rb_hash_lookup(strong_obj_cache, key_rb);
252
- }
268
+ #endif
253
269
 
254
- static void StrongObjectCache_Add(const void* key, VALUE val,
255
- upb_arena* arena) {
256
- PBRUBY_ASSERT(StrongObjectCache_Get(key) == Qnil);
257
- VALUE key_rb = ObjectCache_GetKey(key);
258
- rb_hash_aset(strong_obj_cache, key_rb, val);
259
- upb_arena_addcleanup(arena, (void*)key, StrongObjectCache_Remove);
270
+ static VALUE ObjectCache_GetKey(const void* key) {
271
+ char buf[sizeof(key)];
272
+ memcpy(&buf, &key, sizeof(key));
273
+ intptr_t key_int = (intptr_t)key;
274
+ PBRUBY_ASSERT((key_int & 3) == 0);
275
+ VALUE ret = LL2NUM(key_int >> 2);
276
+ #if USE_SECONDARY_MAP
277
+ ret = SecondaryMap_Get(ret);
278
+ #endif
279
+ return ret;
260
280
  }
261
281
 
262
- // Weak object cache. This speeds up the test suite significantly, so we
263
- // presume it speeds up real code also. However we can only use it in Ruby
264
- // >=2.7 due to:
265
- // https://bugs.ruby-lang.org/issues/16035
266
-
267
- #if USE_WEAK_MAP
282
+ // Public ObjectCache API.
268
283
 
269
284
  VALUE weak_obj_cache = Qnil;
285
+ ID item_get;
286
+ ID item_set;
270
287
 
271
- static void WeakObjectCache_Init() {
288
+ static void ObjectCache_Init() {
272
289
  rb_gc_register_address(&weak_obj_cache);
273
290
  VALUE klass = rb_eval_string("ObjectSpace::WeakMap");
274
291
  weak_obj_cache = rb_class_new_instance(0, NULL, klass);
275
- }
276
-
277
- static VALUE WeakObjectCache_Get(const void* key) {
278
- VALUE key_rb = ObjectCache_GetKey(key);
279
- VALUE ret = rb_funcall(weak_obj_cache, rb_intern("[]"), 1, key_rb);
280
- return ret;
281
- }
282
-
283
- static void WeakObjectCache_Add(const void* key, VALUE val) {
284
- PBRUBY_ASSERT(WeakObjectCache_Get(key) == Qnil);
285
- VALUE key_rb = ObjectCache_GetKey(key);
286
- rb_funcall(weak_obj_cache, rb_intern("[]="), 2, key_rb, val);
287
- PBRUBY_ASSERT(WeakObjectCache_Get(key) == val);
288
- }
289
-
290
- #endif
291
-
292
- // Public ObjectCache API.
293
-
294
- static void ObjectCache_Init() {
295
- StrongObjectCache_Init();
296
- #if USE_WEAK_MAP
297
- WeakObjectCache_Init();
292
+ item_get = rb_intern("[]");
293
+ item_set = rb_intern("[]=");
294
+ #if USE_SECONDARY_MAP
295
+ SecondaryMap_Init();
298
296
  #endif
299
297
  }
300
298
 
301
- void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena) {
302
- #if USE_WEAK_MAP
303
- (void)arena;
304
- WeakObjectCache_Add(key, val);
305
- #else
306
- StrongObjectCache_Add(key, val, arena);
307
- #endif
299
+ void ObjectCache_Add(const void* key, VALUE val) {
300
+ PBRUBY_ASSERT(ObjectCache_Get(key) == Qnil);
301
+ VALUE key_rb = ObjectCache_GetKey(key);
302
+ rb_funcall(weak_obj_cache, item_set, 2, key_rb, val);
303
+ PBRUBY_ASSERT(ObjectCache_Get(key) == val);
308
304
  }
309
305
 
310
306
  // Returns the cached object for this key, if any. Otherwise returns Qnil.
311
307
  VALUE ObjectCache_Get(const void* key) {
312
- #if USE_WEAK_MAP
313
- return WeakObjectCache_Get(key);
314
- #else
315
- return StrongObjectCache_Get(key);
316
- #endif
317
- }
318
-
319
- void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena) {
320
- #if USE_WEAK_MAP
321
- PBRUBY_ASSERT(WeakObjectCache_Get(key) == val);
322
- // This will GC-root the object, but we'll still use the weak map for
323
- // actual lookup.
324
- StrongObjectCache_Add(key, val, arena);
325
- #else
326
- // Value is already pinned, nothing to do.
327
- #endif
308
+ VALUE key_rb = ObjectCache_GetKey(key);
309
+ return rb_funcall(weak_obj_cache, item_get, 1, key_rb);
328
310
  }
329
311
 
330
312
  /*
@@ -55,6 +55,13 @@ const upb_fielddef* map_field_value(const upb_fielddef* field);
55
55
  VALUE Arena_new();
56
56
  upb_arena *Arena_get(VALUE arena);
57
57
 
58
+ // Pins this Ruby object to the lifetime of this arena, so that as long as the
59
+ // arena is alive this object will not be collected.
60
+ //
61
+ // We use this to guarantee that the "frozen" bit on the object will be
62
+ // remembered, even if the user drops their reference to this precise object.
63
+ void Arena_Pin(VALUE arena, VALUE obj);
64
+
58
65
  // -----------------------------------------------------------------------------
59
66
  // ObjectCache
60
67
  // -----------------------------------------------------------------------------
@@ -68,19 +75,11 @@ upb_arena *Arena_get(VALUE arena);
68
75
  // Adds an entry to the cache. The "arena" parameter must give the arena that
69
76
  // "key" was allocated from. In Ruby <2.7.0, it will be used to remove the key
70
77
  // from the cache when the arena is destroyed.
71
- void ObjectCache_Add(const void* key, VALUE val, upb_arena *arena);
78
+ void ObjectCache_Add(const void* key, VALUE val);
72
79
 
73
80
  // Returns the cached object for this key, if any. Otherwise returns Qnil.
74
81
  VALUE ObjectCache_Get(const void* key);
75
82
 
76
- // Pins the previously added object so it is GC-rooted. This turns the
77
- // reference to "val" from weak to strong. We use this to guarantee that the
78
- // "frozen" bit on the object will be remembered, even if the user drops their
79
- // reference to this precise object.
80
- //
81
- // The "arena" parameter must give the arena that "key" was allocated from.
82
- void ObjectCache_Pin(const void* key, VALUE val, upb_arena *arena);
83
-
84
83
  // -----------------------------------------------------------------------------
85
84
  // StringBuilder, for inspect
86
85
  // -----------------------------------------------------------------------------
@@ -88,7 +88,7 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* array, TypeInfo type_info,
88
88
  if (val == Qnil) {
89
89
  val = RepeatedField_alloc(cRepeatedField);
90
90
  RepeatedField* self;
91
- ObjectCache_Add(array, val, Arena_get(arena));
91
+ ObjectCache_Add(array, val);
92
92
  TypedData_Get_Struct(val, RepeatedField, &RepeatedField_type, self);
93
93
  self->array = array;
94
94
  self->arena = arena;
@@ -500,9 +500,10 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
500
500
  */
501
501
  static VALUE RepeatedField_freeze(VALUE _self) {
502
502
  RepeatedField* self = ruby_to_RepeatedField(_self);
503
-
504
- ObjectCache_Pin(self->array, _self, Arena_get(self->arena));
505
- RB_OBJ_FREEZE(_self);
503
+ if (!RB_OBJ_FROZEN(_self)) {
504
+ Arena_Pin(self->arena, _self);
505
+ RB_OBJ_FREEZE(_self);
506
+ }
506
507
  return _self;
507
508
  }
508
509
 
@@ -610,7 +611,7 @@ VALUE RepeatedField_init(int argc, VALUE* argv, VALUE _self) {
610
611
 
611
612
  self->type_info = TypeInfo_FromClass(argc, argv, 0, &self->type_class, &ary);
612
613
  self->array = upb_array_new(arena, self->type_info.type);
613
- ObjectCache_Add(self->array, _self, arena);
614
+ ObjectCache_Add(self->array, _self);
614
615
 
615
616
  if (ary != Qnil) {
616
617
  if (!RB_TYPE_P(ary, T_ARRAY)) {
@@ -6663,10 +6663,9 @@ void upb_array_set(upb_array *arr, size_t i, upb_msgval val) {
6663
6663
  }
6664
6664
 
6665
6665
  bool upb_array_append(upb_array *arr, upb_msgval val, upb_arena *arena) {
6666
- if (!_upb_array_realloc(arr, arr->len + 1, arena)) {
6666
+ if (!upb_array_resize(arr, arr->len + 1, arena)) {
6667
6667
  return false;
6668
6668
  }
6669
- arr->len++;
6670
6669
  upb_array_set(arr, arr->len - 1, val);
6671
6670
  return true;
6672
6671
  }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
data/tests/basic.rb CHANGED
@@ -31,6 +31,38 @@ module BasicTest
31
31
  end
32
32
  include CommonTests
33
33
 
34
+ def test_issue_8311_crash
35
+ Google::Protobuf::DescriptorPool.generated_pool.build do
36
+ add_file("inner.proto", :syntax => :proto3) do
37
+ add_message "Inner" do
38
+ # Removing either of these fixes the segfault.
39
+ optional :foo, :string, 1
40
+ optional :bar, :string, 2
41
+ end
42
+ end
43
+ end
44
+
45
+ Google::Protobuf::DescriptorPool.generated_pool.build do
46
+ add_file("outer.proto", :syntax => :proto3) do
47
+ add_message "Outer" do
48
+ repeated :inners, :message, 1, "Inner"
49
+ end
50
+ end
51
+ end
52
+
53
+ outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
54
+
55
+ outer.new(
56
+ inners: []
57
+ )['inners'].to_s
58
+
59
+ assert_raise Google::Protobuf::TypeError do
60
+ outer.new(
61
+ inners: [nil]
62
+ ).to_s
63
+ end
64
+ end
65
+
34
66
  def test_has_field
35
67
  m = TestSingularFields.new
36
68
  assert !m.has_singular_msg?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-protobuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.15.0
4
+ version: 3.15.5
5
5
  platform: universal-darwin
6
6
  authors:
7
7
  - Protobuf Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-18 00:00:00.000000000 Z
11
+ date: 2021-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler-dock
@@ -128,7 +128,7 @@ homepage: https://developers.google.com/protocol-buffers
128
128
  licenses:
129
129
  - BSD-3-Clause
130
130
  metadata:
131
- source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v3.15.0/ruby
131
+ source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v3.15.5/ruby
132
132
  post_install_message:
133
133
  rdoc_options: []
134
134
  require_paths:
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  - !ruby/object:Gem::Version
148
148
  version: '0'
149
149
  requirements: []
150
- rubygems_version: 3.2.11
150
+ rubygems_version: 3.2.13
151
151
  signing_key:
152
152
  specification_version: 4
153
153
  summary: Protocol Buffers