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 +4 -4
- data/ChangeLog +6 -0
- data/ext/msgpack/buffer.h +18 -5
- data/ext/msgpack/unpacker.c +23 -13
- data/ext/msgpack/unpacker.h +6 -0
- data/ext/msgpack/unpacker_class.c +1 -1
- data/lib/msgpack/bigint.rb +3 -7
- data/lib/msgpack/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc5fdca2a5a867c26e72649de9838ca9a7ee44e2e84d295215207edaa98d3629
|
|
4
|
+
data.tar.gz: 703a7d56d9d634b53020db638e578339296e6a9cbc3da0ee6d3c8efa7d5d58bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
|
|
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;
|
data/ext/msgpack/unpacker.c
CHANGED
|
@@ -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
|
|
77
|
+
static inline int16_t initial_buffer_size(msgpack_unpacker_t* uk, long count, size_t bytes_per_element)
|
|
78
78
|
{
|
|
79
|
-
|
|
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
|
|
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
|
-
/*
|
|
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
|
data/ext/msgpack/unpacker.h
CHANGED
|
@@ -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
|
|
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");
|
data/lib/msgpack/bigint.rb
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
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
|
data/lib/msgpack/version.rb
CHANGED
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.
|
|
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.
|
|
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: []
|