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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8bd00bbc63367659eb90ee7e3f4f1394fecdf713fc724f7908c6a2c7b79bbf7
4
- data.tar.gz: efa1d81f687277247649de777f25be01e56ad8dfac1bdd9ce61111e10231185e
3
+ metadata.gz: 3182d9103a2ee3b673b923a4789e947a9cddb850f870f7fdb54d93f3bd1a5493
4
+ data.tar.gz: 0ee85345c9e1c99223f9cc3e859e4a7295f40f88461ca0f47059cfcc4e80154c
5
5
  SHA512:
6
- metadata.gz: cb8b505c08b88115a87aa0b6ab8b7f34d6e0611af7d37277cef243131990db6cb77ca2508045104588607d54bd58b0c2e67ce0728bd72c4c32d2d77a56b9762e
7
- data.tar.gz: 8dec0d5ba99f33e68049328f060a600da2fe0545caf47c44c2e812a8316cbe64a99152f365be8654cb4af45493de3bed97baa61a0b2a71ae71a7466d0ee11e8c
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
- unsigned long initial_length;
15
- unsigned long len;
16
- unsigned long capa;
17
- #ifdef JSON_DEBUG
18
- unsigned long requested;
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, unsigned long len);
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, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
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
- #ifdef JSON_DEBUG
48
+ #if JSON_DEBUG
49
49
  fb->requested = 0;
50
50
  #endif
51
51
  }
52
52
 
53
- static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
53
+ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
54
54
  {
55
- #ifdef JSON_DEBUG
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, unsigned long required)
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, unsigned long requested)
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
- unsigned long required;
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, unsigned long requested)
123
+ static inline void fbuffer_inc_capa(FBuffer *fb, size_t requested)
124
124
  {
125
- #ifdef JSON_DEBUG
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, unsigned long len)
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, unsigned long len)
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
- #ifdef JSON_DEBUG
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 *newstr = StringValuePtr(str);
165
- unsigned long len = RSTRING_LEN(str);
164
+ const char *ptr;
165
+ size_t len;
166
+ RSTRING_GETMEM(str, ptr, len);
166
167
 
167
- fbuffer_append(fb, newstr, len);
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 *newstr = StringValuePtr(str);
173
- unsigned long len = RSTRING_LEN(str);
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
- #ifdef JSON_DEBUG
180
+ #if JSON_DEBUG
178
181
  fb->requested = len;
179
182
  #endif
180
- fbuffer_append_reserved(fb, newstr, len);
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["JSON_DEBUG"]
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"