msgpack 1.8.5 → 1.8.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9a5462dff41bc8885570f42b59092d6e02729500a9a873aa15ead68ed8872ccb
4
- data.tar.gz: 3fcc99b85b8ece0dd0158f2ee511784a789f41ab9d3bafd9f6fc006ccd3b9061
3
+ metadata.gz: cc5fdca2a5a867c26e72649de9838ca9a7ee44e2e84d295215207edaa98d3629
4
+ data.tar.gz: 703a7d56d9d634b53020db638e578339296e6a9cbc3da0ee6d3c8efa7d5d58bb
5
5
  SHA512:
6
- metadata.gz: 3cb8969960d3d2de3beb39503cb33259ac169f27397d75f981a2563bf14700e4359ca30f2fc6357bf848b707546dc0c692385250c186496e2ef7d5546809bab3
7
- data.tar.gz: 5cb7b9154e12839ee504c5630d3cee504558206ea63fb54236fc7433191a763267a7fce29a43157d59507f0cc1d4b5b88ba62607571ce98ca1175aa911c1c338
6
+ metadata.gz: d06ef9b19f1d8e3d18eb2bc05ed5cd26102bdd0cb60d1d8ac622d122da1d734cc2c17180f4b9c0fd75d093f0829ebd38ecab4f3a685d0cb3653a20cf5bbd78c4
7
+ data.tar.gz: d5f57a80f7a109703629c1965d87638675b478ca0f34ac8421836fbadde433cd108185094326cff0a4b9c7d59f53d07904a4569e9549ca6a500f0309ae58048a
data/ChangeLog CHANGED
@@ -1,3 +1,9 @@
1
+ 2026-10-27 1.8.6
2
+
3
+ * Fix use-after-free when a recursive extension proc rescues, skips or resets.
4
+ * Speed up decoding of oversized integers.
5
+ * Avoid excessive memory allocation from crafted container headers.
6
+
1
7
  2026-09-11 1.8.5
2
8
 
3
9
  * Prevent stack depth underflow when skipping from recursive unpacker.
data/ext/msgpack/buffer.h CHANGED
@@ -237,14 +237,27 @@ void _msgpack_buffer_append_long_string(msgpack_buffer_t* b, VALUE string);
237
237
 
238
238
  static inline size_t msgpack_buffer_append_string(msgpack_buffer_t* b, VALUE string)
239
239
  {
240
- size_t length;
241
- char *ptr;
242
- RSTRING_GETMEM(string, ptr, length);
240
+ size_t length = RSTRING_LEN(string);
243
241
 
244
242
  if(length > b->write_reference_threshold) {
245
243
  _msgpack_buffer_append_long_string(b, string);
246
- } else {
247
- msgpack_buffer_append(b, ptr, length);
244
+ } else if(length > 0) {
245
+ /* Making room can run io.write or trigger GC, either of which may free
246
+ * or shrink the string, so reserve the space first and only then read
247
+ * its pointer. */
248
+ msgpack_buffer_ensure_writable(b, length);
249
+ char *ptr;
250
+ size_t current;
251
+ RSTRING_GETMEM(string, ptr, current);
252
+ if(current > length) {
253
+ current = length;
254
+ }
255
+ memcpy(b->tail.last, ptr, current);
256
+ if(current < length) {
257
+ memset(b->tail.last + current, 0, length - current);
258
+ }
259
+ b->tail.last += length;
260
+ RB_GC_GUARD(string);
248
261
  }
249
262
 
250
263
  return length;
@@ -74,9 +74,13 @@ static inline VALUE rb_hash_new_capa_inline(long capa)
74
74
  #define rb_hash_new_capa rb_hash_new_capa_inline
75
75
  #endif
76
76
 
77
- static inline int16_t initial_buffer_size(long size)
77
+ static inline int16_t initial_buffer_size(msgpack_unpacker_t* uk, long count, size_t bytes_per_element)
78
78
  {
79
- return (size > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : size;
79
+ size_t available = msgpack_buffer_all_readable_size(UNPACKER_BUFFER_(uk)) / bytes_per_element;
80
+ if((size_t)count > available) {
81
+ count = (long)available;
82
+ }
83
+ return (count > INITIAL_BUFFER_CAPACITY_MAX) ? INITIAL_BUFFER_CAPACITY_MAX : count;
80
84
  }
81
85
 
82
86
  void msgpack_unpacker_static_init(void)
@@ -110,6 +114,7 @@ static inline void _msgpack_unpacker_free_stack(msgpack_unpacker_stack_t* stack)
110
114
  }
111
115
  stack->data = NULL;
112
116
  stack->depth = 0;
117
+ stack->floor = 0;
113
118
  }
114
119
  }
115
120
 
@@ -169,7 +174,7 @@ void _msgpack_unpacker_reset(msgpack_unpacker_t* uk)
169
174
  uk->head_byte = HEAD_BYTE_REQUIRED;
170
175
 
171
176
  /*memset(uk->stack, 0, sizeof(msgpack_unpacker_t) * uk->stack.depth);*/
172
- uk->stack.depth = 0;
177
+ msgpack_unpacker_stack_rewind(uk);
173
178
  uk->last_object = Qnil;
174
179
  uk->reading_raw = Qnil;
175
180
  uk->reading_raw_remaining = 0;
@@ -387,13 +392,14 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type)
387
392
  return PRIMITIVE_STACK_TOO_DEEP;
388
393
  }
389
394
  size_t barrier_depth = uk->stack.depth;
395
+ size_t saved_floor = uk->stack.floor;
390
396
  int raised;
397
+
398
+ uk->stack.floor = barrier_depth;
391
399
  obj = protected_proc_call(proc, 1, &uk->self, &raised);
400
+ uk->stack.floor = saved_floor;
392
401
 
393
- /* The user proc can drive the unpacker itself (Unpacker#read, #skip,
394
- * or a rescued error) and leave stack.depth anywhere, including 0.
395
- * Restore it to just below the barrier we pushed instead of an
396
- * unconditional decrement, which would underflow to SIZE_MAX. */
402
+ /* Not --depth: the proc may return with entries left above the barrier. */
397
403
  uk->stack.depth = barrier_depth - 1;
398
404
 
399
405
  if (raised) {
@@ -479,14 +485,14 @@ static int read_primitive(msgpack_unpacker_t* uk)
479
485
  if(count == 0) {
480
486
  return object_complete(uk, rb_ary_new());
481
487
  }
482
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
488
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(uk, count, 1)));
483
489
 
484
490
  SWITCH_RANGE(b, 0x80, 0x8f) // FixMap
485
491
  int count = b & 0x0f;
486
492
  if(count == 0) {
487
493
  return object_complete(uk, rb_hash_new());
488
494
  }
489
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
495
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(uk, count, 2)));
490
496
 
491
497
  SWITCH_RANGE(b, 0xc0, 0xdf) // Variable
492
498
  switch(b) {
@@ -709,7 +715,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
709
715
  if(count == 0) {
710
716
  return object_complete(uk, rb_ary_new());
711
717
  }
712
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
718
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(uk, count, 1)));
713
719
  }
714
720
 
715
721
  case 0xdd: // array 32
@@ -719,7 +725,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
719
725
  if(count == 0) {
720
726
  return object_complete(uk, rb_ary_new());
721
727
  }
722
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(count)));
728
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_ARRAY, count, rb_ary_new2(initial_buffer_size(uk, count, 1)));
723
729
  }
724
730
 
725
731
  case 0xde: // map 16
@@ -729,7 +735,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
729
735
  if(count == 0) {
730
736
  return object_complete(uk, rb_hash_new());
731
737
  }
732
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
738
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(uk, count, 2)));
733
739
  }
734
740
 
735
741
  case 0xdf: // map 32
@@ -739,7 +745,7 @@ static int read_primitive(msgpack_unpacker_t* uk)
739
745
  if(count == 0) {
740
746
  return object_complete(uk, rb_hash_new());
741
747
  }
742
- return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(count)));
748
+ return _msgpack_unpacker_stack_push(uk, STACK_TYPE_MAP_KEY, count*2, rb_hash_new_capa(initial_buffer_size(uk, count, 2)));
743
749
  }
744
750
 
745
751
  default:
@@ -892,6 +898,10 @@ int msgpack_unpacker_skip(msgpack_unpacker_t* uk, size_t target_stack_depth)
892
898
  container_completed:
893
899
  {
894
900
  msgpack_unpacker_stack_entry_t* top = _msgpack_unpacker_stack_entry_top(uk);
901
+ if(top->type == STACK_TYPE_RECURSIVE) {
902
+ STACK_FREE(uk);
903
+ return PRIMITIVE_OBJECT_COMPLETE;
904
+ }
895
905
 
896
906
  /* this section optimized out */
897
907
  // TODO object_complete still creates objects which should be optimized out
@@ -43,6 +43,7 @@ typedef struct {
43
43
 
44
44
  struct msgpack_unpacker_stack_t {
45
45
  size_t depth;
46
+ size_t floor;
46
47
  size_t capacity;
47
48
  msgpack_unpacker_stack_entry_t *data;
48
49
  };
@@ -109,6 +110,11 @@ static inline void msgpack_unpacker_set_allow_unknown_ext(msgpack_unpacker_t* uk
109
110
  uk->allow_unknown_ext = enable;
110
111
  }
111
112
 
113
+ static inline void msgpack_unpacker_stack_rewind(msgpack_unpacker_t* uk)
114
+ {
115
+ uk->stack.depth = uk->stack.floor;
116
+ }
117
+
112
118
 
113
119
  /* error codes */
114
120
  #define PRIMITIVE_CONTAINER_START 1
@@ -165,7 +165,7 @@ static VALUE Unpacker_allow_unknown_ext_p(VALUE self)
165
165
 
166
166
  NORETURN(static void raise_unpacker_error(msgpack_unpacker_t *uk, int r))
167
167
  {
168
- uk->stack.depth = 0;
168
+ msgpack_unpacker_stack_rewind(uk);
169
169
  switch(r) {
170
170
  case PRIMITIVE_EOF:
171
171
  rb_raise(rb_eEOFError, "end of buffer reached");
@@ -5,7 +5,8 @@ module MessagePack
5
5
  # We split the bigint in 32bits chunks so that individual part fits into
6
6
  # a MRI immediate Integer.
7
7
  CHUNK_BITLENGTH = 32
8
- FORMAT = 'CL>*'
8
+ CHUNK_FORMAT = 'L>*'
9
+ FORMAT = "C#{CHUNK_FORMAT}"
9
10
 
10
11
  if Integer.instance_method(:[]).arity != 1 # Ruby 2.7 and newer
11
12
  # Starting from Ruby 2.7 we can address arbitrary bitranges inside an Integer with Integer#[]
@@ -56,12 +57,7 @@ module MessagePack
56
57
  parts = data.unpack(FORMAT)
57
58
 
58
59
  sign = parts.shift
59
- sum = parts.pop.to_i
60
-
61
- parts.reverse_each do |part|
62
- sum = sum << CHUNK_BITLENGTH
63
- sum += part
64
- end
60
+ sum = parts.reverse.pack(CHUNK_FORMAT).unpack1('H*').to_i(16)
65
61
 
66
62
  sign == 0 ? sum : -sum
67
63
  end
@@ -1,5 +1,5 @@
1
1
  module MessagePack
2
- VERSION = "1.8.5"
2
+ VERSION = "1.8.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.
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.8.5
4
+ version: 1.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sadayuki Furuhashi
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
98
  - !ruby/object:Gem::Version
99
99
  version: '0'
100
100
  requirements: []
101
- rubygems_version: 4.0.16
101
+ rubygems_version: 4.0.20
102
102
  specification_version: 4
103
103
  summary: MessagePack, a binary-based efficient data interchange format.
104
104
  test_files: []