google-protobuf 3.15.3-x86-linux → 3.16.0.rc.1-x86-linux

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: baa9d45f0c885758e32b6d221977ef378567b0296dd0aa15b5b2e28801a662bd
4
- data.tar.gz: 33c18b9fb8e2de390a19cec01d5f73bbc2b2089dd1bf3a96ead061822007437d
3
+ metadata.gz: 57dfaa408109ee7a9c22b44623711fb8c636f61734770091f0cfa5d81e157d6b
4
+ data.tar.gz: a948993f9f83cb9fd75b9090f795dbd0a3119e9a1c770fe4121f7a6ba13b4f8a
5
5
  SHA512:
6
- metadata.gz: 6fee0801f9c427747d0511023a81fa2d6199308178b08e42c4e75af8277263311b4a6057e0fabb4befe97eebae67e04d6e3694cf9ff0e94a2670128d4b3239df
7
- data.tar.gz: 436d37545240010cb2bcc0d5429b2727ba81c161cb95486a5d6a2a40ef09675eee6eb59eb512c4a79fc1fd30ea5bc7f1fc82deb6b9f1cb139e023778fcc15398
6
+ metadata.gz: d2394db83f6f2d7243eab2dd788cd77fe156d849966e6c4551c61f90ce4a97acf8c727b0efdff6ad7e3f6b19f8d7fed575ff918b9921c706c553c42fe73c074a
7
+ data.tar.gz: 9ac3ad884829f1bc2ca83aad0da07f45f1c34d7646c1580b3f0c72ad60f7ab6fd7e93010cb15ab4a64fe70a8080568203faedb7c3b4715cb71c81d85649e739b
@@ -315,7 +315,7 @@ bool Msgval_IsEqual(upb_msgval val1, upb_msgval val2, TypeInfo type_info) {
315
315
  return memcmp(&val1, &val2, 8) == 0;
316
316
  case UPB_TYPE_STRING:
317
317
  case UPB_TYPE_BYTES:
318
- return val1.str_val.size != val2.str_val.size ||
318
+ return val1.str_val.size == val2.str_val.size &&
319
319
  memcmp(val1.str_val.data, val2.str_val.data,
320
320
  val1.str_val.size) == 0;
321
321
  case UPB_TYPE_MESSAGE:
@@ -697,16 +697,13 @@ bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
697
697
  * field is of a primitive type).
698
698
  */
699
699
  static VALUE Message_eq(VALUE _self, VALUE _other) {
700
- if (TYPE(_self) != TYPE(_other)) {
701
- return Qfalse;
702
- }
700
+ if (CLASS_OF(_self) != CLASS_OF(_other)) return Qfalse;
703
701
 
704
702
  Message* self = ruby_to_Message(_self);
705
703
  Message* other = ruby_to_Message(_other);
704
+ assert(self->msgdef == other->msgdef);
706
705
 
707
- return Message_Equal(self->msg, other->msg, self->msgdef)
708
- ? Qtrue
709
- : Qfalse;
706
+ return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
710
707
  }
711
708
 
712
709
  uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
@@ -1250,7 +1247,9 @@ upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
1250
1247
 
1251
1248
  const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1252
1249
  const char* name, upb_arena* arena) {
1253
- if (value == Qnil) return NULL;
1250
+ if (value == Qnil) {
1251
+ rb_raise(cTypeError, "nil message not allowed here.");
1252
+ }
1254
1253
 
1255
1254
  VALUE klass = CLASS_OF(value);
1256
1255
  VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
@@ -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) {
@@ -251,14 +251,80 @@ void Arena_register(VALUE module) {
251
251
  // The object is used only for its identity; it does not contain any data.
252
252
  VALUE secondary_map = Qnil;
253
253
 
254
+ // Mutations to the map are under a mutex, because SeconaryMap_MaybeGC()
255
+ // iterates over the map which cannot happen in parallel with insertions, or
256
+ // Ruby will throw:
257
+ // can't add a new key into hash during iteration (RuntimeError)
258
+ VALUE secondary_map_mutex = Qnil;
259
+
260
+ // Lambda that will GC entries from the secondary map that are no longer present
261
+ // in the primary map.
262
+ VALUE gc_secondary_map_lambda = Qnil;
263
+ ID length;
264
+
265
+ extern VALUE weak_obj_cache;
266
+
254
267
  static void SecondaryMap_Init() {
255
268
  rb_gc_register_address(&secondary_map);
269
+ rb_gc_register_address(&gc_secondary_map_lambda);
270
+ rb_gc_register_address(&secondary_map_mutex);
256
271
  secondary_map = rb_hash_new();
272
+ gc_secondary_map_lambda = rb_eval_string(
273
+ "->(secondary, weak) {\n"
274
+ " secondary.delete_if { |k, v| !weak.key?(v) }\n"
275
+ "}\n");
276
+ secondary_map_mutex = rb_mutex_new();
277
+ length = rb_intern("length");
257
278
  }
258
279
 
259
- static VALUE SecondaryMap_Get(VALUE key) {
280
+ // The secondary map is a regular Hash, and will never shrink on its own.
281
+ // The main object cache is a WeakMap that will automatically remove entries
282
+ // when the target object is no longer reachable, but unless we manually
283
+ // remove the corresponding entries from the secondary map, it will grow
284
+ // without bound.
285
+ //
286
+ // To avoid this unbounded growth we periodically remove entries from the
287
+ // secondary map that are no longer present in the WeakMap. The logic of
288
+ // how often to perform this GC is an artbirary tuning parameter that
289
+ // represents a straightforward CPU/memory tradeoff.
290
+ //
291
+ // Requires: secondary_map_mutex is held.
292
+ static void SecondaryMap_MaybeGC() {
293
+ PBRUBY_ASSERT(rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
294
+ size_t weak_len = NUM2ULL(rb_funcall(weak_obj_cache, length, 0));
295
+ size_t secondary_len = RHASH_SIZE(secondary_map);
296
+ if (secondary_len < weak_len) {
297
+ // Logically this case should not be possible: a valid entry cannot exist in
298
+ // the weak table unless there is a corresponding entry in the secondary
299
+ // table. It should *always* be the case that secondary_len >= weak_len.
300
+ //
301
+ // However ObjectSpace::WeakMap#length (and therefore weak_len) is
302
+ // unreliable: it overreports its true length by including non-live objects.
303
+ // However these non-live objects are not yielded in iteration, so we may
304
+ // have previously deleted them from the secondary map in a previous
305
+ // invocation of SecondaryMap_MaybeGC().
306
+ //
307
+ // In this case, we can't measure any waste, so we just return.
308
+ return;
309
+ }
310
+ size_t waste = secondary_len - weak_len;
311
+ // GC if we could remove at least 2000 entries or 20% of the table size
312
+ // (whichever is greater). Since the cost of the GC pass is O(N), we
313
+ // want to make sure that we condition this on overall table size, to
314
+ // avoid O(N^2) CPU costs.
315
+ size_t threshold = PBRUBY_MAX(secondary_len * 0.2, 2000);
316
+ if (waste > threshold) {
317
+ rb_funcall(gc_secondary_map_lambda, rb_intern("call"), 2,
318
+ secondary_map, weak_obj_cache);
319
+ }
320
+ }
321
+
322
+ // Requires: secondary_map_mutex is held by this thread iff create == true.
323
+ static VALUE SecondaryMap_Get(VALUE key, bool create) {
324
+ PBRUBY_ASSERT(!create || rb_mutex_locked_p(secondary_map_mutex) == Qtrue);
260
325
  VALUE ret = rb_hash_lookup(secondary_map, key);
261
- if (ret == Qnil) {
326
+ if (ret == Qnil && create) {
327
+ SecondaryMap_MaybeGC();
262
328
  ret = rb_eval_string("Object.new");
263
329
  rb_hash_aset(secondary_map, key, ret);
264
330
  }
@@ -267,14 +333,15 @@ static VALUE SecondaryMap_Get(VALUE key) {
267
333
 
268
334
  #endif
269
335
 
270
- static VALUE ObjectCache_GetKey(const void* key) {
336
+ // Requires: secondary_map_mutex is held by this thread iff create == true.
337
+ static VALUE ObjectCache_GetKey(const void* key, bool create) {
271
338
  char buf[sizeof(key)];
272
339
  memcpy(&buf, &key, sizeof(key));
273
340
  intptr_t key_int = (intptr_t)key;
274
341
  PBRUBY_ASSERT((key_int & 3) == 0);
275
342
  VALUE ret = LL2NUM(key_int >> 2);
276
343
  #if USE_SECONDARY_MAP
277
- ret = SecondaryMap_Get(ret);
344
+ ret = SecondaryMap_Get(ret, create);
278
345
  #endif
279
346
  return ret;
280
347
  }
@@ -298,14 +365,20 @@ static void ObjectCache_Init() {
298
365
 
299
366
  void ObjectCache_Add(const void* key, VALUE val) {
300
367
  PBRUBY_ASSERT(ObjectCache_Get(key) == Qnil);
301
- VALUE key_rb = ObjectCache_GetKey(key);
368
+ #if USE_SECONDARY_MAP
369
+ rb_mutex_lock(secondary_map_mutex);
370
+ #endif
371
+ VALUE key_rb = ObjectCache_GetKey(key, true);
302
372
  rb_funcall(weak_obj_cache, item_set, 2, key_rb, val);
373
+ #if USE_SECONDARY_MAP
374
+ rb_mutex_unlock(secondary_map_mutex);
375
+ #endif
303
376
  PBRUBY_ASSERT(ObjectCache_Get(key) == val);
304
377
  }
305
378
 
306
379
  // Returns the cached object for this key, if any. Otherwise returns Qnil.
307
380
  VALUE ObjectCache_Get(const void* key) {
308
- VALUE key_rb = ObjectCache_GetKey(key);
381
+ VALUE key_rb = ObjectCache_GetKey(key, false);
309
382
  return rb_funcall(weak_obj_cache, item_get, 1, key_rb);
310
383
  }
311
384
 
@@ -368,8 +441,10 @@ void Init_protobuf_c() {
368
441
  Map_register(protobuf);
369
442
  Message_register(protobuf);
370
443
 
371
- cError = rb_const_get(protobuf, rb_intern("Error"));
444
+ cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
445
+ rb_gc_register_mark_object(cParseError);
372
446
  cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
447
+ rb_gc_register_mark_object(cTypeError);
373
448
 
374
449
  rb_define_singleton_method(protobuf, "discard_unknown",
375
450
  Google_Protobuf_discard_unknown, 1);
@@ -106,6 +106,8 @@ extern VALUE cTypeError;
106
106
  #define PBRUBY_ASSERT(expr) assert(expr)
107
107
  #endif
108
108
 
109
+ #define PBRUBY_MAX(x, y) (((x) > (y)) ? (x) : (y))
110
+
109
111
  #define UPB_UNUSED(var) (void)var
110
112
 
111
113
  #endif // __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
@@ -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
@@ -52,10 +52,15 @@ module BasicTest
52
52
 
53
53
  outer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("Outer").msgclass
54
54
 
55
- outer_proto = outer.new(
55
+ outer.new(
56
56
  inners: []
57
- )
58
- outer_proto['inners'].to_s
57
+ )['inners'].to_s
58
+
59
+ assert_raise Google::Protobuf::TypeError do
60
+ outer.new(
61
+ inners: [nil]
62
+ ).to_s
63
+ end
59
64
  end
60
65
 
61
66
  def test_has_field
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.3
4
+ version: 3.16.0.rc.1
5
5
  platform: x86-linux
6
6
  authors:
7
7
  - Protobuf Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-25 00:00:00.000000000 Z
11
+ date: 2021-04-07 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.3/ruby
131
+ source_code_uri: https://github.com/protocolbuffers/protobuf/tree/v3.16.0-rc1/ruby
132
132
  post_install_message:
133
133
  rdoc_options: []
134
134
  require_paths:
@@ -143,9 +143,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
143
  version: 3.1.dev
144
144
  required_rubygems_version: !ruby/object:Gem::Requirement
145
145
  requirements:
146
- - - ">="
146
+ - - ">"
147
147
  - !ruby/object:Gem::Version
148
- version: '0'
148
+ version: 1.3.1
149
149
  requirements: []
150
150
  rubygems_version: 3.2.3
151
151
  signing_key: