msgpack 1.5.3 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6c335ddbadfa205f9fabd011bdcbe768924a532e762550a8c974035eb2b6ca59
4
- data.tar.gz: 24abdf9bb3b34484ded41acc0ac4291ba25ee48660cca66968b265453b35ed96
3
+ metadata.gz: 9c3bd9f87eaddd3212797209da93c4ec3a1c2384cb4a41e0ea9feb48a75523f2
4
+ data.tar.gz: 16d6223c1c98f50e629c029f077383cbbd7cd194af038255fd28d37aeecbb39a
5
5
  SHA512:
6
- metadata.gz: d0ebbe1cca5508d5a1fe4b28d7558e1cbe35e82bdf3b4596e3998feb86298e4bba718153a275ab808bf83651225f20cea52e1117df816e629cc05fbf2513f53c
7
- data.tar.gz: 17ed1e47c07f1388a78b844ff2621414531eea6287b020a1568c9f2b6c2d3e8cbacff6e18a00159604fc241676cdd7a1542af4c4a41f1fc0795945912e885d6f
6
+ metadata.gz: 6d4bd9048f852ac4c6e1365b07e6a8df9869cd0d9b2ce2c8bff7c836fe3e513451cf8895b36a719d09beaafdb85101363b705da719e5e9e9c7361ee1de96f2cf
7
+ data.tar.gz: a15ac8e77af9dc0ccb06ed266efe1ff93a2bae78e2ab5b980ba87af486d08e34676f9203fbc6b646b3c7f14e2fbdf7d4e9e1892fd58d0ca214a39de0dd2ee345
data/ChangeLog CHANGED
@@ -1,3 +1,16 @@
1
+ 2022-08-23 1.5.6:
2
+
3
+ * No actual code change, just re-release the `java` version properly.
4
+
5
+ 2022-08-22 1.5.5:
6
+
7
+ * Fix a segfault when GC triggers inside a recursive extension.
8
+
9
+ 2022-07-25 1.5.4:
10
+
11
+ * Fix a segfault when deserializing empty symbol (`:""`).
12
+ * Improve compilation flags to not strip debug symbols.
13
+
1
14
  2022-05-30 version 1.5.3:
2
15
 
3
16
  * Fix deduplication of empty strings when using the `freeze: true` option.
data/README.md CHANGED
@@ -40,7 +40,7 @@ or build msgpack-ruby and install:
40
40
  MessagePack for Ruby should run on x86, ARM, PowerPC, SPARC and other CPU architectures.
41
41
 
42
42
  And it works with MRI (CRuby) and Rubinius.
43
- Patches to improve portability is highly welcomed.
43
+ Patches to improve portability are highly welcomed.
44
44
 
45
45
 
46
46
  ## Serializing objects
@@ -51,6 +51,7 @@ Use `MessagePack.pack` or `to_msgpack`:
51
51
  require 'msgpack'
52
52
  msg = MessagePack.pack(obj) # or
53
53
  msg = obj.to_msgpack
54
+ File.binwrite('mydata.msgpack', msg)
54
55
  ```
55
56
 
56
57
  ### Streaming serialization
@@ -71,6 +72,7 @@ Use `MessagePack.unpack`:
71
72
 
72
73
  ```ruby
73
74
  require 'msgpack'
75
+ msg = File.binread('mydata.msgpack')
74
76
  obj = MessagePack.unpack(msg)
75
77
  ```
76
78
 
data/bench/bench.rb ADDED
@@ -0,0 +1,78 @@
1
+ # % bundle install
2
+ # % bundle exec ruby bench/bench.rb
3
+
4
+ require 'msgpack'
5
+
6
+ require 'benchmark/ips'
7
+
8
+ object_plain = {
9
+ 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
10
+ }
11
+
12
+ data_plain = MessagePack.pack(object_plain)
13
+
14
+ object_structured = {
15
+ 'remote_host' => '127.0.0.1',
16
+ 'remote_user' => '-',
17
+ 'date' => '10/Oct/2000:13:55:36 -0700',
18
+ 'request' => 'GET /apache_pb.gif HTTP/1.0',
19
+ 'method' => 'GET',
20
+ 'path' => '/apache_pb.gif',
21
+ 'protocol' => 'HTTP/1.0',
22
+ 'status' => 200,
23
+ 'bytes' => 2326,
24
+ 'referer' => 'http://www.example.com/start.html',
25
+ 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
26
+ }
27
+
28
+ data_structured = MessagePack.pack(object_structured)
29
+
30
+ class Extended
31
+ def to_msgpack_ext
32
+ MessagePack.pack({})
33
+ end
34
+
35
+ def self.from_msgpack_ext(data)
36
+ MessagePack.unpack(data)
37
+ Extended.new
38
+ end
39
+ end
40
+
41
+ object_extended = {
42
+ 'extended' => Extended.new
43
+ }
44
+
45
+ extended_packer = MessagePack::Packer.new
46
+ extended_packer.register_type(0x00, Extended, :to_msgpack_ext)
47
+ data_extended = extended_packer.pack(object_extended).to_s
48
+
49
+ Benchmark.ips do |x|
50
+ x.report('pack-plain') do
51
+ MessagePack.pack(object_plain)
52
+ end
53
+
54
+ x.report('pack-structured') do
55
+ MessagePack.pack(object_structured)
56
+ end
57
+
58
+ x.report('pack-extended') do
59
+ packer = MessagePack::Packer.new
60
+ packer.register_type(0x00, Extended, :to_msgpack_ext)
61
+ packer.pack(object_extended).to_s
62
+ end
63
+
64
+ x.report('unpack-plain') do
65
+ MessagePack.unpack(data_plain)
66
+ end
67
+
68
+ x.report('unpack-structured') do
69
+ MessagePack.unpack(data_structured)
70
+ end
71
+
72
+ x.report('unpack-extended') do
73
+ unpacker = MessagePack::Unpacker.new
74
+ unpacker.register_type(0x00, Extended, :from_msgpack_ext)
75
+ unpacker.feed data_extended
76
+ unpacker.read
77
+ end
78
+ end
data/ext/msgpack/buffer.c CHANGED
@@ -588,13 +588,13 @@ size_t msgpack_buffer_flush_to_io(msgpack_buffer_t* b, VALUE io, ID write_method
588
588
  size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
589
589
  {
590
590
  if(b->io_buffer == Qnil) {
591
- b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, LONG2NUM(b->io_buffer_size));
591
+ b->io_buffer = rb_funcall(b->io, b->io_partial_read_method, 1, SIZET2NUM(b->io_buffer_size));
592
592
  if(b->io_buffer == Qnil) {
593
593
  rb_raise(rb_eEOFError, "IO reached end of file");
594
594
  }
595
595
  StringValue(b->io_buffer);
596
596
  } else {
597
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(b->io_buffer_size), b->io_buffer);
597
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(b->io_buffer_size), b->io_buffer);
598
598
  if(ret == Qnil) {
599
599
  rb_raise(rb_eEOFError, "IO reached end of file");
600
600
  }
@@ -613,9 +613,11 @@ size_t _msgpack_buffer_feed_from_io(msgpack_buffer_t* b)
613
613
 
614
614
  size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string, size_t length)
615
615
  {
616
+ #define MIN(x, y) (((x) < (y)) ? (x) : (y))
617
+
616
618
  if(RSTRING_LEN(string) == 0) {
617
619
  /* direct read */
618
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), string);
620
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), string);
619
621
  if(ret == Qnil) {
620
622
  return 0;
621
623
  }
@@ -627,7 +629,7 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
627
629
  b->io_buffer = rb_str_buf_new(0);
628
630
  }
629
631
 
630
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
632
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(MIN(b->io_buffer_size, length)), b->io_buffer);
631
633
  if(ret == Qnil) {
632
634
  return 0;
633
635
  }
@@ -635,6 +637,8 @@ size_t _msgpack_buffer_read_from_io_to_string(msgpack_buffer_t* b, VALUE string,
635
637
 
636
638
  rb_str_buf_cat(string, (const void*)RSTRING_PTR(b->io_buffer), rl);
637
639
  return rl;
640
+
641
+ #undef MIN
638
642
  }
639
643
 
640
644
  size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
@@ -643,7 +647,7 @@ size_t _msgpack_buffer_skip_from_io(msgpack_buffer_t* b, size_t length)
643
647
  b->io_buffer = rb_str_buf_new(0);
644
648
  }
645
649
 
646
- VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, LONG2NUM(length), b->io_buffer);
650
+ VALUE ret = rb_funcall(b->io, b->io_partial_read_method, 2, SIZET2NUM(length), b->io_buffer);
647
651
  if(ret == Qnil) {
648
652
  return 0;
649
653
  }
@@ -96,17 +96,17 @@ void MessagePack_Buffer_set_options(msgpack_buffer_t* b, VALUE io, VALUE options
96
96
 
97
97
  v = rb_hash_aref(options, sym_read_reference_threshold);
98
98
  if(v != Qnil) {
99
- msgpack_buffer_set_read_reference_threshold(b, NUM2ULONG(v));
99
+ msgpack_buffer_set_read_reference_threshold(b, NUM2SIZET(v));
100
100
  }
101
101
 
102
102
  v = rb_hash_aref(options, sym_write_reference_threshold);
103
103
  if(v != Qnil) {
104
- msgpack_buffer_set_write_reference_threshold(b, NUM2ULONG(v));
104
+ msgpack_buffer_set_write_reference_threshold(b, NUM2SIZET(v));
105
105
  }
106
106
 
107
107
  v = rb_hash_aref(options, sym_io_buffer_size);
108
108
  if(v != Qnil) {
109
- msgpack_buffer_set_io_buffer_size(b, NUM2ULONG(v));
109
+ msgpack_buffer_set_io_buffer_size(b, NUM2SIZET(v));
110
110
  }
111
111
  }
112
112
  }
@@ -301,11 +301,11 @@ static VALUE Buffer_skip(VALUE self, VALUE sn)
301
301
 
302
302
  /* do nothing */
303
303
  if(n == 0) {
304
- return ULONG2NUM(0);
304
+ return INT2NUM(0);
305
305
  }
306
306
 
307
307
  size_t sz = read_until_eof(b, Qnil, n);
308
- return ULONG2NUM(sz);
308
+ return SIZET2NUM(sz);
309
309
  }
310
310
 
311
311
  static VALUE Buffer_skip_all(VALUE self, VALUE sn)
@@ -473,7 +473,7 @@ static VALUE Buffer_write_to(VALUE self, VALUE io)
473
473
  {
474
474
  BUFFER(self, b);
475
475
  size_t sz = msgpack_buffer_flush_to_io(b, io, s_write, true);
476
- return ULONG2NUM(sz);
476
+ return SIZET2NUM(sz);
477
477
  }
478
478
 
479
479
  void MessagePack_Buffer_module_init(VALUE mMessagePack)
@@ -6,7 +6,7 @@ have_func("rb_enc_interned_str", "ruby.h") # Ruby 3.0+
6
6
  have_func("rb_hash_new_capa", "ruby.h") # Ruby 3.2+
7
7
 
8
8
  unless RUBY_PLATFORM.include? 'mswin'
9
- $CFLAGS << %[ -I.. -Wall -O3 -g -std=gnu99]
9
+ $CFLAGS << %[ -I.. -Wall -O3 #{RbConfig::CONFIG["debugflags"]} -std=gnu99]
10
10
  end
11
11
  #$CFLAGS << %[ -DDISABLE_RMEM]
12
12
  #$CFLAGS << %[ -DDISABLE_RMEM_REUSE_INTERNAL_FRAGMENT]
@@ -322,7 +322,7 @@ static VALUE Packer_write_to(VALUE self, VALUE io)
322
322
  {
323
323
  PACKER(self, pk);
324
324
  size_t sz = msgpack_buffer_flush_to_io(PACKER_BUFFER_(pk), io, s_write, true);
325
- return ULONG2NUM(sz);
325
+ return SIZET2NUM(sz);
326
326
  }
327
327
 
328
328
  //static VALUE Packer_append(VALUE self, VALUE string_or_buffer)
@@ -60,13 +60,16 @@ void msgpack_unpacker_static_destroy()
60
60
  #define HEAD_BYTE_REQUIRED 0xc1
61
61
 
62
62
  static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
63
+ msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
64
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
63
65
  #ifdef UNPACKER_STACK_RMEM
64
- return msgpack_rmem_alloc(&s_stack_rmem);
66
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
65
67
  /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
66
68
  #else
67
- /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_t));*/
68
- return xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_t));
69
+ /*uk->stack = calloc(MSGPACK_UNPACKER_STACK_CAPACITY, sizeof(msgpack_unpacker_stack_entry_t));*/
70
+ stack->data = xmalloc(MSGPACK_UNPACKER_STACK_CAPACITY * sizeof(msgpack_unpacker_stack_entry_t));
69
71
  #endif
72
+ return stack;
70
73
  }
71
74
 
72
75
  msgpack_unpacker_t* _msgpack_unpacker_new(void)
@@ -81,17 +84,17 @@ msgpack_unpacker_t* _msgpack_unpacker_new(void)
81
84
  uk->reading_raw = Qnil;
82
85
 
83
86
  uk->stack = _msgpack_unpacker_new_stack();
84
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
85
87
 
86
88
  return uk;
87
89
  }
88
90
 
89
91
  static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
90
92
  #ifdef UNPACKER_STACK_RMEM
91
- msgpack_rmem_free(&s_stack_rmem, stack);
93
+ msgpack_rmem_free(&s_stack_rmem, stack->data);
92
94
  #else
93
- xfree(stack);
95
+ xfree(stack->data);
94
96
  #endif
97
+ xfree(stack);
95
98
  }
96
99
 
97
100
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
@@ -100,18 +103,24 @@ void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
100
103
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
101
104
  }
102
105
 
106
+ void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
107
+ {
108
+ while (stack) {
109
+ msgpack_unpacker_stack_entry_t* s = stack->data;
110
+ msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
111
+ for(; s < send; s++) {
112
+ rb_gc_mark(s->object);
113
+ rb_gc_mark(s->key);
114
+ }
115
+ stack = stack->parent;
116
+ }
117
+ }
118
+
103
119
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
104
120
  {
105
121
  rb_gc_mark(uk->last_object);
106
122
  rb_gc_mark(uk->reading_raw);
107
-
108
- msgpack_unpacker_stack_t* s = uk->stack;
109
- msgpack_unpacker_stack_t* send = uk->stack + uk->stack_depth;
110
- for(; s < send; s++) {
111
- rb_gc_mark(s->object);
112
- rb_gc_mark(s->key);
113
- }
114
-
123
+ msgpack_unpacker_mark_stack(uk->stack);
115
124
  /* See MessagePack_Buffer_wrap */
116
125
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
117
126
  rb_gc_mark(uk->buffer_ref);
@@ -123,9 +132,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
123
132
 
124
133
  uk->head_byte = HEAD_BYTE_REQUIRED;
125
134
 
126
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack_depth);*/
127
- uk->stack_depth = 0;
128
-
135
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
136
+ uk->stack->depth = 0;
129
137
  uk->last_object = Qnil;
130
138
  uk->reading_raw = Qnil;
131
139
  uk->reading_raw_remaining = 0;
@@ -177,6 +185,9 @@ static inline int object_complete_symbol(msgpack_unpacker_t* uk, VALUE object)
177
185
  static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str)
178
186
  {
179
187
  if (uk->optimized_symbol_ext_type && ext_type == uk->symbol_ext_type) {
188
+ if (RB_UNLIKELY(NIL_P(str))) { // empty extension is returned as Qnil
189
+ return object_complete_symbol(uk, ID2SYM(rb_intern3("", 0, rb_utf8_encoding())));
190
+ }
180
191
  return object_complete_symbol(uk, rb_str_intern(str));
181
192
  }
182
193
 
@@ -198,37 +209,37 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
198
209
  }
199
210
 
200
211
  /* stack funcs */
201
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk)
212
+ static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
202
213
  {
203
- return &uk->stack[uk->stack_depth-1];
214
+ return &uk->stack->data[uk->stack->depth-1];
204
215
  }
205
216
 
206
217
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
207
218
  {
208
219
  reset_head_byte(uk);
209
220
 
210
- if(uk->stack_capacity - uk->stack_depth <= 0) {
221
+ if(uk->stack->capacity - uk->stack->depth <= 0) {
211
222
  return PRIMITIVE_STACK_TOO_DEEP;
212
223
  }
213
224
 
214
- msgpack_unpacker_stack_t* next = &uk->stack[uk->stack_depth];
225
+ msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
215
226
  next->count = count;
216
227
  next->type = type;
217
228
  next->object = object;
218
229
  next->key = Qnil;
219
230
 
220
- uk->stack_depth++;
231
+ uk->stack->depth++;
221
232
  return PRIMITIVE_CONTAINER_START;
222
233
  }
223
234
 
224
235
  static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
225
236
  {
226
- return --uk->stack_depth;
237
+ return --uk->stack->depth;
227
238
  }
228
239
 
229
240
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
230
241
  {
231
- return uk->stack_depth == 0;
242
+ return uk->stack->depth == 0;
232
243
  }
233
244
 
234
245
  #ifdef USE_CASE_RANGE
@@ -256,8 +267,8 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
256
267
 
257
268
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
258
269
  {
259
- if(uk->stack_depth > 0) {
260
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
270
+ if(uk->stack->depth > 0) {
271
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
261
272
  if(top->type == STACK_TYPE_MAP_KEY) {
262
273
  return true;
263
274
  }
@@ -311,20 +322,14 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
311
322
  reset_head_byte(uk);
312
323
  uk->reading_raw_remaining = 0;
313
324
 
314
- msgpack_unpacker_stack_t* stack = uk->stack;
315
- size_t stack_depth = uk->stack_depth;
316
- size_t stack_capacity = uk->stack_capacity;
317
-
318
- uk->stack = _msgpack_unpacker_new_stack();
319
- uk->stack_depth = 0;
320
- uk->stack_capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
325
+ msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
326
+ child_stack->parent = uk->stack;
327
+ uk->stack = child_stack;
321
328
 
322
329
  obj = rb_funcall(proc, s_call, 1, uk->buffer.owner);
323
330
 
324
- _msgpack_unpacker_free_stack(uk->stack);
325
- uk->stack = stack;
326
- uk->stack_depth = stack_depth;
327
- uk->stack_capacity = stack_capacity;
331
+ uk->stack = child_stack->parent;
332
+ _msgpack_unpacker_free_stack(child_stack);
328
333
 
329
334
  return object_complete(uk, obj);
330
335
  }
@@ -477,7 +482,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
477
482
  {
478
483
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
479
484
  uint32_t u32 = _msgpack_be32(cb->u32);
480
- return object_complete(uk, ULONG2NUM((unsigned long)u32));
485
+ return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
481
486
  }
482
487
 
483
488
  case 0xcf: // unsigned int 64
@@ -505,7 +510,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
505
510
  {
506
511
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
507
512
  int32_t i32 = _msgpack_be32(cb->i32);
508
- return object_complete(uk, LONG2NUM((long)i32));
513
+ return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
509
514
  }
510
515
 
511
516
  case 0xd3: // signed int 64
@@ -734,7 +739,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
734
739
 
735
740
  container_completed:
736
741
  {
737
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
742
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
738
743
  switch(top->type) {
739
744
  case STACK_TYPE_ARRAY:
740
745
  rb_ary_push(top->object, uk->last_object);
@@ -784,7 +789,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
784
789
 
785
790
  container_completed:
786
791
  {
787
- msgpack_unpacker_stack_t* top = _msgpack_unpacker_stack_top(uk);
792
+ msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
788
793
 
789
794
  /* this section optimized out */
790
795
  // TODO object_complete still creates objects which should be optimized out
@@ -27,6 +27,7 @@
27
27
 
28
28
  struct msgpack_unpacker_t;
29
29
  typedef struct msgpack_unpacker_t msgpack_unpacker_t;
30
+ typedef struct msgpack_unpacker_stack_t msgpack_unpacker_stack_t;
30
31
 
31
32
  enum stack_type_t {
32
33
  STACK_TYPE_ARRAY,
@@ -39,19 +40,22 @@ typedef struct {
39
40
  enum stack_type_t type;
40
41
  VALUE object;
41
42
  VALUE key;
42
- } msgpack_unpacker_stack_t;
43
+ } msgpack_unpacker_stack_entry_t;
44
+
45
+ struct msgpack_unpacker_stack_t {
46
+ size_t depth;
47
+ size_t capacity;
48
+ msgpack_unpacker_stack_entry_t *data;
49
+ msgpack_unpacker_stack_t *parent;
50
+ };
43
51
 
44
52
  #define MSGPACK_UNPACKER_STACK_SIZE (8+4+8+8) /* assumes size_t <= 64bit, enum <= 32bit, VALUE <= 64bit */
45
53
 
46
54
  struct msgpack_unpacker_t {
47
55
  msgpack_buffer_t buffer;
48
-
56
+ msgpack_unpacker_stack_t *stack;
49
57
  unsigned int head_byte;
50
58
 
51
- msgpack_unpacker_stack_t* stack;
52
- size_t stack_depth;
53
- size_t stack_capacity;
54
-
55
59
  VALUE last_object;
56
60
 
57
61
  VALUE reading_raw;
@@ -209,7 +209,7 @@ static VALUE Unpacker_read_array_header(VALUE self)
209
209
  raise_unpacker_error(r);
210
210
  }
211
211
 
212
- return ULONG2NUM(size);
212
+ return ULONG2NUM(size); // long at least 32 bits
213
213
  }
214
214
 
215
215
  static VALUE Unpacker_read_map_header(VALUE self)
@@ -222,7 +222,7 @@ static VALUE Unpacker_read_map_header(VALUE self)
222
222
  raise_unpacker_error((int)r);
223
223
  }
224
224
 
225
- return ULONG2NUM(size);
225
+ return ULONG2NUM(size); // long at least 32 bits
226
226
  }
227
227
 
228
228
 
@@ -1,5 +1,5 @@
1
1
  module MessagePack
2
- VERSION = "1.5.3"
2
+ VERSION = "1.5.6"
3
3
  # Note for maintainers:
4
4
  # Don't miss building/releasing the JRuby version (rake buld:java)
5
5
  # See "How to build -java rubygems" in README for more details.
data/msgpack.gemspec CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
27
27
  s.add_development_dependency 'rspec', ['~> 3.3']
28
28
  s.add_development_dependency 'yard'
29
29
  s.add_development_dependency 'json'
30
+ s.add_development_dependency 'benchmark-ips', ['~> 2.10.0']
30
31
  end
data/spec/factory_spec.rb CHANGED
@@ -474,6 +474,10 @@ describe MessagePack::Factory do
474
474
  expect(roundtrip(:symbol)).to be :symbol
475
475
  end
476
476
 
477
+ it 'works with empty symbol' do
478
+ expect(roundtrip(:"")).to be :""
479
+ end
480
+
477
481
  it 'preserves encoding for ASCII symbols' do
478
482
  expect(:symbol.encoding).to be Encoding::US_ASCII
479
483
  expect(roundtrip(:symbol)).to be :symbol
@@ -583,6 +587,30 @@ describe MessagePack::Factory do
583
587
  GC.stress = false
584
588
  end
585
589
  end
590
+
591
+ it 'does not crash in recursive extensions' do
592
+ my_hash_type = Class.new(Hash)
593
+ factory = MessagePack::Factory.new
594
+ factory.register_type(7,
595
+ my_hash_type,
596
+ packer: ->(value, packer) do
597
+ packer.write(value.to_h)
598
+ end,
599
+ unpacker: ->(unpacker) { my_hash_type.new(unpacker.read) },
600
+ recursive: true,
601
+ )
602
+
603
+ payload = factory.dump(
604
+ [my_hash_type.new]
605
+ )
606
+
607
+ begin
608
+ GC.stress = true
609
+ factory.load(payload)
610
+ ensure
611
+ GC.stress = false
612
+ end
613
+ end
586
614
  end
587
615
 
588
616
  describe 'DefaultFactory' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msgpack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-07-01 00:00:00.000000000 Z
13
+ date: 2022-08-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -96,6 +96,20 @@ dependencies:
96
96
  - - ">="
97
97
  - !ruby/object:Gem::Version
98
98
  version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: benchmark-ips
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: 2.10.0
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: 2.10.0
99
113
  description: MessagePack is a binary-based efficient object serialization library.
100
114
  It enables to exchange structured objects between many languages like JSON. But
101
115
  unlike JSON, it is very fast and small.
@@ -117,16 +131,7 @@ files:
117
131
  - README.md
118
132
  - Rakefile
119
133
  - appveyor.yml
120
- - bench/pack.rb
121
- - bench/pack_log.rb
122
- - bench/pack_log_long.rb
123
- - bench/pack_symbols.rb
124
- - bench/run.sh
125
- - bench/run_long.sh
126
- - bench/run_symbols.sh
127
- - bench/unpack.rb
128
- - bench/unpack_log.rb
129
- - bench/unpack_log_long.rb
134
+ - bench/bench.rb
130
135
  - doclib/msgpack.rb
131
136
  - doclib/msgpack/buffer.rb
132
137
  - doclib/msgpack/core_ext.rb
data/bench/pack.rb DELETED
@@ -1,23 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data = { 'hello' => 'world', 'nested' => ['structure', {value: 42}] }
5
- data_sym = { hello: 'world', nested: ['structure', {value: 42}] }
6
-
7
- data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
8
-
9
- Viiite.bench do |b|
10
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
11
- b.report(:strings) do
12
- runs.times do
13
- MessagePack.pack(data)
14
- end
15
- end
16
-
17
- b.report(:symbols) do
18
- runs.times do
19
- MessagePack.pack(data_sym)
20
- end
21
- end
22
- end
23
- end
data/bench/pack_log.rb DELETED
@@ -1,33 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data_plain = { 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' }
5
- data_structure = {
6
- 'remote_host' => '127.0.0.1',
7
- 'remote_user' => '-',
8
- 'date' => '10/Oct/2000:13:55:36 -0700',
9
- 'request' => 'GET /apache_pb.gif HTTP/1.0',
10
- 'method' => 'GET',
11
- 'path' => '/apache_pb.gif',
12
- 'protocol' => 'HTTP/1.0',
13
- 'status' => 200,
14
- 'bytes' => 2326,
15
- 'referer' => 'http://www.example.com/start.html',
16
- 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
17
- }
18
-
19
- Viiite.bench do |b|
20
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
21
- b.report(:plain) do
22
- runs.times do
23
- MessagePack.pack(data_plain)
24
- end
25
- end
26
-
27
- b.report(:structure) do
28
- runs.times do
29
- MessagePack.pack(data_structure)
30
- end
31
- end
32
- end
33
- end
@@ -1,65 +0,0 @@
1
- # viiite report --regroup bench,threads bench/pack_log_long.rb
2
-
3
- require 'viiite'
4
- require 'msgpack'
5
-
6
- data_plain = { 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' }
7
- data_structure = {
8
- 'remote_host' => '127.0.0.1',
9
- 'remote_user' => '-',
10
- 'date' => '10/Oct/2000:13:55:36 -0700',
11
- 'request' => 'GET /apache_pb.gif HTTP/1.0',
12
- 'method' => 'GET',
13
- 'path' => '/apache_pb.gif',
14
- 'protocol' => 'HTTP/1.0',
15
- 'status' => 200,
16
- 'bytes' => 2326,
17
- 'referer' => 'http://www.example.com/start.html',
18
- 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
19
- }
20
-
21
- seconds = 3600 # 1 hour
22
-
23
- Viiite.bench do |b|
24
- b.range_over([1, 2, 4, 8, 16], :threads) do |threads|
25
- b.report(:plain) do
26
- ths = []
27
- end_at = Time.now + seconds
28
- threads.times do
29
- t = Thread.new do
30
- packs = 0
31
- while Time.now < end_at
32
- 10000.times do
33
- MessagePack.pack(data_plain)
34
- end
35
- packs += 10000
36
- end
37
- packs
38
- end
39
- ths.push t
40
- end
41
- sum = ths.reduce(0){|r,t| r + t.value }
42
- puts "MessagePack.pack, plain, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
43
- end
44
-
45
- b.report(:structure) do
46
- ths = []
47
- end_at = Time.now + seconds
48
- threads.times do
49
- t = Thread.new do
50
- packs = 0
51
- while Time.now < end_at
52
- 10000.times do
53
- MessagePack.pack(data_structure)
54
- end
55
- packs += 10000
56
- end
57
- packs
58
- end
59
- ths.push t
60
- end
61
- sum = ths.reduce(0){|r,t| r + t.value }
62
- puts "MessagePack.pack, structured, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
63
- end
64
- end
65
- end
@@ -1,28 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data = :symbol
5
-
6
- Viiite.bench do |b|
7
- b.variation_point :branch, `git rev-parse --abbrev-ref HEAD`
8
-
9
- b.range_over([:symbol, :none], :reg_type) do |reg_type|
10
- packer = MessagePack::Packer.new
11
- packer.register_type(0x00, Symbol, :to_msgpack_ext) if reg_type == :symbol
12
-
13
- b.range_over([100_000, 1_000_000, 10_000_000], :count) do |count|
14
- packer.clear
15
- b.report(:multi_run) do
16
- count.times do
17
- packer.pack(data)
18
- end
19
- end
20
-
21
- packer.clear
22
- items_data = [].fill(data, 0, count)
23
- b.report(:large_run) do
24
- packer.pack(items_data)
25
- end
26
- end
27
- end
28
- end
data/bench/run.sh DELETED
@@ -1,14 +0,0 @@
1
- #!/bin/sh
2
-
3
- # prerequisites
4
- # $ rbenv shell 2.2.1 (or jruby-x.x.x or ...)
5
- # $ rake install
6
-
7
- echo "pack"
8
- viiite report --regroup bench,runs bench/pack.rb
9
- echo "unpack"
10
- viiite report --regroup bench,runs bench/unpack.rb
11
- echo "pack log"
12
- viiite report --regroup bench,runs bench/pack_log.rb
13
- echo "unpack log"
14
- viiite report --regroup bench,runs bench/unpack_log.rb
data/bench/run_long.sh DELETED
@@ -1,35 +0,0 @@
1
- #!/bin/sh
2
-
3
- # prerequisites
4
- # $ sudo apt-get install sysstat
5
- # $ rbenv shell 2.2.1 (or jruby-x.x.x or ...)
6
- # $ rake install
7
-
8
- # 60 * 600 : 60*60 * 5[threads] * 2[bench]
9
-
10
- ruby -v
11
-
12
- echo "pack log long"
13
- viiite report --regroup bench,threads bench/pack_log_long.rb &
14
- sar -o pack_log_long.sar -r 60 600 > /dev/null 2>&1 &
15
-
16
- declare -i i=0
17
- while [ $i -lt 600 ]; do
18
- ps auxww | grep ruby | grep -v grep | awk '{print $5,$6;}' >> pack_log_long.mem.txt
19
- i=i+1
20
- sleep 60
21
- done
22
-
23
- sleep 120 # cool down
24
-
25
- echo "unpack log long"
26
- viiite report --regroup bench,threads bench/unpack_log_long.rb &
27
- sar -o unpack_log_long.sar -r 60 600 > /dev/null 2>&1 &
28
-
29
- i=0
30
- while [ $i -lt 600 ]; do
31
- ps auxww | grep ruby | grep -v grep | awk '{print $5,$6;}' >> pack_log_long.mem.txt
32
- i=i+1
33
- sleep 60
34
- done
35
-
data/bench/run_symbols.sh DELETED
@@ -1,26 +0,0 @@
1
- #!/bin/sh
2
-
3
- # so master and this branch have the benchmark file in any case
4
- cp bench/pack_symbols.rb bench/pack_symbols_tmp.rb
5
-
6
- benchmark=""
7
- current_branch=`git rev-parse --abbrev-ref HEAD`
8
-
9
- for branch in master $current_branch; do
10
- echo "Testing branch $branch"
11
- git checkout $branch
12
-
13
- echo "Installing gem..."
14
- rake install
15
-
16
- echo "Running benchmark..."
17
- if [ "$benchmark" ]; then
18
- benchmark+=$'\n'
19
- fi
20
- benchmark+=$(viiite run bench/pack_symbols_tmp.rb)
21
- echo
22
- done
23
-
24
- rm bench/pack_symbols_tmp.rb
25
-
26
- echo "$benchmark" | viiite report --regroup bench,reg_type,count,branch
data/bench/unpack.rb DELETED
@@ -1,21 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data = MessagePack.pack(:hello => 'world', :nested => ['structure', {:value => 42}])
5
-
6
- Viiite.bench do |b|
7
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
8
- b.report(:strings) do
9
- runs.times do
10
- MessagePack.unpack(data)
11
- end
12
- end
13
-
14
- b.report(:symbols) do
15
- options = {:symbolize_keys => true}
16
- runs.times do
17
- MessagePack.unpack(data, options)
18
- end
19
- end
20
- end
21
- end
data/bench/unpack_log.rb DELETED
@@ -1,34 +0,0 @@
1
- require 'viiite'
2
- require 'msgpack'
3
-
4
- data_plain = MessagePack.pack({ 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"' })
5
-
6
- data_structure = MessagePack.pack({
7
- 'remote_host' => '127.0.0.1',
8
- 'remote_user' => '-',
9
- 'date' => '10/Oct/2000:13:55:36 -0700',
10
- 'request' => 'GET /apache_pb.gif HTTP/1.0',
11
- 'method' => 'GET',
12
- 'path' => '/apache_pb.gif',
13
- 'protocol' => 'HTTP/1.0',
14
- 'status' => 200,
15
- 'bytes' => 2326,
16
- 'referer' => 'http://www.example.com/start.html',
17
- 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
18
- })
19
-
20
- Viiite.bench do |b|
21
- b.range_over([10_000, 100_000, 1000_000], :runs) do |runs|
22
- b.report(:plain) do
23
- runs.times do
24
- MessagePack.unpack(data_plain)
25
- end
26
- end
27
-
28
- b.report(:structure) do
29
- runs.times do
30
- MessagePack.unpack(data_structure)
31
- end
32
- end
33
- end
34
- end
@@ -1,67 +0,0 @@
1
- # viiite report --regroup bench,threads bench/pack_log_long.rb
2
-
3
- require 'viiite'
4
- require 'msgpack'
5
-
6
- data_plain = MessagePack.pack({
7
- 'message' => '127.0.0.1 - - [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"'
8
- })
9
- data_structure = MessagePack.pack({
10
- 'remote_host' => '127.0.0.1',
11
- 'remote_user' => '-',
12
- 'date' => '10/Oct/2000:13:55:36 -0700',
13
- 'request' => 'GET /apache_pb.gif HTTP/1.0',
14
- 'method' => 'GET',
15
- 'path' => '/apache_pb.gif',
16
- 'protocol' => 'HTTP/1.0',
17
- 'status' => 200,
18
- 'bytes' => 2326,
19
- 'referer' => 'http://www.example.com/start.html',
20
- 'agent' => 'Mozilla/4.08 [en] (Win98; I ;Nav)',
21
- })
22
-
23
- seconds = 3600 # 1 hour
24
-
25
- Viiite.bench do |b|
26
- b.range_over([1, 2, 4, 8, 16], :threads) do |threads|
27
- b.report(:plain) do
28
- ths = []
29
- end_at = Time.now + seconds
30
- threads.times do
31
- t = Thread.new do
32
- packs = 0
33
- while Time.now < end_at
34
- 10000.times do
35
- MessagePack.unpack(data_plain)
36
- end
37
- packs += 10000
38
- end
39
- packs
40
- end
41
- ths.push t
42
- end
43
- sum = ths.reduce(0){|r,t| r + t.value }
44
- puts "MessagePack.unpack, plain, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
45
- end
46
-
47
- b.report(:structure) do
48
- ths = []
49
- end_at = Time.now + seconds
50
- threads.times do
51
- t = Thread.new do
52
- packs = 0
53
- while Time.now < end_at
54
- 10000.times do
55
- MessagePack.unpack(data_structure)
56
- end
57
- packs += 10000
58
- end
59
- packs
60
- end
61
- ths.push t
62
- end
63
- sum = ths.reduce(0){|r,t| r + t.value }
64
- puts "MessagePack.unpack, structured, #{threads} threads: #{sum} times, #{sum / seconds} times/second."
65
- end
66
- end
67
- end