json 2.19.2 → 2.19.5
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 +22 -2
- data/ext/json/ext/generator/extconf.rb +2 -0
- data/ext/json/ext/generator/generator.c +25 -18
- data/ext/json/ext/json.h +11 -0
- data/ext/json/ext/parser/extconf.rb +4 -0
- data/ext/json/ext/parser/parser.c +55 -35
- data/lib/json/truffle_ruby/generator.rb +8 -8
- data/lib/json/version.rb +1 -1
- data/lib/json.rb +2 -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: 0bbb85e1521c171ca73ab935cc00899ff3eb7086921a64542a3937fa9589848d
|
|
4
|
+
data.tar.gz: 328853f7f164d91522d6791a51cca5ccb3ae418410752a3fb72189bc14c157d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 326b0621e562eebc66f155cee358ca295dde7584e7f60268a354da3e8a1a02e13bfcd9fef7f9b2f9f2ea196987b07bb9e50578347231f14d9fb0e863ac9445ac
|
|
7
|
+
data.tar.gz: 0e9e2ab4c91b5544ac8440613a0fd63aab2f7b7ce5a39f41e786af736e80ca28de8d3388057134dde05ba53f4f150d24aa1a8cde92dac82abbb4104740409631
|
data/CHANGES.md
CHANGED
|
@@ -2,9 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
-
### 2026-
|
|
5
|
+
### 2026-05-04 (2.19.5)
|
|
6
6
|
|
|
7
|
-
*
|
|
7
|
+
* Cap the parser to emit a maximum of 5 deprecation warnings per document. Emitting more is not helpful.
|
|
8
|
+
|
|
9
|
+
### 2026-04-19 (2.19.4)
|
|
10
|
+
|
|
11
|
+
* Fix parsing of out of range floats (very large exponents that lead to either `0.0` or `Inf`).
|
|
12
|
+
|
|
13
|
+
### 2026-03-25 (2.19.3)
|
|
14
|
+
|
|
15
|
+
* Fix handling of unescaped control characters preceeded by a backslash.
|
|
16
|
+
|
|
17
|
+
### 2026-03-18 (2.19.2)
|
|
18
|
+
|
|
19
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
8
20
|
|
|
9
21
|
### 2026-03-08 (2.19.1)
|
|
10
22
|
|
|
@@ -24,6 +36,10 @@
|
|
|
24
36
|
|
|
25
37
|
* Add `:allow_control_characters` parser options, to allow JSON strings containing unescaped ASCII control characters (e.g. newlines).
|
|
26
38
|
|
|
39
|
+
### 2026-03-18 (2.17.1.2) - Security Backport
|
|
40
|
+
|
|
41
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
42
|
+
|
|
27
43
|
### 2025-12-04 (2.17.1)
|
|
28
44
|
|
|
29
45
|
* Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
|
|
@@ -50,6 +66,10 @@
|
|
|
50
66
|
* Optimized numbers parsing using SWAR (thanks to Scott Myron).
|
|
51
67
|
* Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
|
|
52
68
|
|
|
69
|
+
### 2026-03-18 (2.15.2.1) - Security Backport
|
|
70
|
+
|
|
71
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
72
|
+
|
|
53
73
|
### 2025-10-25 (2.15.2)
|
|
54
74
|
|
|
55
75
|
* Fix `JSON::Coder` to have one dedicated depth counter per invocation.
|
|
@@ -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
|
|
|
@@ -722,27 +722,20 @@ static void State_compact(void *ptr)
|
|
|
722
722
|
state->as_json = rb_gc_location(state->as_json);
|
|
723
723
|
}
|
|
724
724
|
|
|
725
|
-
static void State_free(void *ptr)
|
|
726
|
-
{
|
|
727
|
-
JSON_Generator_State *state = ptr;
|
|
728
|
-
ruby_xfree(state);
|
|
729
|
-
}
|
|
730
|
-
|
|
731
725
|
static size_t State_memsize(const void *ptr)
|
|
732
726
|
{
|
|
733
727
|
return sizeof(JSON_Generator_State);
|
|
734
728
|
}
|
|
735
729
|
|
|
736
730
|
static const rb_data_type_t JSON_Generator_State_type = {
|
|
737
|
-
"JSON/Generator/State",
|
|
738
|
-
{
|
|
731
|
+
.wrap_struct_name = "JSON/Generator/State",
|
|
732
|
+
.function = {
|
|
739
733
|
.dmark = State_mark,
|
|
740
|
-
.dfree =
|
|
734
|
+
.dfree = RUBY_DEFAULT_FREE,
|
|
741
735
|
.dsize = State_memsize,
|
|
742
736
|
.dcompact = State_compact,
|
|
743
737
|
},
|
|
744
|
-
|
|
745
|
-
RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
738
|
+
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
|
|
746
739
|
};
|
|
747
740
|
|
|
748
741
|
static void state_init(JSON_Generator_State *state)
|
|
@@ -826,9 +819,17 @@ static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
|
|
|
826
819
|
return Qundef;
|
|
827
820
|
}
|
|
828
821
|
|
|
822
|
+
static inline int json_str_coderange(VALUE str) {
|
|
823
|
+
int coderange = RB_ENC_CODERANGE(str);
|
|
824
|
+
if (coderange == RUBY_ENC_CODERANGE_UNKNOWN) {
|
|
825
|
+
coderange = rb_enc_str_coderange(str);
|
|
826
|
+
}
|
|
827
|
+
return coderange;
|
|
828
|
+
}
|
|
829
|
+
|
|
829
830
|
static inline bool valid_json_string_p(VALUE str)
|
|
830
831
|
{
|
|
831
|
-
int coderange =
|
|
832
|
+
int coderange = json_str_coderange(str);
|
|
832
833
|
|
|
833
834
|
if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
|
|
834
835
|
return true;
|
|
@@ -841,12 +842,8 @@ static inline bool valid_json_string_p(VALUE str)
|
|
|
841
842
|
return false;
|
|
842
843
|
}
|
|
843
844
|
|
|
844
|
-
static
|
|
845
|
+
NOINLINE(static) VALUE convert_invalid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
845
846
|
{
|
|
846
|
-
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
847
|
-
return str;
|
|
848
|
-
}
|
|
849
|
-
|
|
850
847
|
if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
|
|
851
848
|
VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
|
|
852
849
|
if (coerced_str != str) {
|
|
@@ -882,6 +879,16 @@ static inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE
|
|
|
882
879
|
return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
|
|
883
880
|
}
|
|
884
881
|
|
|
882
|
+
ALWAYS_INLINE(static) VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
|
|
883
|
+
{
|
|
884
|
+
if (RB_LIKELY(valid_json_string_p(str))) {
|
|
885
|
+
return str;
|
|
886
|
+
}
|
|
887
|
+
else {
|
|
888
|
+
return convert_invalid_encoding(data, str, as_json_called, is_key);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
|
|
885
892
|
static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
|
|
886
893
|
{
|
|
887
894
|
fbuffer_append_char(buffer, '"');
|
|
@@ -900,7 +907,7 @@ static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data
|
|
|
900
907
|
search.chunk_end = NULL;
|
|
901
908
|
#endif /* HAVE_SIMD */
|
|
902
909
|
|
|
903
|
-
switch (
|
|
910
|
+
switch (json_str_coderange(obj)) {
|
|
904
911
|
case ENC_CODERANGE_7BIT:
|
|
905
912
|
case ENC_CODERANGE_VALID:
|
|
906
913
|
if (RB_UNLIKELY(data->state->ascii_only)) {
|
data/ext/json/ext/json.h
CHANGED
|
@@ -54,6 +54,17 @@ typedef unsigned char _Bool;
|
|
|
54
54
|
# define RUBY_TYPED_FROZEN_SHAREABLE 0
|
|
55
55
|
#endif
|
|
56
56
|
|
|
57
|
+
#ifdef RUBY_TYPED_EMBEDDABLE
|
|
58
|
+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
|
|
59
|
+
#else
|
|
60
|
+
# ifdef HAVE_CONST_RUBY_TYPED_EMBEDDABLE
|
|
61
|
+
# define RUBY_TYPED_EMBEDDABLE RUBY_TYPED_EMBEDDABLE
|
|
62
|
+
# define HAVE_RUBY_TYPED_EMBEDDABLE 1
|
|
63
|
+
# else
|
|
64
|
+
# define RUBY_TYPED_EMBEDDABLE 0
|
|
65
|
+
# endif
|
|
66
|
+
#endif
|
|
67
|
+
|
|
57
68
|
#ifndef NORETURN
|
|
58
69
|
#if defined(__has_attribute) && __has_attribute(noreturn)
|
|
59
70
|
#define NORETURN(x) __attribute__((noreturn)) x
|
|
@@ -7,6 +7,10 @@ have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0
|
|
|
7
7
|
have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2
|
|
8
8
|
have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby
|
|
9
9
|
|
|
10
|
+
if RUBY_ENGINE == "ruby"
|
|
11
|
+
have_const("RUBY_TYPED_EMBEDDABLE", "ruby.h") # RUBY_VERSION >= 3.3
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
append_cflags("-std=c99")
|
|
11
15
|
|
|
12
16
|
if enable_config('parser-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
|
|
@@ -241,17 +241,27 @@ static void rvalue_stack_mark(void *ptr)
|
|
|
241
241
|
{
|
|
242
242
|
rvalue_stack *stack = (rvalue_stack *)ptr;
|
|
243
243
|
long index;
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
if (stack && stack->ptr) {
|
|
245
|
+
for (index = 0; index < stack->head; index++) {
|
|
246
|
+
rb_gc_mark(stack->ptr[index]);
|
|
247
|
+
}
|
|
246
248
|
}
|
|
247
249
|
}
|
|
248
250
|
|
|
251
|
+
static void rvalue_stack_free_buffer(rvalue_stack *stack)
|
|
252
|
+
{
|
|
253
|
+
ruby_xfree(stack->ptr);
|
|
254
|
+
stack->ptr = NULL;
|
|
255
|
+
}
|
|
256
|
+
|
|
249
257
|
static void rvalue_stack_free(void *ptr)
|
|
250
258
|
{
|
|
251
259
|
rvalue_stack *stack = (rvalue_stack *)ptr;
|
|
252
260
|
if (stack) {
|
|
253
|
-
|
|
261
|
+
rvalue_stack_free_buffer(stack);
|
|
262
|
+
#ifndef HAVE_RUBY_TYPED_EMBEDDABLE
|
|
254
263
|
ruby_xfree(stack);
|
|
264
|
+
#endif
|
|
255
265
|
}
|
|
256
266
|
}
|
|
257
267
|
|
|
@@ -262,14 +272,13 @@ static size_t rvalue_stack_memsize(const void *ptr)
|
|
|
262
272
|
}
|
|
263
273
|
|
|
264
274
|
static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
|
|
265
|
-
"JSON::Ext::Parser/rvalue_stack",
|
|
266
|
-
{
|
|
275
|
+
.wrap_struct_name = "JSON::Ext::Parser/rvalue_stack",
|
|
276
|
+
.function = {
|
|
267
277
|
.dmark = rvalue_stack_mark,
|
|
268
278
|
.dfree = rvalue_stack_free,
|
|
269
279
|
.dsize = rvalue_stack_memsize,
|
|
270
280
|
},
|
|
271
|
-
|
|
272
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
|
281
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
|
|
273
282
|
};
|
|
274
283
|
|
|
275
284
|
static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
|
|
@@ -291,8 +300,12 @@ static void rvalue_stack_eagerly_release(VALUE handle)
|
|
|
291
300
|
if (handle) {
|
|
292
301
|
rvalue_stack *stack;
|
|
293
302
|
TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
|
|
294
|
-
|
|
303
|
+
#ifdef HAVE_RUBY_TYPED_EMBEDDABLE
|
|
304
|
+
rvalue_stack_free_buffer(stack);
|
|
305
|
+
#else
|
|
295
306
|
rvalue_stack_free(stack);
|
|
307
|
+
RTYPEDDATA_DATA(handle) = NULL;
|
|
308
|
+
#endif
|
|
296
309
|
}
|
|
297
310
|
}
|
|
298
311
|
|
|
@@ -343,7 +356,7 @@ typedef struct JSON_ParserStruct {
|
|
|
343
356
|
} JSON_ParserConfig;
|
|
344
357
|
|
|
345
358
|
typedef struct JSON_ParserStateStruct {
|
|
346
|
-
VALUE stack_handle;
|
|
359
|
+
VALUE *stack_handle;
|
|
347
360
|
const char *start;
|
|
348
361
|
const char *cursor;
|
|
349
362
|
const char *end;
|
|
@@ -351,6 +364,7 @@ typedef struct JSON_ParserStateStruct {
|
|
|
351
364
|
rvalue_cache name_cache;
|
|
352
365
|
int in_array;
|
|
353
366
|
int current_nesting;
|
|
367
|
+
unsigned int emitted_deprecations;
|
|
354
368
|
} JSON_ParserState;
|
|
355
369
|
|
|
356
370
|
static inline size_t rest(JSON_ParserState *state) {
|
|
@@ -436,9 +450,8 @@ static VALUE build_parse_error_message(const char *format, JSON_ParserState *sta
|
|
|
436
450
|
}
|
|
437
451
|
}
|
|
438
452
|
|
|
439
|
-
VALUE
|
|
440
|
-
|
|
441
|
-
RB_GC_GUARD(msg);
|
|
453
|
+
VALUE message = rb_enc_sprintf(enc_utf8, format, ptr);
|
|
454
|
+
rb_str_catf(message, " at line %ld column %ld", line, column);
|
|
442
455
|
return message;
|
|
443
456
|
}
|
|
444
457
|
|
|
@@ -758,7 +771,9 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser
|
|
|
758
771
|
}
|
|
759
772
|
raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
|
|
760
773
|
}
|
|
761
|
-
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (config->allow_invalid_escape) {
|
|
762
777
|
APPEND_CHAR(*pe);
|
|
763
778
|
} else {
|
|
764
779
|
raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
|
|
@@ -841,7 +856,7 @@ NOINLINE(static) VALUE json_decode_large_float(const char *start, long len)
|
|
|
841
856
|
/* Ruby JSON optimized float decoder using vendored Ryu algorithm
|
|
842
857
|
* Accepts pre-extracted mantissa and exponent from first-pass validation
|
|
843
858
|
*/
|
|
844
|
-
static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits,
|
|
859
|
+
static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits, int64_t exponent, bool negative,
|
|
845
860
|
const char *start, const char *end)
|
|
846
861
|
{
|
|
847
862
|
if (RB_UNLIKELY(config->decimal_class)) {
|
|
@@ -849,13 +864,21 @@ static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantis
|
|
|
849
864
|
return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text);
|
|
850
865
|
}
|
|
851
866
|
|
|
867
|
+
if (RB_UNLIKELY(exponent > INT32_MAX)) {
|
|
868
|
+
return negative ? CMinusInfinity : CInfinity;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
if (RB_UNLIKELY(exponent < INT32_MIN)) {
|
|
872
|
+
return rb_float_new(negative ? -0.0 : 0.0);
|
|
873
|
+
}
|
|
874
|
+
|
|
852
875
|
// Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
|
|
853
876
|
// Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
|
|
854
877
|
if (RB_UNLIKELY(mantissa_digits > 17 || mantissa_digits + exponent < -307)) {
|
|
855
878
|
return json_decode_large_float(start, end - start);
|
|
856
879
|
}
|
|
857
880
|
|
|
858
|
-
return DBL2NUM(ryu_s2d_from_parts(mantissa, mantissa_digits, exponent, negative));
|
|
881
|
+
return DBL2NUM(ryu_s2d_from_parts(mantissa, mantissa_digits, (int32_t)exponent, negative));
|
|
859
882
|
}
|
|
860
883
|
|
|
861
884
|
static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
|
|
@@ -909,9 +932,6 @@ NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE d
|
|
|
909
932
|
cursor_position(state, &line, &column);
|
|
910
933
|
rb_str_concat(message, build_parse_error_message("", state, line, column)) ;
|
|
911
934
|
rb_exc_raise(parse_error_new(message, line, column));
|
|
912
|
-
|
|
913
|
-
raise_parse_error(RSTRING_PTR(message), state);
|
|
914
|
-
RB_GC_GUARD(message);
|
|
915
935
|
}
|
|
916
936
|
|
|
917
937
|
static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
|
|
@@ -926,7 +946,12 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi
|
|
|
926
946
|
case JSON_IGNORE:
|
|
927
947
|
break;
|
|
928
948
|
case JSON_DEPRECATED:
|
|
929
|
-
|
|
949
|
+
// Only emit the first few deprecations to avoid spamming.
|
|
950
|
+
if (state->emitted_deprecations < 5) {
|
|
951
|
+
emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
|
|
952
|
+
state->emitted_deprecations++;
|
|
953
|
+
}
|
|
954
|
+
|
|
930
955
|
break;
|
|
931
956
|
case JSON_RAISE:
|
|
932
957
|
raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
|
|
@@ -948,7 +973,7 @@ static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *
|
|
|
948
973
|
if (RB_UNLIKELY(config->on_load_proc)) {
|
|
949
974
|
value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
|
|
950
975
|
}
|
|
951
|
-
rvalue_stack_push(state->stack, value,
|
|
976
|
+
rvalue_stack_push(state->stack, value, state->stack_handle, &state->stack);
|
|
952
977
|
return value;
|
|
953
978
|
}
|
|
954
979
|
|
|
@@ -1133,7 +1158,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
|
|
|
1133
1158
|
const char first_digit = *state->cursor;
|
|
1134
1159
|
|
|
1135
1160
|
// Variables for Ryu optimization - extract digits during parsing
|
|
1136
|
-
|
|
1161
|
+
int64_t exponent = 0;
|
|
1137
1162
|
int decimal_point_pos = -1;
|
|
1138
1163
|
uint64_t mantissa = 0;
|
|
1139
1164
|
|
|
@@ -1177,7 +1202,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
|
|
|
1177
1202
|
raise_parse_error_at("invalid number: %s", state, start);
|
|
1178
1203
|
}
|
|
1179
1204
|
|
|
1180
|
-
exponent = negative_exponent ? -
|
|
1205
|
+
exponent = negative_exponent ? -abs_exponent : abs_exponent;
|
|
1181
1206
|
}
|
|
1182
1207
|
|
|
1183
1208
|
if (integer) {
|
|
@@ -1558,11 +1583,13 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
|
|
|
1558
1583
|
const char *start;
|
|
1559
1584
|
RSTRING_GETMEM(Vsource, start, len);
|
|
1560
1585
|
|
|
1586
|
+
VALUE stack_handle = 0;
|
|
1561
1587
|
JSON_ParserState _state = {
|
|
1562
1588
|
.start = start,
|
|
1563
1589
|
.cursor = start,
|
|
1564
1590
|
.end = start + len,
|
|
1565
1591
|
.stack = &stack,
|
|
1592
|
+
.stack_handle = &stack_handle,
|
|
1566
1593
|
};
|
|
1567
1594
|
JSON_ParserState *state = &_state;
|
|
1568
1595
|
|
|
@@ -1570,8 +1597,8 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
|
|
|
1570
1597
|
|
|
1571
1598
|
// This may be skipped in case of exception, but
|
|
1572
1599
|
// it won't cause a leak.
|
|
1573
|
-
rvalue_stack_eagerly_release(
|
|
1574
|
-
|
|
1600
|
+
rvalue_stack_eagerly_release(stack_handle);
|
|
1601
|
+
RB_GC_GUARD(stack_handle);
|
|
1575
1602
|
json_ensure_eof(state);
|
|
1576
1603
|
|
|
1577
1604
|
return result;
|
|
@@ -1609,26 +1636,19 @@ static void JSON_ParserConfig_mark(void *ptr)
|
|
|
1609
1636
|
rb_gc_mark(config->decimal_class);
|
|
1610
1637
|
}
|
|
1611
1638
|
|
|
1612
|
-
static void JSON_ParserConfig_free(void *ptr)
|
|
1613
|
-
{
|
|
1614
|
-
JSON_ParserConfig *config = ptr;
|
|
1615
|
-
ruby_xfree(config);
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
1639
|
static size_t JSON_ParserConfig_memsize(const void *ptr)
|
|
1619
1640
|
{
|
|
1620
1641
|
return sizeof(JSON_ParserConfig);
|
|
1621
1642
|
}
|
|
1622
1643
|
|
|
1623
1644
|
static const rb_data_type_t JSON_ParserConfig_type = {
|
|
1624
|
-
"JSON::Ext::Parser/ParserConfig",
|
|
1625
|
-
{
|
|
1645
|
+
.wrap_struct_name = "JSON::Ext::Parser/ParserConfig",
|
|
1646
|
+
.function = {
|
|
1626
1647
|
JSON_ParserConfig_mark,
|
|
1627
|
-
|
|
1648
|
+
RUBY_DEFAULT_FREE,
|
|
1628
1649
|
JSON_ParserConfig_memsize,
|
|
1629
1650
|
},
|
|
1630
|
-
|
|
1631
|
-
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
|
|
1651
|
+
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
|
|
1632
1652
|
};
|
|
1633
1653
|
|
|
1634
1654
|
static VALUE cJSON_parser_s_allocate(VALUE klass)
|
|
@@ -48,7 +48,7 @@ module JSON
|
|
|
48
48
|
SCRIPT_SAFE_ESCAPE_PATTERN = /[\/"\\\x0-\x1f\u2028-\u2029]/
|
|
49
49
|
|
|
50
50
|
def self.native_type?(value) # :nodoc:
|
|
51
|
-
(false == value || true == value || nil == value || String === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
|
|
51
|
+
(false == value || true == value || nil == value || String === value || Symbol === value || Array === value || Hash === value || Integer === value || Float === value || Fragment === value)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def self.native_key?(key) # :nodoc:
|
|
@@ -517,11 +517,11 @@ module JSON
|
|
|
517
517
|
|
|
518
518
|
if empty?
|
|
519
519
|
state.depth -= 1
|
|
520
|
-
return '{}'
|
|
520
|
+
return +'{}'
|
|
521
521
|
end
|
|
522
522
|
|
|
523
523
|
delim = ",#{state.object_nl}"
|
|
524
|
-
result =
|
|
524
|
+
result = "{#{state.object_nl}"
|
|
525
525
|
first = true
|
|
526
526
|
key_type = nil
|
|
527
527
|
indent = !state.object_nl.empty?
|
|
@@ -558,7 +558,7 @@ module JSON
|
|
|
558
558
|
raise TypeError, "#{key.class}#to_s returns an instance of #{key_str.class}, expected a String"
|
|
559
559
|
end
|
|
560
560
|
|
|
561
|
-
result =
|
|
561
|
+
result = "#{result}#{key_json}#{state.space_before}:#{state.space}"
|
|
562
562
|
if state.strict? && !Generator.native_type?(value)
|
|
563
563
|
if state.as_json
|
|
564
564
|
value = state.as_json.call(value, false)
|
|
@@ -609,7 +609,7 @@ module JSON
|
|
|
609
609
|
|
|
610
610
|
if empty?
|
|
611
611
|
state.depth -= 1
|
|
612
|
-
return '[]'
|
|
612
|
+
return +'[]'
|
|
613
613
|
end
|
|
614
614
|
|
|
615
615
|
result = '['.dup
|
|
@@ -734,17 +734,17 @@ module JSON
|
|
|
734
734
|
|
|
735
735
|
module TrueClass
|
|
736
736
|
# Returns a JSON string for true: 'true'.
|
|
737
|
-
def to_json(*) 'true' end
|
|
737
|
+
def to_json(*) +'true' end
|
|
738
738
|
end
|
|
739
739
|
|
|
740
740
|
module FalseClass
|
|
741
741
|
# Returns a JSON string for false: 'false'.
|
|
742
|
-
def to_json(*) 'false' end
|
|
742
|
+
def to_json(*) +'false' end
|
|
743
743
|
end
|
|
744
744
|
|
|
745
745
|
module NilClass
|
|
746
746
|
# Returns a JSON string for nil: 'null'.
|
|
747
|
-
def to_json(*) 'null' end
|
|
747
|
+
def to_json(*) +'null' end
|
|
748
748
|
end
|
|
749
749
|
end
|
|
750
750
|
end
|
data/lib/json/version.rb
CHANGED
data/lib/json.rb
CHANGED
|
@@ -335,8 +335,8 @@ require 'json/common'
|
|
|
335
335
|
# JSON.generate(JSON::MinusInfinity)
|
|
336
336
|
#
|
|
337
337
|
# Allow:
|
|
338
|
-
# ruby = [Float::
|
|
339
|
-
# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,-Infinity]'
|
|
338
|
+
# ruby = [Float::NAN, Float::INFINITY, JSON::NaN, JSON::Infinity, JSON::MinusInfinity]
|
|
339
|
+
# JSON.generate(ruby, allow_nan: true) # => '[NaN,Infinity,NaN,Infinity,-Infinity]'
|
|
340
340
|
#
|
|
341
341
|
# ---
|
|
342
342
|
#
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: json
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.19.
|
|
4
|
+
version: 2.19.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Florian Frank
|
|
@@ -84,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
84
84
|
- !ruby/object:Gem::Version
|
|
85
85
|
version: '0'
|
|
86
86
|
requirements: []
|
|
87
|
-
rubygems_version: 4.0.
|
|
87
|
+
rubygems_version: 4.0.6
|
|
88
88
|
specification_version: 4
|
|
89
89
|
summary: JSON Implementation for Ruby
|
|
90
90
|
test_files: []
|