google-protobuf 3.15.7 → 3.19.0

Sign up to get free protection for your applications and to get access to all the features.

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,