msgpack 1.7.2 → 1.8.0

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.
@@ -20,13 +20,49 @@
20
20
  #include "rmem.h"
21
21
  #include "extension_value_class.h"
22
22
  #include <assert.h>
23
+ #include <limits.h>
23
24
 
24
25
  #if !defined(HAVE_RB_PROC_CALL_WITH_BLOCK)
25
26
  #define rb_proc_call_with_block(recv, argc, argv, block) rb_funcallv(recv, rb_intern("call"), argc, argv)
26
27
  #endif
27
28
 
29
+ #ifndef HAVE_RB_GC_MARK_LOCATIONS
30
+ // For TruffleRuby
31
+ void rb_gc_mark_locations(const VALUE *start, const VALUE *end)
32
+ {
33
+ VALUE *value = start;
34
+
35
+ while (value < end) {
36
+ rb_gc_mark(*value);
37
+ value++;
38
+ }
39
+ }
40
+ #endif
41
+
42
+ struct protected_proc_call_args {
43
+ VALUE proc;
44
+ int argc;
45
+ VALUE *argv;
46
+ };
47
+
48
+ static VALUE protected_proc_call_safe(VALUE _args) {
49
+ struct protected_proc_call_args *args = (struct protected_proc_call_args *)_args;
50
+
51
+ return rb_proc_call_with_block(args->proc, args->argc, args->argv, Qnil);
52
+ }
53
+
54
+ static VALUE protected_proc_call(VALUE proc, int argc, VALUE *argv, int *raised) {
55
+ struct protected_proc_call_args args = {
56
+ .proc = proc,
57
+ .argc = argc,
58
+ .argv = argv,
59
+ };
60
+ return rb_protect(protected_proc_call_safe, (VALUE)&args, raised);
61
+ }
62
+
28
63
  static int RAW_TYPE_STRING = 256;
29
64
  static int RAW_TYPE_BINARY = 257;
65
+ static int16_t INITIAL_BUFFER_CAPACITY_MAX = SHRT_MAX;
30
66
 
31
67
  static msgpack_rmem_t s_stack_rmem;
32
68
 
@@ -37,6 +73,11 @@ static inline VALUE rb_hash_new_capa(long capa)
37
73
  }
38
74
  #endif
39
75
 
76
+ static inline int16_t initial_buffer_size(long size)
77
+ {
78
+ return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
79
+ }
80
+
40
81
  void msgpack_unpacker_static_init(void)
41
82
  {
42
83
  assert(sizeof(msgpack_unpacker_stack_entry_t) * MSGPACK_UNPACKER_STACK_CAPACITY <= MSGPACK_RMEM_PAGE_SIZE);
@@ -51,14 +92,29 @@ void msgpack_unpacker_static_destroy(void)
51
92
 
52
93
  #define HEAD_BYTE_REQUIRED 0xc1
53
94
 
54
- static inline msgpack_unpacker_stack_t* _msgpack_unpacker_new_stack(void) {
55
- msgpack_unpacker_stack_t *stack = ZALLOC(msgpack_unpacker_stack_t);
56
- stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
57
- stack->data = msgpack_rmem_alloc(&s_stack_rmem);
58
- /*memset(uk->stack, 0, MSGPACK_UNPACKER_STACK_CAPACITY);*/
59
- return stack;
95
+ static inline bool _msgpack_unpacker_stack_init(msgpack_unpacker_stack_t *stack) {
96
+ if (!stack->data) {
97
+ stack->capacity = MSGPACK_UNPACKER_STACK_CAPACITY;
98
+ stack->data = msgpack_rmem_alloc(&s_stack_rmem);
99
+ stack->depth = 0;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+
105
+ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
106
+ if (stack->data) {
107
+ if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
108
+ rb_bug("Failed to free an rmem pointer, memory leak?");
109
+ }
110
+ stack->data = NULL;
111
+ stack->depth = 0;
112
+ }
60
113
  }
61
114
 
115
+ #define STACK_INIT(uk) bool stack_allocated = _msgpack_unpacker_stack_init(&uk->stack);
116
+ #define STACK_FREE(uk) if (stack_allocated) { _msgpack_unpacker_free_stack(&uk->stack); }
117
+
62
118
  void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
63
119
  {
64
120
  msgpack_buffer_init(UNPACKER_BUFFER_(uk));
@@ -67,41 +123,38 @@ void _msgpack_unpacker_init(msgpack_unpacker_t* uk)
67
123
 
68
124
  uk->last_object = Qnil;
69
125
  uk->reading_raw = Qnil;
70
-
71
- uk->stack = _msgpack_unpacker_new_stack();
72
- }
73
-
74
- static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack) {
75
- if (!msgpack_rmem_free(&s_stack_rmem, stack->data)) {
76
- rb_bug("Failed to free an rmem pointer, memory leak?");
77
- }
78
- xfree(stack);
79
126
  }
80
127
 
81
128
  void _msgpack_unpacker_destroy(msgpack_unpacker_t* uk)
82
129
  {
83
- _msgpack_unpacker_free_stack(uk->stack);
130
+ _msgpack_unpacker_free_stack(&uk->stack);
84
131
  msgpack_buffer_destroy(UNPACKER_BUFFER_(uk));
85
132
  }
86
133
 
87
134
  void msgpack_unpacker_mark_stack(msgpack_unpacker_stack_t* stack)
88
135
  {
89
- while (stack) {
136
+ if (stack->data) {
90
137
  msgpack_unpacker_stack_entry_t* s = stack->data;
91
138
  msgpack_unpacker_stack_entry_t* send = stack->data + stack->depth;
92
139
  for(; s < send; s++) {
93
140
  rb_gc_mark(s->object);
94
141
  rb_gc_mark(s->key);
95
142
  }
96
- stack = stack->parent;
97
143
  }
98
144
  }
99
145
 
146
+ void msgpack_unpacker_mark_key_cache(msgpack_key_cache_t *cache)
147
+ {
148
+ const VALUE *entries = &cache->entries[0];
149
+ rb_gc_mark_locations(entries, entries + cache->length);
150
+ }
151
+
100
152
  void msgpack_unpacker_mark(msgpack_unpacker_t* uk)
101
153
  {
102
154
  rb_gc_mark(uk->last_object);
103
155
  rb_gc_mark(uk->reading_raw);
104
- msgpack_unpacker_mark_stack(uk->stack);
156
+ msgpack_unpacker_mark_stack(&uk->stack);
157
+ msgpack_unpacker_mark_key_cache(&uk->key_cache);
105
158
  /* See MessagePack_Buffer_wrap */
106
159
  /* msgpack_buffer_mark(UNPACKER_BUFFER_(uk)); */
107
160
  rb_gc_mark(uk->buffer_ref);
@@ -114,8 +167,8 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
114
167
 
115
168
  uk->head_byte = HEAD_BYTE_REQUIRED;
116
169
 
117
- /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack->depth);*/
118
- uk->stack->depth = 0;
170
+ /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack.depth);*/
171
+ uk->stack.depth = 0;
119
172
  uk->last_object = Qnil;
120
173
  uk->reading_raw = Qnil;
121
174
  uk->reading_raw_remaining = 0;
@@ -179,7 +232,12 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
179
232
  if(proc != Qnil) {
180
233
  VALUE obj;
181
234
  VALUE arg = (str == Qnil ? rb_str_buf_new(0) : str);
182
- obj = rb_proc_call_with_block(proc, 1, &arg, Qnil);
235
+ int raised;
236
+ obj = protected_proc_call(proc, 1, &arg, &raised);
237
+ if (raised) {
238
+ uk->last_object = rb_errinfo();
239
+ return PRIMITIVE_RECURSIVE_RAISED;
240
+ }
183
241
  return object_complete(uk, obj);
184
242
  }
185
243
 
@@ -194,35 +252,35 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU
194
252
  /* stack funcs */
195
253
  static inline msgpack_unpacker_stack_entry_t* _msgpack_unpacker_stack_entry_top(msgpack_unpacker_t* uk)
196
254
  {
197
- return &uk->stack->data[uk->stack->depth-1];
255
+ return &uk->stack.data[uk->stack.depth-1];
198
256
  }
199
257
 
200
258
  static inline int _msgpack_unpacker_stack_push(msgpack_unpacker_t* uk, enum stack_type_t type, size_t count, VALUE object)
201
259
  {
202
260
  reset_head_byte(uk);
203
261
 
204
- if(uk->stack->capacity - uk->stack->depth <= 0) {
262
+ if(uk->stack.capacity - uk->stack.depth <= 0) {
205
263
  return PRIMITIVE_STACK_TOO_DEEP;
206
264
  }
207
265
 
208
- msgpack_unpacker_stack_entry_t* next = &uk->stack->data[uk->stack->depth];
266
+ msgpack_unpacker_stack_entry_t* next = &uk->stack.data[uk->stack.depth];
209
267
  next->count = count;
210
268
  next->type = type;
211
269
  next->object = object;
212
270
  next->key = Qnil;
213
271
 
214
- uk->stack->depth++;
272
+ uk->stack.depth++;
215
273
  return PRIMITIVE_CONTAINER_START;
216
274
  }
217
275
 
218
- static inline VALUE msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
276
+ static inline size_t msgpack_unpacker_stack_pop(msgpack_unpacker_t* uk)
219
277
  {
220
- return --uk->stack->depth;
278
+ return --uk->stack.depth;
221
279
  }
222
280
 
223
281
  static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
224
282
  {
225
- return uk->stack->depth == 0;
283
+ return uk->stack.depth == 0;
226
284
  }
227
285
 
228
286
  #ifdef USE_CASE_RANGE
@@ -241,16 +299,29 @@ static inline bool msgpack_unpacker_stack_is_empty(msgpack_unpacker_t* uk)
241
299
 
242
300
  #endif
243
301
 
302
+ union msgpack_buffer_cast_block_t {
303
+ char buffer[8];
304
+ uint8_t u8;
305
+ uint16_t u16;
306
+ uint32_t u32;
307
+ uint64_t u64;
308
+ int8_t i8;
309
+ int16_t i16;
310
+ int32_t i32;
311
+ int64_t i64;
312
+ float f;
313
+ double d;
314
+ };
244
315
 
245
316
  #define READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, n) \
246
- union msgpack_buffer_cast_block_t* cb = msgpack_buffer_read_cast_block(UNPACKER_BUFFER_(uk), n); \
247
- if(cb == NULL) { \
317
+ union msgpack_buffer_cast_block_t cb; \
318
+ if (!msgpack_buffer_read_all(UNPACKER_BUFFER_(uk), (char *)&cb.buffer, n)) { \
248
319
  return PRIMITIVE_EOF; \
249
320
  }
250
321
 
251
322
  static inline bool is_reading_map_key(msgpack_unpacker_t* uk)
252
323
  {
253
- if(uk->stack->depth > 0) {
324
+ if(uk->stack.depth > 0) {
254
325
  msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
255
326
  if(top->type == STACK_TYPE_MAP_KEY) {
256
327
  return true;
@@ -305,14 +376,15 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
305
376
  reset_head_byte(uk);
306
377
  uk->reading_raw_remaining = 0;
307
378
 
308
- msgpack_unpacker_stack_t* child_stack = _msgpack_unpacker_new_stack();
309
- child_stack->parent = uk->stack;
310
- uk->stack = child_stack;
311
-
312
- obj = rb_proc_call_with_block(proc, 1, &uk->self, Qnil);
379
+ _msgpack_unpacker_stack_push(uk, STACK_TYPE_RECURSIVE, 1, Qnil);
380
+ int raised;
381
+ obj = protected_proc_call(proc, 1, &uk->self, &raised);
382
+ msgpack_unpacker_stack_pop(uk);
313
383
 
314
- uk->stack = child_stack->parent;
315
- _msgpack_unpacker_free_stack(child_stack);
384
+ if (raised) {
385
+ uk->last_object = rb_errinfo();
386
+ return PRIMITIVE_RECURSIVE_RAISED;
387
+ }
316
388
 
317
389
  return object_complete(uk, obj);
318
390
  }
@@ -322,15 +394,32 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
322
394
  size_t length = uk->reading_raw_remaining;
323
395
  if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) {
324
396
  int ret;
325
- if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type) || (uk->symbolize_keys && is_reading_map_key(uk))) {
397
+ if ((uk->optimized_symbol_ext_type && uk->symbol_ext_type == raw_type)) {
326
398
  VALUE symbol = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, raw_type != RAW_TYPE_BINARY);
327
399
  ret = object_complete_symbol(uk, symbol);
400
+ } else if (is_reading_map_key(uk) && raw_type == RAW_TYPE_STRING) {
401
+ /* don't use zerocopy for hash keys but get a frozen string directly
402
+ * because rb_hash_aset freezes keys and it causes copying */
403
+ VALUE key;
404
+ if (uk->symbolize_keys) {
405
+ if (uk->use_key_cache) {
406
+ key = msgpack_buffer_read_top_as_interned_symbol(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
407
+ } else {
408
+ key = msgpack_buffer_read_top_as_symbol(UNPACKER_BUFFER_(uk), length, true);
409
+ }
410
+ ret = object_complete_symbol(uk, key);
411
+ } else {
412
+ if (uk->use_key_cache) {
413
+ key = msgpack_buffer_read_top_as_interned_string(UNPACKER_BUFFER_(uk), &uk->key_cache, length);
414
+ } else {
415
+ key = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, true, true);
416
+ }
417
+
418
+ ret = object_complete(uk, key);
419
+ }
328
420
  } else {
329
421
  bool will_freeze = uk->freeze;
330
422
  if(raw_type == RAW_TYPE_STRING || raw_type == RAW_TYPE_BINARY) {
331
- /* don't use zerocopy for hash keys but get a frozen string directly
332
- * because rb_hash_aset freezes keys and it causes copying */
333
- will_freeze = will_freeze || is_reading_map_key(uk);
334
423
  VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze, raw_type == RAW_TYPE_STRING);
335
424
  ret = object_complete(uk, string);
336
425
  } else {
@@ -375,14 +464,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
375
464
  if(count == 0) {
376
465
  return object_complete(uk, rb_ary_new());
377
466
  }
378
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
467
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
379
468
 
380
469
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
381
470
  int count = b & 0x0f;
382
471
  if(count == 0) {
383
472
  return object_complete(uk, rb_hash_new());
384
473
  }
385
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
474
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
386
475
 
387
476
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
388
477
  switch(b) {
@@ -400,8 +489,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
400
489
  case 0xc7: // ext 8
401
490
  {
402
491
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
403
- uint8_t length = cb->u8;
404
- int ext_type = (signed char) cb->buffer[1];
492
+ uint8_t length = cb.u8;
493
+ int ext_type = (signed char) cb.buffer[1];
405
494
  if(length == 0) {
406
495
  return object_complete_ext(uk, ext_type, Qnil);
407
496
  }
@@ -412,8 +501,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
412
501
  case 0xc8: // ext 16
413
502
  {
414
503
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 3);
415
- uint16_t length = _msgpack_be16(cb->u16);
416
- int ext_type = (signed char) cb->buffer[2];
504
+ uint16_t length = _msgpack_be16(cb.u16);
505
+ int ext_type = (signed char) cb.buffer[2];
417
506
  if(length == 0) {
418
507
  return object_complete_ext(uk, ext_type, Qnil);
419
508
  }
@@ -424,8 +513,8 @@ static int read_primitive(msgpack_unpacker_t* uk)
424
513
  case 0xc9: // ext 32
425
514
  {
426
515
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 5);
427
- uint32_t length = _msgpack_be32(cb->u32);
428
- int ext_type = (signed char) cb->buffer[4];
516
+ uint32_t length = _msgpack_be32(cb.u32);
517
+ int ext_type = (signed char) cb.buffer[4];
429
518
  if(length == 0) {
430
519
  return object_complete_ext(uk, ext_type, Qnil);
431
520
  }
@@ -436,77 +525,77 @@ static int read_primitive(msgpack_unpacker_t* uk)
436
525
  case 0xca: // float
437
526
  {
438
527
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
439
- cb->u32 = _msgpack_be_float(cb->u32);
440
- return object_complete(uk, rb_float_new(cb->f));
528
+ cb.u32 = _msgpack_be_float(cb.u32);
529
+ return object_complete(uk, rb_float_new(cb.f));
441
530
  }
442
531
 
443
532
  case 0xcb: // double
444
533
  {
445
534
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
446
- cb->u64 = _msgpack_be_double(cb->u64);
447
- return object_complete(uk, rb_float_new(cb->d));
535
+ cb.u64 = _msgpack_be_double(cb.u64);
536
+ return object_complete(uk, rb_float_new(cb.d));
448
537
  }
449
538
 
450
539
  case 0xcc: // unsigned int 8
451
540
  {
452
541
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
453
- uint8_t u8 = cb->u8;
542
+ uint8_t u8 = cb.u8;
454
543
  return object_complete(uk, INT2NUM((int)u8));
455
544
  }
456
545
 
457
546
  case 0xcd: // unsigned int 16
458
547
  {
459
548
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
460
- uint16_t u16 = _msgpack_be16(cb->u16);
549
+ uint16_t u16 = _msgpack_be16(cb.u16);
461
550
  return object_complete(uk, INT2NUM((int)u16));
462
551
  }
463
552
 
464
553
  case 0xce: // unsigned int 32
465
554
  {
466
555
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
467
- uint32_t u32 = _msgpack_be32(cb->u32);
556
+ uint32_t u32 = _msgpack_be32(cb.u32);
468
557
  return object_complete(uk, ULONG2NUM(u32)); // long at least 32 bits
469
558
  }
470
559
 
471
560
  case 0xcf: // unsigned int 64
472
561
  {
473
562
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
474
- uint64_t u64 = _msgpack_be64(cb->u64);
563
+ uint64_t u64 = _msgpack_be64(cb.u64);
475
564
  return object_complete(uk, rb_ull2inum(u64));
476
565
  }
477
566
 
478
567
  case 0xd0: // signed int 8
479
568
  {
480
569
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
481
- int8_t i8 = cb->i8;
570
+ int8_t i8 = cb.i8;
482
571
  return object_complete(uk, INT2NUM((int)i8));
483
572
  }
484
573
 
485
574
  case 0xd1: // signed int 16
486
575
  {
487
576
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
488
- int16_t i16 = _msgpack_be16(cb->i16);
577
+ int16_t i16 = _msgpack_be16(cb.i16);
489
578
  return object_complete(uk, INT2NUM((int)i16));
490
579
  }
491
580
 
492
581
  case 0xd2: // signed int 32
493
582
  {
494
583
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
495
- int32_t i32 = _msgpack_be32(cb->i32);
584
+ int32_t i32 = _msgpack_be32(cb.i32);
496
585
  return object_complete(uk, LONG2NUM(i32)); // long at least 32 bits
497
586
  }
498
587
 
499
588
  case 0xd3: // signed int 64
500
589
  {
501
590
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 8);
502
- int64_t i64 = _msgpack_be64(cb->i64);
591
+ int64_t i64 = _msgpack_be64(cb.i64);
503
592
  return object_complete(uk, rb_ll2inum(i64));
504
593
  }
505
594
 
506
595
  case 0xd4: // fixext 1
507
596
  {
508
597
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
509
- int ext_type = cb->i8;
598
+ int ext_type = cb.i8;
510
599
  uk->reading_raw_remaining = 1;
511
600
  return read_raw_body_begin(uk, ext_type);
512
601
  }
@@ -514,7 +603,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
514
603
  case 0xd5: // fixext 2
515
604
  {
516
605
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
517
- int ext_type = cb->i8;
606
+ int ext_type = cb.i8;
518
607
  uk->reading_raw_remaining = 2;
519
608
  return read_raw_body_begin(uk, ext_type);
520
609
  }
@@ -522,7 +611,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
522
611
  case 0xd6: // fixext 4
523
612
  {
524
613
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
525
- int ext_type = cb->i8;
614
+ int ext_type = cb.i8;
526
615
  uk->reading_raw_remaining = 4;
527
616
  return read_raw_body_begin(uk, ext_type);
528
617
  }
@@ -530,7 +619,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
530
619
  case 0xd7: // fixext 8
531
620
  {
532
621
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
533
- int ext_type = cb->i8;
622
+ int ext_type = cb.i8;
534
623
  uk->reading_raw_remaining = 8;
535
624
  return read_raw_body_begin(uk, ext_type);
536
625
  }
@@ -538,7 +627,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
538
627
  case 0xd8: // fixext 16
539
628
  {
540
629
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
541
- int ext_type = cb->i8;
630
+ int ext_type = cb.i8;
542
631
  uk->reading_raw_remaining = 16;
543
632
  return read_raw_body_begin(uk, ext_type);
544
633
  }
@@ -547,7 +636,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
547
636
  case 0xd9: // raw 8 / str 8
548
637
  {
549
638
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
550
- uint8_t count = cb->u8;
639
+ uint8_t count = cb.u8;
551
640
  /* read_raw_body_begin sets uk->reading_raw */
552
641
  uk->reading_raw_remaining = count;
553
642
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -556,7 +645,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
556
645
  case 0xda: // raw 16 / str 16
557
646
  {
558
647
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
559
- uint16_t count = _msgpack_be16(cb->u16);
648
+ uint16_t count = _msgpack_be16(cb.u16);
560
649
  /* read_raw_body_begin sets uk->reading_raw */
561
650
  uk->reading_raw_remaining = count;
562
651
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -565,7 +654,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
565
654
  case 0xdb: // raw 32 / str 32
566
655
  {
567
656
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
568
- uint32_t count = _msgpack_be32(cb->u32);
657
+ uint32_t count = _msgpack_be32(cb.u32);
569
658
  /* read_raw_body_begin sets uk->reading_raw */
570
659
  uk->reading_raw_remaining = count;
571
660
  return read_raw_body_begin(uk, RAW_TYPE_STRING);
@@ -574,7 +663,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
574
663
  case 0xc4: // bin 8
575
664
  {
576
665
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 1);
577
- uint8_t count = cb->u8;
666
+ uint8_t count = cb.u8;
578
667
  /* read_raw_body_begin sets uk->reading_raw */
579
668
  uk->reading_raw_remaining = count;
580
669
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -583,7 +672,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
583
672
  case 0xc5: // bin 16
584
673
  {
585
674
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
586
- uint16_t count = _msgpack_be16(cb->u16);
675
+ uint16_t count = _msgpack_be16(cb.u16);
587
676
  /* read_raw_body_begin sets uk->reading_raw */
588
677
  uk->reading_raw_remaining = count;
589
678
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -592,7 +681,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
592
681
  case 0xc6: // bin 32
593
682
  {
594
683
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
595
- uint32_t count = _msgpack_be32(cb->u32);
684
+ uint32_t count = _msgpack_be32(cb.u32);
596
685
  /* read_raw_body_begin sets uk->reading_raw */
597
686
  uk->reading_raw_remaining = count;
598
687
  return read_raw_body_begin(uk, RAW_TYPE_BINARY);
@@ -601,41 +690,41 @@ static int read_primitive(msgpack_unpacker_t* uk)
601
690
  case 0xdc: // array 16
602
691
  {
603
692
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
604
- uint16_t count = _msgpack_be16(cb->u16);
693
+ uint16_t count = _msgpack_be16(cb.u16);
605
694
  if(count == 0) {
606
695
  return object_complete(uk, rb_ary_new());
607
696
  }
608
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
697
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
609
698
  }
610
699
 
611
700
  case 0xdd: // array 32
612
701
  {
613
702
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
614
- uint32_t count = _msgpack_be32(cb->u32);
703
+ uint32_t count = _msgpack_be32(cb.u32);
615
704
  if(count == 0) {
616
705
  return object_complete(uk, rb_ary_new());
617
706
  }
618
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(count));
707
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
619
708
  }
620
709
 
621
710
  case 0xde: // map 16
622
711
  {
623
712
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
624
- uint16_t count = _msgpack_be16(cb->u16);
713
+ uint16_t count = _msgpack_be16(cb.u16);
625
714
  if(count == 0) {
626
715
  return object_complete(uk, rb_hash_new());
627
716
  }
628
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
717
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
629
718
  }
630
719
 
631
720
  case 0xdf: // map 32
632
721
  {
633
722
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
634
- uint32_t count = _msgpack_be32(cb->u32);
723
+ uint32_t count = _msgpack_be32(cb.u32);
635
724
  if(count == 0) {
636
725
  return object_complete(uk, rb_hash_new());
637
726
  }
638
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(count));
727
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
639
728
  }
640
729
 
641
730
  default:
@@ -661,12 +750,12 @@ int msgpack_unpacker_read_array_header(msgpack_unpacker_t* uk, uint32_t* result_
661
750
  } else if(b == 0xdc) {
662
751
  /* array 16 */
663
752
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
664
- *result_size = _msgpack_be16(cb->u16);
753
+ *result_size = _msgpack_be16(cb.u16);
665
754
 
666
755
  } else if(b == 0xdd) {
667
756
  /* array 32 */
668
757
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
669
- *result_size = _msgpack_be32(cb->u32);
758
+ *result_size = _msgpack_be32(cb.u32);
670
759
 
671
760
  } else {
672
761
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -689,12 +778,12 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
689
778
  } else if(b == 0xde) {
690
779
  /* map 16 */
691
780
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 2);
692
- *result_size = _msgpack_be16(cb->u16);
781
+ *result_size = _msgpack_be16(cb.u16);
693
782
 
694
783
  } else if(b == 0xdf) {
695
784
  /* map 32 */
696
785
  READ_CAST_BLOCK_OR_RETURN_EOF(cb, uk, 4);
697
- *result_size = _msgpack_be32(cb->u32);
786
+ *result_size = _msgpack_be32(cb.u32);
698
787
 
699
788
  } else {
700
789
  return PRIMITIVE_UNEXPECTED_TYPE;
@@ -706,9 +795,15 @@ int msgpack_unpacker_read_map_header(msgpack_unpacker_t* uk, uint32_t* result_si
706
795
 
707
796
  int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
708
797
  {
798
+ STACK_INIT(uk);
799
+
709
800
  while(true) {
710
801
  int r = read_primitive(uk);
711
802
  if(r < 0) {
803
+ if (r != PRIMITIVE_EOF) {
804
+ // We keep the stack on EOF as the parsing may be resumed.
805
+ STACK_FREE(uk);
806
+ }
712
807
  return r;
713
808
  }
714
809
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -717,6 +812,7 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
717
812
  /* PRIMITIVE_OBJECT_COMPLETE */
718
813
 
719
814
  if(msgpack_unpacker_stack_is_empty(uk)) {
815
+ STACK_FREE(uk);
720
816
  return PRIMITIVE_OBJECT_COMPLETE;
721
817
  }
722
818
 
@@ -740,12 +836,16 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
740
836
  }
741
837
  top->type = STACK_TYPE_MAP_KEY;
742
838
  break;
839
+ case STACK_TYPE_RECURSIVE:
840
+ STACK_FREE(uk);
841
+ return PRIMITIVE_OBJECT_COMPLETE;
743
842
  }
744
843
  size_t count = --top->count;
745
844
 
746
845
  if(count == 0) {
747
846
  object_complete(uk, top->object);
748
847
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
848
+ STACK_FREE(uk);
749
849
  return PRIMITIVE_OBJECT_COMPLETE;
750
850
  }
751
851
  goto container_completed;
@@ -756,9 +856,12 @@ int msgpack_unpacker_read(msgpack_unpacker_t* uk, size_t target_stack_depth)
756
856
 
757
857
  int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
758
858
  {
859
+ STACK_INIT(uk);
860
+
759
861
  while(true) {
760
862
  int r = read_primitive(uk);
761
863
  if(r < 0) {
864
+ STACK_FREE(uk);
762
865
  return r;
763
866
  }
764
867
  if(r == PRIMITIVE_CONTAINER_START) {
@@ -767,6 +870,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
767
870
  /* PRIMITIVE_OBJECT_COMPLETE */
768
871
 
769
872
  if(msgpack_unpacker_stack_is_empty(uk)) {
873
+ STACK_FREE(uk);
770
874
  return PRIMITIVE_OBJECT_COMPLETE;
771
875
  }
772
876
 
@@ -782,6 +886,7 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
782
886
  if(count == 0) {
783
887
  object_complete(uk, Qnil);
784
888
  if(msgpack_unpacker_stack_pop(uk) <= target_stack_depth) {
889
+ STACK_FREE(uk);
785
890
  return PRIMITIVE_OBJECT_COMPLETE;
786
891
  }
787
892
  goto container_completed;