json 2.18.1 → 2.19.7
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/CHANGES.md +45 -0
- data/ext/json/ext/fbuffer/fbuffer.h +27 -16
- data/ext/json/ext/generator/extconf.rb +2 -0
- data/ext/json/ext/generator/generator.c +89 -316
- data/ext/json/ext/json.h +15 -0
- data/ext/json/ext/parser/extconf.rb +4 -0
- data/ext/json/ext/parser/parser.c +172 -101
- data/ext/json/ext/simd/simd.h +0 -10
- data/lib/json/common.rb +41 -10
- data/lib/json/ext/generator/state.rb +1 -1
- data/lib/json/truffle_ruby/generator.rb +21 -9
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +14 -2
- 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: 579bc938143b2fc703d90623fb985af883a7b46f0641d874cc44a39a4ffae2dd
|
|
4
|
+
data.tar.gz: f69a8d12a9f83378e0e0e6b0abdda34cf23d7ebf026dcc114dc70089dd159190
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3bb0a35502ac84a22a71f076a68feb5ea525ff802491e2532bd863653d1b6808de4715108886e6bb00cc5ef378ec298bea81e2d932a748886f1f4ec8b0637b03
|
|
7
|
+
data.tar.gz: e50b9b31f846e105a725807db54fe86f8176331d975ea772a1f9f666ed91e4555497f79008a4b01b08de3c2605cb1867671f87b86f196632b05d1f5a21872143
|
data/CHANGES.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-05-28 (2.19.7)
|
|
6
|
+
|
|
7
|
+
* Fix some more edge cases with out of range floats.
|
|
8
|
+
* Ensure the string provided to `JSON.parse` can't be mutated during parsing.
|
|
9
|
+
* Add missing write barriers in `State#dup`.
|
|
10
|
+
* Further validate generator `depth` config.
|
|
11
|
+
|
|
12
|
+
### 2026-05-28 (2.19.6)
|
|
13
|
+
|
|
14
|
+
* Cleanly handle overly large `depth` generator argument.
|
|
15
|
+
* Add missing write barrier in `ParserConfig`.
|
|
16
|
+
|
|
17
|
+
### 2026-05-04 (2.19.5)
|
|
18
|
+
|
|
19
|
+
* Cap the parser to emit a maximum of 5 deprecation warnings per document. Emitting more is not helpful.
|
|
20
|
+
|
|
21
|
+
### 2026-04-19 (2.19.4)
|
|
22
|
+
|
|
23
|
+
* Fix parsing of out of range floats (very large exponents that lead to either `0.0` or `Inf`).
|
|
24
|
+
|
|
25
|
+
### 2026-03-25 (2.19.3)
|
|
26
|
+
|
|
27
|
+
* Fix handling of unescaped control characters preceeded by a backslash.
|
|
28
|
+
|
|
29
|
+
### 2026-03-18 (2.19.2)
|
|
30
|
+
|
|
31
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
32
|
+
|
|
33
|
+
### 2026-03-08 (2.19.1)
|
|
34
|
+
|
|
35
|
+
* Fix a compiler dependent GC bug introduced in `2.18.0`.
|
|
36
|
+
|
|
37
|
+
### 2026-03-06 (2.19.0)
|
|
38
|
+
|
|
39
|
+
* Fix `allow_blank` parsing option to no longer allow invalid types (e.g. `load([], allow_blank: true)` now raise a type error).
|
|
40
|
+
* Add `allow_invalid_escape` parsing option to ignore backslashes that aren't followed by one of the valid escape characters.
|
|
41
|
+
|
|
5
42
|
### 2026-02-03 (2.18.1)
|
|
6
43
|
|
|
7
44
|
* Fix a potential crash in very specific circumstance if GC triggers during a call to `to_json`
|
|
@@ -11,6 +48,10 @@
|
|
|
11
48
|
|
|
12
49
|
* Add `:allow_control_characters` parser options, to allow JSON strings containing unescaped ASCII control characters (e.g. newlines).
|
|
13
50
|
|
|
51
|
+
### 2026-03-18 (2.17.1.2) - Security Backport
|
|
52
|
+
|
|
53
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
54
|
+
|
|
14
55
|
### 2025-12-04 (2.17.1)
|
|
15
56
|
|
|
16
57
|
* Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
|
|
@@ -37,6 +78,10 @@
|
|
|
37
78
|
* Optimized numbers parsing using SWAR (thanks to Scott Myron).
|
|
38
79
|
* Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
|
|
39
80
|
|
|
81
|
+
### 2026-03-18 (2.15.2.1) - Security Backport
|
|
82
|
+
|
|
83
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
84
|
+
|
|
40
85
|
### 2025-10-25 (2.15.2)
|
|
41
86
|
|
|
42
87
|
* Fix `JSON::Coder` to have one dedicated depth counter per invocation.
|
|
@@ -11,11 +11,11 @@ enum fbuffer_type {
|
|
|
11
11
|
|
|
12
12
|
typedef struct FBufferStruct {
|
|
13
13
|
enum fbuffer_type type;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
size_t initial_length;
|
|
15
|
+
size_t len;
|
|
16
|
+
size_t capa;
|
|
17
17
|
#if JSON_DEBUG
|
|
18
|
-
|
|
18
|
+
size_t requested;
|
|
19
19
|
#endif
|
|
20
20
|
char *ptr;
|
|
21
21
|
VALUE io;
|
|
@@ -32,12 +32,12 @@ typedef struct FBufferStruct {
|
|
|
32
32
|
|
|
33
33
|
static void fbuffer_free(FBuffer *fb);
|
|
34
34
|
static void fbuffer_clear(FBuffer *fb);
|
|
35
|
-
static void fbuffer_append(FBuffer *fb, const char *newstr,
|
|
35
|
+
static void fbuffer_append(FBuffer *fb, const char *newstr, size_t len);
|
|
36
36
|
static void fbuffer_append_long(FBuffer *fb, long number);
|
|
37
37
|
static inline void fbuffer_append_char(FBuffer *fb, char newchr);
|
|
38
38
|
static VALUE fbuffer_finalize(FBuffer *fb);
|
|
39
39
|
|
|
40
|
-
static void fbuffer_stack_init(FBuffer *fb,
|
|
40
|
+
static void fbuffer_stack_init(FBuffer *fb, size_t initial_length, char *stack_buffer, size_t stack_buffer_size)
|
|
41
41
|
{
|
|
42
42
|
fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
|
|
43
43
|
if (stack_buffer) {
|
|
@@ -50,7 +50,7 @@ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *
|
|
|
50
50
|
#endif
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
static inline void fbuffer_consumed(FBuffer *fb,
|
|
53
|
+
static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
|
|
54
54
|
{
|
|
55
55
|
#if JSON_DEBUG
|
|
56
56
|
if (consumed > fb->requested) {
|
|
@@ -79,7 +79,7 @@ static void fbuffer_flush(FBuffer *fb)
|
|
|
79
79
|
fbuffer_clear(fb);
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
static void fbuffer_realloc(FBuffer *fb,
|
|
82
|
+
static void fbuffer_realloc(FBuffer *fb, size_t required)
|
|
83
83
|
{
|
|
84
84
|
if (required > fb->capa) {
|
|
85
85
|
if (fb->type == FBUFFER_STACK_ALLOCATED) {
|
|
@@ -94,7 +94,7 @@ static void fbuffer_realloc(FBuffer *fb, unsigned long required)
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
-
static void fbuffer_do_inc_capa(FBuffer *fb,
|
|
97
|
+
static void fbuffer_do_inc_capa(FBuffer *fb, size_t requested)
|
|
98
98
|
{
|
|
99
99
|
if (RB_UNLIKELY(fb->io)) {
|
|
100
100
|
if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
|
|
@@ -108,7 +108,7 @@ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
size_t required;
|
|
112
112
|
|
|
113
113
|
if (RB_UNLIKELY(!fb->ptr)) {
|
|
114
114
|
fb->ptr = ALLOC_N(char, fb->initial_length);
|
|
@@ -120,7 +120,7 @@ static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
120
120
|
fbuffer_realloc(fb, required);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
static inline void fbuffer_inc_capa(FBuffer *fb,
|
|
123
|
+
static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
|
|
124
124
|
{
|
|
125
125
|
#if JSON_DEBUG
|
|
126
126
|
fb->requested = requested;
|
|
@@ -131,13 +131,22 @@ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
static inline
|
|
134
|
+
static inline size_t fbuffer_size_mul_or_raise(size_t a, size_t b)
|
|
135
|
+
{
|
|
136
|
+
size_t result = a * b;
|
|
137
|
+
if (RB_UNLIKELY(a != 0 && (result / a) != b)) {
|
|
138
|
+
rb_raise(rb_eArgError, "Buffer overflow, the resulting document is too large to be generated");
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, size_t len)
|
|
135
144
|
{
|
|
136
145
|
MEMCPY(fb->ptr + fb->len, newstr, char, len);
|
|
137
146
|
fbuffer_consumed(fb, len);
|
|
138
147
|
}
|
|
139
148
|
|
|
140
|
-
static inline void fbuffer_append(FBuffer *fb, const char *newstr,
|
|
149
|
+
static inline void fbuffer_append(FBuffer *fb, const char *newstr, size_t len)
|
|
141
150
|
{
|
|
142
151
|
if (len > 0) {
|
|
143
152
|
fbuffer_inc_capa(fb, len);
|
|
@@ -162,19 +171,20 @@ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
|
162
171
|
static void fbuffer_append_str(FBuffer *fb, VALUE str)
|
|
163
172
|
{
|
|
164
173
|
const char *ptr;
|
|
165
|
-
|
|
174
|
+
size_t len;
|
|
166
175
|
RSTRING_GETMEM(str, ptr, len);
|
|
167
176
|
|
|
168
177
|
fbuffer_append(fb, ptr, len);
|
|
178
|
+
RB_GC_GUARD(str);
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
|
|
172
182
|
{
|
|
173
183
|
const char *ptr;
|
|
174
|
-
|
|
184
|
+
size_t len;
|
|
175
185
|
RSTRING_GETMEM(str, ptr, len);
|
|
176
186
|
|
|
177
|
-
fbuffer_inc_capa(fb, repeat
|
|
187
|
+
fbuffer_inc_capa(fb, fbuffer_size_mul_or_raise(repeat, len));
|
|
178
188
|
while (repeat) {
|
|
179
189
|
#if JSON_DEBUG
|
|
180
190
|
fb->requested = len;
|
|
@@ -182,6 +192,7 @@ static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
|
|
|
182
192
|
fbuffer_append_reserved(fb, ptr, len);
|
|
183
193
|
repeat--;
|
|
184
194
|
}
|
|
195
|
+
RB_GC_GUARD(str);
|
|
185
196
|
}
|
|
186
197
|
|
|
187
198
|
static inline void fbuffer_append_char(FBuffer *fb, char newchr)
|
|
@@ -5,6 +5,8 @@ if RUBY_ENGINE == 'truffleruby'
|
|
|
5
5
|
File.write('Makefile', dummy_makefile("").join)
|
|
6
6
|
else
|
|
7
7
|
append_cflags("-std=c99")
|
|
8
|
+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
|
|
9
|
+
|
|
8
10
|
$defs << "-DJSON_GENERATOR"
|
|
9
11
|
$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
|
|
10
12
|
|