google-protobuf 3.15.0.rc.2-x64-mingw32 → 3.15.4-x64-mingw32
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 +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/lib/google/2.3/protobuf_c.so +0 -0
- data/lib/google/2.4/protobuf_c.so +0 -0
- data/lib/google/2.5/protobuf_c.so +0 -0
- data/lib/google/2.6/protobuf_c.so +0 -0
- data/lib/google/2.7/protobuf_c.so +0 -0
- data/lib/google/3.0/protobuf_c.so +0 -0
- data/tests/basic.rb +32 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea2082db1e9d7d386de2c0b025de7d4f8f8886fd141db2bca8214675334ea463
|
4
|
+
data.tar.gz: 28b1240941cec4bfe78a4614c01515be6c85347993c703999646e04b14f78b2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfc5ac101c540fb4f9323681a9bbb4dcc014ff3f4ec7937c9ac67b37831e2ad6019ecd51a04eb5d7b476c42ab86c7d7e43b645731639162d59f4f3d4df7ee661
|
7
|
+
data.tar.gz: 81f0bd039eb1d14a60fd6bffe2caef9cb24a641efdee424e4f941e8e916b0d81f902fbc9b83e69e088c902dbdab0f96eff1dfb4cd22f8f21868e442d4a8d6d04
|
@@ -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)) {
|
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.4
|
5
5
|
platform: x64-mingw32
|
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-03 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.4/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:
|
148
|
+
version: '0'
|
149
149
|
requirements: []
|
150
150
|
rubygems_version: 3.2.3
|
151
151
|
signing_key:
|