json 2.19.3 → 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 +17 -1
- 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 +52 -34
- 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,13 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
### Unreleased
|
|
4
4
|
|
|
5
|
+
### 2026-05-04 (2.19.5)
|
|
6
|
+
|
|
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
|
+
|
|
5
13
|
### 2026-03-25 (2.19.3)
|
|
6
14
|
|
|
7
15
|
* Fix handling of unescaped control characters preceeded by a backslash.
|
|
8
16
|
|
|
9
17
|
### 2026-03-18 (2.19.2)
|
|
10
18
|
|
|
11
|
-
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`.
|
|
19
|
+
* Fix a format string injection vulnerability in `JSON.parse(doc, allow_duplicate_key: false)`. `CVE-2026-33210`.
|
|
12
20
|
|
|
13
21
|
### 2026-03-08 (2.19.1)
|
|
14
22
|
|
|
@@ -28,6 +36,10 @@
|
|
|
28
36
|
|
|
29
37
|
* Add `:allow_control_characters` parser options, to allow JSON strings containing unescaped ASCII control characters (e.g. newlines).
|
|
30
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
|
+
|
|
31
43
|
### 2025-12-04 (2.17.1)
|
|
32
44
|
|
|
33
45
|
* Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
|
|
@@ -54,6 +66,10 @@
|
|
|
54
66
|
* Optimized numbers parsing using SWAR (thanks to Scott Myron).
|
|
55
67
|
* Optimized parsing of pretty printed documents using SWAR (thanks to Scott Myron).
|
|
56
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
|
+
|
|
57
73
|
### 2025-10-25 (2.15.2)
|
|
58
74
|
|
|
59
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
|
|
|
@@ -843,7 +856,7 @@ NOINLINE(static) VALUE json_decode_large_float(const char *start, long len)
|
|
|
843
856
|
/* Ruby JSON optimized float decoder using vendored Ryu algorithm
|
|
844
857
|
* Accepts pre-extracted mantissa and exponent from first-pass validation
|
|
845
858
|
*/
|
|
846
|
-
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,
|
|
847
860
|
const char *start, const char *end)
|
|
848
861
|
{
|
|
849
862
|
if (RB_UNLIKELY(config->decimal_class)) {
|
|
@@ -851,13 +864,21 @@ static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantis
|
|
|
851
864
|
return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text);
|
|
852
865
|
}
|
|
853
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
|
+
|
|
854
875
|
// Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
|
|
855
876
|
// Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
|
|
856
877
|
if (RB_UNLIKELY(mantissa_digits > 17 || mantissa_digits + exponent < -307)) {
|
|
857
878
|
return json_decode_large_float(start, end - start);
|
|
858
879
|
}
|
|
859
880
|
|
|
860
|
-
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));
|
|
861
882
|
}
|
|
862
883
|
|
|
863
884
|
static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
|
|
@@ -911,9 +932,6 @@ NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE d
|
|
|
911
932
|
cursor_position(state, &line, &column);
|
|
912
933
|
rb_str_concat(message, build_parse_error_message("", state, line, column)) ;
|
|
913
934
|
rb_exc_raise(parse_error_new(message, line, column));
|
|
914
|
-
|
|
915
|
-
raise_parse_error(RSTRING_PTR(message), state);
|
|
916
|
-
RB_GC_GUARD(message);
|
|
917
935
|
}
|
|
918
936
|
|
|
919
937
|
static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
|
|
@@ -928,7 +946,12 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi
|
|
|
928
946
|
case JSON_IGNORE:
|
|
929
947
|
break;
|
|
930
948
|
case JSON_DEPRECATED:
|
|
931
|
-
|
|
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
|
+
|
|
932
955
|
break;
|
|
933
956
|
case JSON_RAISE:
|
|
934
957
|
raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
|
|
@@ -950,7 +973,7 @@ static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *
|
|
|
950
973
|
if (RB_UNLIKELY(config->on_load_proc)) {
|
|
951
974
|
value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
|
|
952
975
|
}
|
|
953
|
-
rvalue_stack_push(state->stack, value,
|
|
976
|
+
rvalue_stack_push(state->stack, value, state->stack_handle, &state->stack);
|
|
954
977
|
return value;
|
|
955
978
|
}
|
|
956
979
|
|
|
@@ -1135,7 +1158,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
|
|
|
1135
1158
|
const char first_digit = *state->cursor;
|
|
1136
1159
|
|
|
1137
1160
|
// Variables for Ryu optimization - extract digits during parsing
|
|
1138
|
-
|
|
1161
|
+
int64_t exponent = 0;
|
|
1139
1162
|
int decimal_point_pos = -1;
|
|
1140
1163
|
uint64_t mantissa = 0;
|
|
1141
1164
|
|
|
@@ -1179,7 +1202,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
|
|
|
1179
1202
|
raise_parse_error_at("invalid number: %s", state, start);
|
|
1180
1203
|
}
|
|
1181
1204
|
|
|
1182
|
-
exponent = negative_exponent ? -
|
|
1205
|
+
exponent = negative_exponent ? -abs_exponent : abs_exponent;
|
|
1183
1206
|
}
|
|
1184
1207
|
|
|
1185
1208
|
if (integer) {
|
|
@@ -1560,11 +1583,13 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
|
|
|
1560
1583
|
const char *start;
|
|
1561
1584
|
RSTRING_GETMEM(Vsource, start, len);
|
|
1562
1585
|
|
|
1586
|
+
VALUE stack_handle = 0;
|
|
1563
1587
|
JSON_ParserState _state = {
|
|
1564
1588
|
.start = start,
|
|
1565
1589
|
.cursor = start,
|
|
1566
1590
|
.end = start + len,
|
|
1567
1591
|
.stack = &stack,
|
|
1592
|
+
.stack_handle = &stack_handle,
|
|
1568
1593
|
};
|
|
1569
1594
|
JSON_ParserState *state = &_state;
|
|
1570
1595
|
|
|
@@ -1572,8 +1597,8 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
|
|
|
1572
1597
|
|
|
1573
1598
|
// This may be skipped in case of exception, but
|
|
1574
1599
|
// it won't cause a leak.
|
|
1575
|
-
rvalue_stack_eagerly_release(
|
|
1576
|
-
|
|
1600
|
+
rvalue_stack_eagerly_release(stack_handle);
|
|
1601
|
+
RB_GC_GUARD(stack_handle);
|
|
1577
1602
|
json_ensure_eof(state);
|
|
1578
1603
|
|
|
1579
1604
|
return result;
|
|
@@ -1611,26 +1636,19 @@ static void JSON_ParserConfig_mark(void *ptr)
|
|
|
1611
1636
|
rb_gc_mark(config->decimal_class);
|
|
1612
1637
|
}
|
|
1613
1638
|
|
|
1614
|
-
static void JSON_ParserConfig_free(void *ptr)
|
|
1615
|
-
{
|
|
1616
|
-
JSON_ParserConfig *config = ptr;
|
|
1617
|
-
ruby_xfree(config);
|
|
1618
|
-
}
|
|
1619
|
-
|
|
1620
1639
|
static size_t JSON_ParserConfig_memsize(const void *ptr)
|
|
1621
1640
|
{
|
|
1622
1641
|
return sizeof(JSON_ParserConfig);
|
|
1623
1642
|
}
|
|
1624
1643
|
|
|
1625
1644
|
static const rb_data_type_t JSON_ParserConfig_type = {
|
|
1626
|
-
"JSON::Ext::Parser/ParserConfig",
|
|
1627
|
-
{
|
|
1645
|
+
.wrap_struct_name = "JSON::Ext::Parser/ParserConfig",
|
|
1646
|
+
.function = {
|
|
1628
1647
|
JSON_ParserConfig_mark,
|
|
1629
|
-
|
|
1648
|
+
RUBY_DEFAULT_FREE,
|
|
1630
1649
|
JSON_ParserConfig_memsize,
|
|
1631
1650
|
},
|
|
1632
|
-
|
|
1633
|
-
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,
|
|
1634
1652
|
};
|
|
1635
1653
|
|
|
1636
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: []
|