google-protobuf 3.15.7 → 3.19.0

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.

@@ -167,7 +167,8 @@ VALUE Map_deep_copy(VALUE obj) {
167
167
  new_arena_rb);
168
168
  }
169
169
 
170
- const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
170
+ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
171
+ upb_arena* arena) {
171
172
  const upb_fielddef* key_field = map_field_key(field);
172
173
  const upb_fielddef* value_field = map_field_value(field);
173
174
  TypeInfo value_type_info = TypeInfo_get(value_field);
@@ -189,6 +190,7 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
189
190
  rb_raise(cTypeError, "Map value type has wrong message/enum class");
190
191
  }
191
192
 
193
+ Arena_fuse(self->arena, arena);
192
194
  return self->map;
193
195
  }
194
196
 
@@ -236,7 +238,7 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
236
238
  upb_msg *self_msg = Map_GetMutable(_self);
237
239
  size_t iter = UPB_MAP_BEGIN;
238
240
 
239
- upb_arena_fuse(arena, Arena_get(other->arena));
241
+ Arena_fuse(other->arena, arena);
240
242
 
241
243
  if (self->key_type != other->key_type ||
242
244
  self->value_type_info.type != other->value_type_info.type ||
@@ -511,7 +513,7 @@ static VALUE Map_dup(VALUE _self) {
511
513
  upb_arena *arena = Arena_get(new_self->arena);
512
514
  upb_map *new_map = Map_GetMutable(new_map_rb);
513
515
 
514
- upb_arena_fuse(arena, Arena_get(self->arena));
516
+ Arena_fuse(self->arena, arena);
515
517
 
516
518
  while (upb_mapiter_next(self->map, &iter)) {
517
519
  upb_msgval key = upb_mapiter_key(self->map, iter);
@@ -678,7 +680,10 @@ void Map_register(VALUE module) {
678
680
  rb_define_method(klass, "delete", Map_delete, 1);
679
681
  rb_define_method(klass, "clear", Map_clear, 0);
680
682
  rb_define_method(klass, "length", Map_length, 0);
683
+ rb_define_method(klass, "size", Map_length, 0);
681
684
  rb_define_method(klass, "dup", Map_dup, 0);
685
+ // Also define #clone so that we don't inherit Object#clone.
686
+ rb_define_method(klass, "clone", Map_dup, 0);
682
687
  rb_define_method(klass, "==", Map_eq, 1);
683
688
  rb_define_method(klass, "freeze", Map_freeze, 0);
684
689
  rb_define_method(klass, "hash", Map_hash, 0);
@@ -44,7 +44,8 @@ VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
44
44
  // Gets the underlying upb_map for this Ruby map object, which must have
45
45
  // key/value type that match |field|. If this is not a map or the type doesn't
46
46
  // match, raises an exception.
47
- const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field);
47
+ const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
48
+ upb_arena *arena);
48
49
 
49
50
  // Implements #inspect for this map by appending its contents to |b|.
50
51
  void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
@@ -35,7 +35,6 @@
35
35
  #include "map.h"
36
36
  #include "protobuf.h"
37
37
  #include "repeated_field.h"
38
- #include "third_party/wyhash/wyhash.h"
39
38
 
40
39
  static VALUE cParseError = Qnil;
41
40
  static ID descriptor_instancevar_interned;
@@ -277,9 +276,9 @@ static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
277
276
  upb_arena* arena) {
278
277
  upb_msgval msgval;
279
278
  if (upb_fielddef_ismap(f)) {
280
- msgval.map_val = Map_GetUpbMap(val, f);
279
+ msgval.map_val = Map_GetUpbMap(val, f, arena);
281
280
  } else if (upb_fielddef_isseq(f)) {
282
- msgval.array_val = RepeatedField_GetUpbArray(val, f);
281
+ msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
283
282
  } else {
284
283
  if (val == Qnil &&
285
284
  (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
@@ -660,7 +659,7 @@ static VALUE Message_dup(VALUE _self) {
660
659
  // TODO(copy unknown fields?)
661
660
  // TODO(use official upb msg copy function)
662
661
  memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
663
- upb_arena_fuse(Arena_get(new_msg_self->arena), Arena_get(self->arena));
662
+ Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
664
663
  return new_msg;
665
664
  }
666
665
 
@@ -717,7 +716,7 @@ uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
717
716
  &size);
718
717
 
719
718
  if (data) {
720
- uint64_t ret = wyhash(data, size, seed, _wyp);
719
+ uint64_t ret = Wyhash(data, size, seed, kWyhashSalt);
721
720
  upb_arena_free(arena);
722
721
  return ret;
723
722
  } else {
@@ -734,7 +733,10 @@ uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
734
733
  */
735
734
  static VALUE Message_hash(VALUE _self) {
736
735
  Message* self = ruby_to_Message(_self);
737
- return INT2FIX(Message_Hash(self->msg, self->msgdef, 0));
736
+ uint64_t hash_value = Message_Hash(self->msg, self->msgdef, 0);
737
+ // RUBY_FIXNUM_MAX should be one less than a power of 2.
738
+ assert((RUBY_FIXNUM_MAX & (RUBY_FIXNUM_MAX + 1)) == 0);
739
+ return INT2FIX(hash_value & RUBY_FIXNUM_MAX);
738
740
  }
739
741
 
740
742
  /*
@@ -791,6 +793,14 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
791
793
  VALUE msg_value;
792
794
  VALUE msg_key;
793
795
 
796
+ if (!is_proto2 && upb_fielddef_issubmsg(field) &&
797
+ !upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
798
+ // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
799
+ msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
800
+ rb_hash_aset(hash, msg_key, Qnil);
801
+ continue;
802
+ }
803
+
794
804
  // Do not include fields that are not present (oneof or optional fields).
795
805
  if (is_proto2 && upb_fielddef_haspresence(field) &&
796
806
  !upb_msg_has(msg, field)) {
@@ -1303,7 +1313,7 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1303
1313
  }
1304
1314
 
1305
1315
  Message* self = ruby_to_Message(value);
1306
- upb_arena_fuse(arena, Arena_get(self->arena));
1316
+ Arena_fuse(self->arena, arena);
1307
1317
 
1308
1318
  return self->msg;
1309
1319
  }
@@ -37,7 +37,7 @@
37
37
  #include "message.h"
38
38
  #include "repeated_field.h"
39
39
 
40
- VALUE cError;
40
+ VALUE cParseError;
41
41
  VALUE cTypeError;
42
42
 
43
43
  const upb_fielddef* map_field_key(const upb_fielddef* field) {
@@ -180,6 +180,7 @@ static void Arena_mark(void *data) {
180
180
  static void Arena_free(void *data) {
181
181
  Arena *arena = data;
182
182
  upb_arena_free(arena->arena);
183
+ xfree(arena);
183
184
  }
184
185
 
185
186
  static VALUE cArena;
@@ -203,6 +204,16 @@ upb_arena *Arena_get(VALUE _arena) {
203
204
  return arena->arena;
204
205
  }
205
206
 
207
+ void Arena_fuse(VALUE _arena, upb_arena *other) {
208
+ Arena *arena;
209
+ TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
210
+ if (!upb_arena_fuse(arena->arena, other)) {
211
+ rb_raise(rb_eRuntimeError,
212
+ "Unable to fuse arenas. This should never happen since Ruby does "
213
+ "not use initial blocks");
214
+ }
215
+ }
216
+
206
217
  VALUE Arena_new() {
207
218
  return Arena_alloc(cArena);
208
219
  }
@@ -237,8 +248,16 @@ void Arena_register(VALUE module) {
237
248
  // We use WeakMap for the cache. For Ruby <2.7 we also need a secondary Hash
238
249
  // to store WeakMap keys because Ruby <2.7 WeakMap doesn't allow non-finalizable
239
250
  // keys.
240
-
241
- #if RUBY_API_VERSION_CODE >= 20700
251
+ //
252
+ // We also need the secondary Hash if sizeof(long) < sizeof(VALUE), because this
253
+ // means it may not be possible to fit a pointer into a Fixnum. Keys are
254
+ // pointers, and if they fit into a Fixnum, Ruby doesn't collect them, but if
255
+ // they overflow and require allocating a Bignum, they could get collected
256
+ // prematurely, thus removing the cache entry. This happens on 64-bit Windows,
257
+ // on which pointers are 64 bits but longs are 32 bits. In this case, we enable
258
+ // the secondary Hash to hold the keys and prevent them from being collected.
259
+
260
+ #if RUBY_API_VERSION_CODE >= 20700 && SIZEOF_LONG >= SIZEOF_VALUE
242
261
  #define USE_SECONDARY_MAP 0
243
262
  #else
244
263
  #define USE_SECONDARY_MAP 1
@@ -325,7 +344,7 @@ static VALUE SecondaryMap_Get(VALUE key, bool create) {
325
344
  VALUE ret = rb_hash_lookup(secondary_map, key);
326
345
  if (ret == Qnil && create) {
327
346
  SecondaryMap_MaybeGC();
328
- ret = rb_eval_string("Object.new");
347
+ ret = rb_class_new_instance(0, NULL, rb_cObject);
329
348
  rb_hash_aset(secondary_map, key, ret);
330
349
  }
331
350
  return ret;
@@ -335,11 +354,9 @@ static VALUE SecondaryMap_Get(VALUE key, bool create) {
335
354
 
336
355
  // Requires: secondary_map_mutex is held by this thread iff create == true.
337
356
  static VALUE ObjectCache_GetKey(const void* key, bool create) {
338
- char buf[sizeof(key)];
339
- memcpy(&buf, &key, sizeof(key));
340
- intptr_t key_int = (intptr_t)key;
341
- PBRUBY_ASSERT((key_int & 3) == 0);
342
- VALUE ret = LL2NUM(key_int >> 2);
357
+ VALUE key_val = (VALUE)key;
358
+ PBRUBY_ASSERT((key_val & 3) == 0);
359
+ VALUE ret = LL2NUM(key_val >> 2);
343
360
  #if USE_SECONDARY_MAP
344
361
  ret = SecondaryMap_Get(ret, create);
345
362
  #endif
@@ -441,8 +458,10 @@ void Init_protobuf_c() {
441
458
  Map_register(protobuf);
442
459
  Message_register(protobuf);
443
460
 
444
- cError = rb_const_get(protobuf, rb_intern("Error"));
461
+ cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
462
+ rb_gc_register_mark_object(cParseError);
445
463
  cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
464
+ rb_gc_register_mark_object(cTypeError);
446
465
 
447
466
  rb_define_singleton_method(protobuf, "discard_unknown",
448
467
  Google_Protobuf_discard_unknown, 1);
@@ -55,6 +55,10 @@ 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
+ // Fuses this arena to another, throwing a Ruby exception if this is not
59
+ // possible.
60
+ void Arena_fuse(VALUE arena, upb_arena *other);
61
+
58
62
  // Pins this Ruby object to the lifetime of this arena, so that as long as the
59
63
  // arena is alive this object will not be collected.
60
64
  //
@@ -34,7 +34,6 @@
34
34
  #include "defs.h"
35
35
  #include "message.h"
36
36
  #include "protobuf.h"
37
- #include "third_party/wyhash/wyhash.h"
38
37
 
39
38
  // -----------------------------------------------------------------------------
40
39
  // Repeated field container type.
@@ -149,7 +148,8 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
149
148
  return new_rptfield;
150
149
  }
151
150
 
152
- const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field) {
151
+ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
152
+ upb_arena* arena) {
153
153
  RepeatedField* self;
154
154
  TypeInfo type_info = TypeInfo_get(field);
155
155
 
@@ -167,6 +167,7 @@ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field)
167
167
  rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
168
168
  }
169
169
 
170
+ Arena_fuse(self->arena, arena);
170
171
  return self->array;
171
172
  }
172
173
 
@@ -412,7 +413,7 @@ static VALUE RepeatedField_dup(VALUE _self) {
412
413
  int size = upb_array_size(self->array);
413
414
  int i;
414
415
 
415
- upb_arena_fuse(arena, Arena_get(self->arena));
416
+ Arena_fuse(self->arena, arena);
416
417
 
417
418
  for (i = 0; i < size; i++) {
418
419
  upb_msgval msgval = upb_array_get(self->array, i);
@@ -550,6 +551,7 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
550
551
  RepeatedField* dupped = ruby_to_RepeatedField(dupped_);
551
552
  upb_array *dupped_array = RepeatedField_GetMutable(dupped_);
552
553
  upb_arena* arena = Arena_get(dupped->arena);
554
+ Arena_fuse(list_rptfield->arena, arena);
553
555
  int size = upb_array_size(list_rptfield->array);
554
556
  int i;
555
557
 
@@ -44,7 +44,8 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
44
44
  // Gets the underlying upb_array for this Ruby RepeatedField object, which must
45
45
  // have a type that matches |f|. If this is not a repeated field or the type
46
46
  // doesn't match, raises an exception.
47
- const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f);
47
+ const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f,
48
+ upb_arena* arena);
48
49
 
49
50
  // Implements #inspect for this repeated field by appending its contents to |b|.
50
51
  void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,