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 +4 -4
- data/ext/google/protobuf_c/defs.c +4 -6
- data/ext/google/protobuf_c/map.c +6 -5
- data/ext/google/protobuf_c/message.c +41 -35
- data/ext/google/protobuf_c/message.h +3 -0
- data/ext/google/protobuf_c/protobuf.c +77 -95
- data/ext/google/protobuf_c/protobuf.h +8 -9
- data/ext/google/protobuf_c/repeated_field.c +6 -5
- data/ext/google/protobuf_c/ruby-upb.c +1 -2
- data/lib/google/2.3/protobuf_c.bundle +0 -0
- data/lib/google/2.4/protobuf_c.bundle +0 -0
- data/lib/google/2.5/protobuf_c.bundle +0 -0
- data/lib/google/2.6/protobuf_c.bundle +0 -0
- data/lib/google/2.7/protobuf_c.bundle +0 -0
- data/lib/google/3.0/protobuf_c.bundle +0 -0
- data/tests/basic.rb +32 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 152a419245524837e516b8041a033d25694b04aba29c011b50e789413bb077d1
|
4
|
+
data.tar.gz: b9dc4f70c168a6b094c7b2a968d720e5078d1a179579ea08a968ad03a1582bac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
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
|
-
|
964
|
-
|
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
|
-
|
972
|
-
return Convert_UpbToRuby(msgval, TypeInfo_get(self->fielddef), arena);
|
970
|
+
return Message_getfield(msg_rb, self->fielddef);
|
973
971
|
}
|
974
972
|
|
975
973
|
/*
|
data/ext/google/protobuf_c/map.c
CHANGED
@@ -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
|
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
|
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
|
-
|
595
|
-
|
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_
|
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
|
-
|
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
|
-
|
855
|
-
|
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
|
-
|
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)
|
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
|
-
|
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
|
-
{
|
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
|
-
|
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
|
-
|
186
|
-
TypedData_Get_Struct(_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
|
213
|
-
//
|
214
|
-
//
|
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
|
242
|
+
#define USE_SECONDARY_MAP 0
|
219
243
|
#else
|
220
|
-
#define
|
244
|
+
#define USE_SECONDARY_MAP 1
|
221
245
|
#endif
|
222
246
|
|
223
|
-
|
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
|
-
//
|
232
|
-
//
|
233
|
-
//
|
234
|
-
|
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
|
-
|
237
|
-
|
238
|
-
|
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
|
244
|
-
VALUE
|
245
|
-
|
246
|
-
|
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
|
-
|
250
|
-
VALUE key_rb = ObjectCache_GetKey(key);
|
251
|
-
return rb_hash_lookup(strong_obj_cache, key_rb);
|
252
|
-
}
|
268
|
+
#endif
|
253
269
|
|
254
|
-
static
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
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
|
-
//
|
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
|
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
|
-
|
278
|
-
|
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
|
302
|
-
|
303
|
-
(
|
304
|
-
|
305
|
-
|
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
|
-
|
313
|
-
return
|
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
|
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
|
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
|
-
|
505
|
-
|
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
|
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 (!
|
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.
|
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-
|
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.
|
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.
|
150
|
+
rubygems_version: 3.2.13
|
151
151
|
signing_key:
|
152
152
|
specification_version: 4
|
153
153
|
summary: Protocol Buffers
|