json 2.16.0 → 2.19.3
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 +43 -1
- data/ext/json/ext/fbuffer/fbuffer.h +29 -25
- data/ext/json/ext/generator/extconf.rb +1 -1
- data/ext/json/ext/generator/generator.c +132 -369
- data/ext/json/ext/json.h +13 -0
- data/ext/json/ext/parser/extconf.rb +1 -2
- data/ext/json/ext/parser/parser.c +235 -179
- data/ext/json/ext/simd/simd.h +33 -16
- data/ext/json/ext/vendor/fpconv.c +3 -3
- data/lib/json/common.rb +62 -14
- data/lib/json/ext/generator/state.rb +1 -1
- data/lib/json/truffle_ruby/generator.rb +34 -18
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +33 -0
- 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: 3182d9103a2ee3b673b923a4789e947a9cddb850f870f7fdb54d93f3bd1a5493
|
|
4
|
+
data.tar.gz: 0ee85345c9e1c99223f9cc3e859e4a7295f40f88461ca0f47059cfcc4e80154c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dedf64066bc4017b977330468b01613ce1d4a78c267b38519b7ef2705368e5d73187b64ca99777afaf900cc5f58523a722833e83c0ee011944bf15b34c33479e
|
|
7
|
+
data.tar.gz: c187fa755e0a7bd2e2ddb74498062a8138ac4882630713e3372886b5648a22a453b1a388174038b2d4144a724e1d44d5b444b190e49e3e7eb2047d8b98eef0a8
|
data/CHANGES.md
CHANGED
|
@@ -2,6 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-03-25 (2.19.3)
|
|
6
|
+
|
|
7
|
+
* Fix handling of unescaped control characters preceeded by a backslash.
|
|
8
|
+
|
|
9
|
+
### 2026-03-18 (2.19.2)
|
|
10
|
+
|
|
11
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`.
|
|
12
|
+
|
|
13
|
+
### 2026-03-08 (2.19.1)
|
|
14
|
+
|
|
15
|
+
* Fix a compiler dependent GC bug introduced in `2.18.0`.
|
|
16
|
+
|
|
17
|
+
### 2026-03-06 (2.19.0)
|
|
18
|
+
|
|
19
|
+
* Fix `allow_blank` parsing option to no longer allow invalid types (e.g. `load([], allow_blank: true)` now raise a type error).
|
|
20
|
+
* Add `allow_invalid_escape` parsing option to ignore backslashes that aren't followed by one of the valid escape characters.
|
|
21
|
+
|
|
22
|
+
### 2026-02-03 (2.18.1)
|
|
23
|
+
|
|
24
|
+
* Fix a potential crash in very specific circumstance if GC triggers during a call to `to_json`
|
|
25
|
+
without first invoking a user defined `#to_json` method.
|
|
26
|
+
|
|
27
|
+
### 2025-12-11 (2.18.0)
|
|
28
|
+
|
|
29
|
+
* Add `:allow_control_characters` parser options, to allow JSON strings containing unescaped ASCII control characters (e.g. newlines).
|
|
30
|
+
|
|
31
|
+
### 2025-12-04 (2.17.1)
|
|
32
|
+
|
|
33
|
+
* Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
|
|
34
|
+
|
|
35
|
+
### 2025-12-03 (2.17.0)
|
|
36
|
+
|
|
37
|
+
* Improve `JSON.load` and `JSON.unsafe_load` to allow passing options as second argument.
|
|
38
|
+
* Fix the parser to no longer ignore invalid escapes in strings.
|
|
39
|
+
Only `\"`, `\\`, `\b`, `\f`, `\n`, `\r`, `\t` and `\u` are valid JSON escapes.
|
|
40
|
+
* Fixed `JSON::Coder` to use the depth it was initialized with.
|
|
41
|
+
* On TruffleRuby, fix the generator to not call `to_json` on the return value of `as_json` for `Float::NAN`.
|
|
42
|
+
* Fixed handling of `state.depth`: when `to_json` changes `state.depth` but does not restore it, it is reset
|
|
43
|
+
automatically to its initial value.
|
|
44
|
+
In particular, when a `NestingError` is raised, `depth` is no longer equal to `max_nesting` after the call to
|
|
45
|
+
generate, and is reset to its initial value. Similarly when `to_json` raises an exception.
|
|
46
|
+
|
|
5
47
|
### 2025-11-07 (2.16.0)
|
|
6
48
|
|
|
7
49
|
* Deprecate `JSON::State#[]` and `JSON::State#[]=`. Consider using `JSON::Coder` instead.
|
|
@@ -46,7 +88,7 @@
|
|
|
46
88
|
* Fix `JSON.generate` `strict: true` mode to also restrict hash keys.
|
|
47
89
|
* Fix `JSON::Coder` to also invoke block for hash keys that aren't strings nor symbols.
|
|
48
90
|
* Fix `JSON.unsafe_load` usage with proc
|
|
49
|
-
* Fix the parser to more consistently reject invalid UTF-16 surogate pairs.
|
|
91
|
+
* Fix the parser to more consistently reject invalid UTF-16 surogate pairs.
|
|
50
92
|
* Stop defining `String.json_create`, `String#to_json_raw`, `String#to_json_raw_object` when `json/add` isn't loaded.
|
|
51
93
|
|
|
52
94
|
### 2025-07-28 (2.13.2)
|
|
@@ -11,11 +11,11 @@ enum fbuffer_type {
|
|
|
11
11
|
|
|
12
12
|
typedef struct FBufferStruct {
|
|
13
13
|
enum fbuffer_type type;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
#
|
|
18
|
-
|
|
14
|
+
size_t initial_length;
|
|
15
|
+
size_t len;
|
|
16
|
+
size_t capa;
|
|
17
|
+
#if JSON_DEBUG
|
|
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) {
|
|
@@ -45,14 +45,14 @@ static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *
|
|
|
45
45
|
fb->ptr = stack_buffer;
|
|
46
46
|
fb->capa = stack_buffer_size;
|
|
47
47
|
}
|
|
48
|
-
#
|
|
48
|
+
#if JSON_DEBUG
|
|
49
49
|
fb->requested = 0;
|
|
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) {
|
|
57
57
|
rb_bug("fbuffer: Out of bound write");
|
|
58
58
|
}
|
|
@@ -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,9 +120,9 @@ 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;
|
|
127
127
|
#endif
|
|
128
128
|
|
|
@@ -131,13 +131,13 @@ static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr,
|
|
134
|
+
static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, size_t len)
|
|
135
135
|
{
|
|
136
136
|
MEMCPY(fb->ptr + fb->len, newstr, char, len);
|
|
137
137
|
fbuffer_consumed(fb, len);
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
static inline void fbuffer_append(FBuffer *fb, const char *newstr,
|
|
140
|
+
static inline void fbuffer_append(FBuffer *fb, const char *newstr, size_t len)
|
|
141
141
|
{
|
|
142
142
|
if (len > 0) {
|
|
143
143
|
fbuffer_inc_capa(fb, len);
|
|
@@ -148,7 +148,7 @@ static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long
|
|
|
148
148
|
/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
|
|
149
149
|
static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
150
150
|
{
|
|
151
|
-
#
|
|
151
|
+
#if JSON_DEBUG
|
|
152
152
|
if (fb->requested < 1) {
|
|
153
153
|
rb_bug("fbuffer: unreserved write");
|
|
154
154
|
}
|
|
@@ -161,25 +161,29 @@ static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
|
|
|
161
161
|
|
|
162
162
|
static void fbuffer_append_str(FBuffer *fb, VALUE str)
|
|
163
163
|
{
|
|
164
|
-
const char *
|
|
165
|
-
|
|
164
|
+
const char *ptr;
|
|
165
|
+
size_t len;
|
|
166
|
+
RSTRING_GETMEM(str, ptr, len);
|
|
166
167
|
|
|
167
|
-
fbuffer_append(fb,
|
|
168
|
+
fbuffer_append(fb, ptr, len);
|
|
169
|
+
RB_GC_GUARD(str);
|
|
168
170
|
}
|
|
169
171
|
|
|
170
172
|
static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
|
|
171
173
|
{
|
|
172
|
-
const char *
|
|
173
|
-
|
|
174
|
+
const char *ptr;
|
|
175
|
+
size_t len;
|
|
176
|
+
RSTRING_GETMEM(str, ptr, len);
|
|
174
177
|
|
|
175
178
|
fbuffer_inc_capa(fb, repeat * len);
|
|
176
179
|
while (repeat) {
|
|
177
|
-
#
|
|
180
|
+
#if JSON_DEBUG
|
|
178
181
|
fb->requested = len;
|
|
179
182
|
#endif
|
|
180
|
-
fbuffer_append_reserved(fb,
|
|
183
|
+
fbuffer_append_reserved(fb, ptr, len);
|
|
181
184
|
repeat--;
|
|
182
185
|
}
|
|
186
|
+
RB_GC_GUARD(str);
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
static inline void fbuffer_append_char(FBuffer *fb, char newchr)
|
|
@@ -6,7 +6,7 @@ if RUBY_ENGINE == 'truffleruby'
|
|
|
6
6
|
else
|
|
7
7
|
append_cflags("-std=c99")
|
|
8
8
|
$defs << "-DJSON_GENERATOR"
|
|
9
|
-
$defs << "-DJSON_DEBUG" if ENV
|
|
9
|
+
$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
|
|
10
10
|
|
|
11
11
|
if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
|
|
12
12
|
load __dir__ + "/../simd/conf.rb"
|