json 2.19.9 → 2.20.0

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: 5e5fed66aaa650ac7aaf223c4d8e505a2d6ce3fe72599af4931356ae619f020b
4
- data.tar.gz: 347004780c7a7568685502ade79f145371a49a213d348a65c99ea8fbffc6eee7
3
+ metadata.gz: 24e3bc40d587f5a4c001b5f4c7da30170bdf06f5401f2aa1928469c8fb3860e2
4
+ data.tar.gz: b668789b5f3a56d7db311eb4ec9d10b6d236debab23016fabd1682316d50ae50
5
5
  SHA512:
6
- metadata.gz: 0bffdb4cd21e4656a1402a00d95ae890dc75befff379aeef4aad575a7f715a0dbeb87cfef6fefa3cd5235c3302a29fabb510d5db67e527678023cd8a88c34b49
7
- data.tar.gz: 7e08cfae0c5d404687644528ecfb9438c9ea254f43fd285d116ba1542a4ef78045463b18850324e91ba4d0c735e7d9ed4b583499aadafe7d0bab51dd54a8d086
6
+ metadata.gz: aaa62a65724e3caa24797ce93ed3ac710a0186a1fd2db990a20fddb10eb99c71d92a967d0bed9d5086cb5b203c5dda0793faa461fda1e5c6963c62da5b4db3dc
7
+ data.tar.gz: fc44e571dcb662a35a36165d7f7afbb94b11ab8d5660ab1a65905961b7548260152afbb3286fd233223ea5435b6bb62135a3b67b30bd26ca0cd8114e6921c980
data/CHANGES.md CHANGED
@@ -2,10 +2,20 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2026-06-23 (2.20.0)
6
+
7
+ * Both C and Java parsers are no longer recursive, so parsing very deep documents with `max_nesting: false` will no longer
8
+ result in `SystemStackError stack level too deep` errors.
9
+ * The `:max_nesting` option still defaults to `100`.
10
+ * Optimized floating point number parsing further by replacing the ryu algorithm by a port of Eisel-Lemire Fast Float.
11
+ * Added `JSON::ResumableParser` to parse streams of JSON documents. Not yet available on JRuby.
12
+ * Deprecate default support of JavaScript comments in the parser and add `allow_comments: true` parsing option.
13
+ * Integrate with Ruby 4.1 `ruby_sized_xfree`.
14
+
5
15
  ### 2026-06-11 (2.19.9)
6
16
 
7
17
  * Fix buffer overflow that could lead to a crash when writing JSON directly into an IO
8
- with `JSON.generate(object, io)`. [CVE-PENDING].
18
+ with `JSON.generate(object, io)`. [CVE-2026-54696].
9
19
 
10
20
  ### 2026-06-03 (2.19.8)
11
21
 
data/LEGAL CHANGED
@@ -15,6 +15,6 @@ ext/json/ext/vendor/jeaiii-ltoa.h::
15
15
  This file is adapted from https://github.com/jeaiii/itoa
16
16
  It is licensed under the MIT License
17
17
 
18
- ext/json/ext/vendor/ryu.h::
19
- This file is adapted from the Ryu algorithm by Ulf Adams https://github.com/ulfjack/ryu.
20
- It is dual-licensed under Apache License 2.0 OR Boost Software License 1.0.
18
+ ext/json/ext/vendor/fast_float_parser.h::
19
+ This file is adapted from the Fast Float C++ library by The fast_float authors https://github.com/fastfloat/fast_float
20
+ It is licensed under the MIT License
data/README.md CHANGED
@@ -306,5 +306,3 @@ The latest version of this library can be downloaded at
306
306
  Online Documentation should be located at
307
307
 
308
308
  * https://www.rubydoc.info/gems/json
309
-
310
- [Ragel]: http://www.colm.net/open-source/ragel/
@@ -68,7 +68,7 @@ static inline void fbuffer_consumed(FBuffer *fb, size_t consumed)
68
68
  static void fbuffer_free(FBuffer *fb)
69
69
  {
70
70
  if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
71
- ruby_xfree(fb->ptr);
71
+ JSON_SIZED_FREE_N(fb->ptr, fb->capa);
72
72
  }
73
73
  }
74
74
 
@@ -92,7 +92,7 @@ static void fbuffer_realloc(FBuffer *fb, size_t new_capa)
92
92
  fb->type = FBUFFER_HEAP_ALLOCATED;
93
93
  MEMCPY(fb->ptr, old_buffer, char, fb->len);
94
94
  } else {
95
- REALLOC_N(fb->ptr, char, new_capa);
95
+ JSON_SIZED_REALLOC_N(fb->ptr, char, new_capa, fb->capa);
96
96
  }
97
97
  fb->capa = new_capa;
98
98
  }
@@ -6,6 +6,7 @@ if RUBY_ENGINE == 'truffleruby'
6
6
  else
7
7
  append_cflags("-std=c99")
8
8
  have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
9
+ have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
9
10
 
10
11
  $defs << "-DJSON_GENERATOR"
11
12
  $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
@@ -724,7 +724,11 @@ static void State_compact(void *ptr)
724
724
 
725
725
  static size_t State_memsize(const void *ptr)
726
726
  {
727
+ #ifdef HAVE_RUBY_TYPED_EMBEDDABLE
728
+ return 0;
729
+ #else
727
730
  return sizeof(JSON_Generator_State);
731
+ #endif
728
732
  }
729
733
 
730
734
  static const rb_data_type_t JSON_Generator_State_type = {
data/ext/json/ext/json.h CHANGED
@@ -11,6 +11,9 @@
11
11
 
12
12
  #if defined(RUBY_DEBUG) && RUBY_DEBUG
13
13
  # define JSON_ASSERT RUBY_ASSERT
14
+ # ifndef JSON_DEBUG
15
+ # define JSON_DEBUG 1
16
+ # endif
14
17
  #else
15
18
  # ifdef JSON_DEBUG
16
19
  # include <assert.h>
@@ -20,8 +23,18 @@
20
23
  # endif
21
24
  #endif
22
25
 
26
+ #ifdef JSON_DEBUG
27
+ # define JSON_UNREACHABLE_RETURN(val) rb_bug("Unreachable")
28
+ #else
29
+ # define JSON_UNREACHABLE_RETURN UNREACHABLE_RETURN
30
+ #endif
31
+
23
32
  /* shims */
24
33
 
34
+ #ifndef UNDEF_P
35
+ #define UNDEF_P(val) (val == Qundef)
36
+ #endif
37
+
25
38
  #if SIZEOF_UINT64_T == SIZEOF_LONG_LONG
26
39
  # define INT64T2NUM(x) LL2NUM(x)
27
40
  # define UINT64T2NUM(x) ULL2NUM(x)
@@ -49,6 +62,24 @@ typedef unsigned char _Bool;
49
62
  #endif
50
63
  #endif
51
64
 
65
+ #ifndef HAVE_RUBY_XFREE_SIZED
66
+ static inline void ruby_xfree_sized(void *ptr, size_t oldsize)
67
+ {
68
+ ruby_xfree(ptr);
69
+ }
70
+
71
+ static inline void *ruby_xrealloc2_sized(void *ptr, size_t new_elems, size_t elem_size, size_t old_elems)
72
+ {
73
+ return ruby_xrealloc2(ptr, new_elems, elem_size);
74
+ }
75
+ #endif
76
+
77
+ # define JSON_SIZED_REALLOC_N(v, T, m, n) \
78
+ ((v) = (T *)ruby_xrealloc2_sized((void *)(v), (m), sizeof(T), (n)))
79
+
80
+ # define JSON_SIZED_FREE(v) ruby_xfree_sized((void *)(v), sizeof(*(v)))
81
+ # define JSON_SIZED_FREE_N(v, n) ruby_xfree_sized((void *)(v), sizeof(*(v)) * (n))
82
+
52
83
  #ifndef HAVE_RB_EXT_RACTOR_SAFE
53
84
  # undef RUBY_TYPED_FROZEN_SHAREABLE
54
85
  # define RUBY_TYPED_FROZEN_SHAREABLE 0
@@ -113,4 +144,36 @@ typedef unsigned char _Bool;
113
144
  #define JSON_CPU_LITTLE_ENDIAN_64BITS 0
114
145
  #endif
115
146
 
147
+ #ifdef JSON_TRUFFLERUBY_RB_CATCH_BUG
148
+
149
+ #undef RB_BLOCK_CALL_FUNC_ARGLIST
150
+ #define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, func_args) VALUE func_args
151
+
152
+ NORETURN(static inline) void json_rb_throw_obj(VALUE tag, VALUE obj)
153
+ {
154
+ VALUE exc = rb_exc_new_str(rb_eException, rb_utf8_str_new_cstr("throw_workaround"));
155
+ rb_ivar_set(exc, rb_intern("@throw_tag"), tag);
156
+ rb_ivar_set(exc, rb_intern("@throw_obj"), obj);
157
+ rb_exc_raise(exc);
158
+ }
159
+ #define rb_throw_obj json_rb_throw_obj
160
+
161
+ static inline VALUE json_rb_catch_obj(VALUE tag, VALUE (*func)(VALUE args), VALUE func_args)
162
+ {
163
+ int status;
164
+ VALUE result = rb_protect(func, func_args, &status);
165
+ if (status) {
166
+ VALUE exc = rb_errinfo();
167
+ if (tag == rb_ivar_get(exc, rb_intern("@throw_tag"))) {
168
+ rb_set_errinfo(Qnil);
169
+ return rb_ivar_get(exc, rb_intern("@throw_obj"));
170
+ }
171
+ rb_jump_tag(status);
172
+ }
173
+ return result;
174
+ }
175
+ #define rb_catch_obj json_rb_catch_obj
176
+
177
+ #endif // JSON_TRUFFLERUBY_RB_CATCH_BUG
178
+
116
179
  #endif // _JSON_H_
@@ -2,10 +2,43 @@
2
2
  require 'mkmf'
3
3
 
4
4
  $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
5
+
6
+ if RUBY_ENGINE == 'truffleruby' && RUBY_ENGINE_VERSION < '40.0'
7
+ # Ref: https://github.com/truffleruby/truffleruby/issues/4329
8
+ # Ref: https://github.com/truffleruby/truffleruby/pull/4333
9
+ $defs << "-DJSON_TRUFFLERUBY_RB_CATCH_BUG"
10
+ end
11
+
5
12
  have_func("rb_enc_interned_str", "ruby/encoding.h") # RUBY_VERSION >= 3.0
6
13
  have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0
7
14
  have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2
8
15
  have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby
16
+ have_func("ruby_xfree_sized", "ruby.h") # RUBY_VERSION >= 4.1
17
+
18
+ def have_builtin_func(name, check_expr, opt = "", &b)
19
+ checking_for checking_message(name.funcall_style, nil, opt) do
20
+ if try_compile(<<SRC, opt, &b)
21
+ int foo;
22
+ int main() { #{check_expr}; return 0; }
23
+ SRC
24
+ $defs.push(format("-DHAVE_BUILTIN_%s", name.tr_cpp))
25
+ true
26
+ else
27
+ false
28
+ end
29
+ end
30
+ end
31
+
32
+ have_builtin_func("__builtin_clzll", "__builtin_clzll(0)")
33
+
34
+ if have_header("x86intrin.h")
35
+ have_func("_lzcnt_u64", "x86intrin.h")
36
+ end
37
+
38
+ if have_header("intrin.h")
39
+ have_func("__lzcnt64", "intrin.h")
40
+ have_func("_BitScanReverse64", "intrin.h")
41
+ end
9
42
 
10
43
  if RUBY_ENGINE == "ruby"
11
44
  have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3