json 2.17.0 → 2.18.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: a35454680e80a622fb539155325b2f693e90b352aad3f24b7f9eafc5ca797963
4
- data.tar.gz: 9eee4f7ce5348a1eb44100766d5a7b326a4e76691fbfd3db8a2410020fb75ec1
3
+ metadata.gz: 51eab66896e862b679d424133f11e1367d5d8e71add943e67cf0673d0d562fcd
4
+ data.tar.gz: 7b69d4a42137897fe9a45bd60a21b759d133c112cb4ba16020099f27074ac2fd
5
5
  SHA512:
6
- metadata.gz: 0771fad39331fe9d47dbd855a02f662053a79ff08679c8bc76855dcfd3edbcdb32746cc0db435e6ea14815eacdbe97bf1152b704eacb7ddf1423917eb2545923
7
- data.tar.gz: 742dc87f4cc0306e613cfb65824aaee600aa53f0715135190ffaa4ca1f25aa6820a10b1860befcf90f3dcf6676bd5bb304f0e2858ec1e5933f66b089fca82e78
6
+ metadata.gz: ea3b026c8ccd6cb477858bf06f07f8b5adc5bcf7b52a175487c19dc2835ef63db2e4f87074a00ec2fe2c70e588c205f679116536da40f15e767f35351a52fc5c
7
+ data.tar.gz: f58144a5329ad95128e00bbc5670280f6a699e04cf05060bdfc7acaf112e62eb44c14c36328a9683d86e138c6eb2f3599f5ec35347867ac99ab9f0e16813c4df
data/CHANGES.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2025-12-11 (2.18.0)
6
+
7
+ * Add `:allow_control_characters` parser options, to allow JSON strings containing unescaped ASCII control characters (e.g. newlines).
8
+
9
+ ### 2025-12-04 (2.17.1)
10
+
11
+ * Fix a regression in parsing of unicode surogate pairs (`\uXX\uXX`) that could cause an invalid string to be returned.
12
+
5
13
  ### 2025-12-03 (2.17.0)
6
14
 
7
15
  * Improve `JSON.load` and `JSON.unsafe_load` to allow passing options as second argument.
@@ -7,7 +7,7 @@ static VALUE CNaN, CInfinity, CMinusInfinity;
7
7
 
8
8
  static ID i_new, i_try_convert, i_uminus, i_encode;
9
9
 
10
- static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze,
10
+ static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_control_characters, sym_symbolize_names, sym_freeze,
11
11
  sym_decimal_class, sym_on_load, sym_allow_duplicate_key;
12
12
 
13
13
  static int binary_encindex;
@@ -335,6 +335,7 @@ typedef struct JSON_ParserStruct {
335
335
  int max_nesting;
336
336
  bool allow_nan;
337
337
  bool allow_trailing_comma;
338
+ bool allow_control_characters;
338
339
  bool symbolize_names;
339
340
  bool freeze;
340
341
  } JSON_ParserConfig;
@@ -651,7 +652,9 @@ static inline const char *json_next_backslash(const char *pe, const char *string
651
652
  positions->size--;
652
653
  const char *next_position = positions->positions[0];
653
654
  positions->positions++;
654
- return next_position;
655
+ if (next_position >= pe) {
656
+ return next_position;
657
+ }
655
658
  }
656
659
 
657
660
  if (positions->has_more) {
@@ -750,9 +753,15 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser
750
753
  break;
751
754
  default:
752
755
  if ((unsigned char)*pe < 0x20) {
753
- raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
756
+ if (!config->allow_control_characters) {
757
+ if (*pe == '\n') {
758
+ raise_parse_error_at("Invalid unescaped newline character (\\n) in string: %s", state, pe - 1);
759
+ }
760
+ raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
761
+ }
762
+ } else {
763
+ raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
754
764
  }
755
- raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
756
765
  break;
757
766
  }
758
767
  }
@@ -1004,7 +1013,9 @@ static VALUE json_parse_escaped_string(JSON_ParserState *state, JSON_ParserConfi
1004
1013
  break;
1005
1014
  }
1006
1015
  default:
1007
- raise_parse_error("invalid ASCII control character in string: %s", state);
1016
+ if (!config->allow_control_characters) {
1017
+ raise_parse_error("invalid ASCII control character in string: %s", state);
1018
+ }
1008
1019
  break;
1009
1020
  }
1010
1021
 
@@ -1425,14 +1436,15 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1425
1436
  {
1426
1437
  JSON_ParserConfig *config = (JSON_ParserConfig *)data;
1427
1438
 
1428
- if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
1429
- else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
1430
- else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
1431
- else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
1432
- else if (key == sym_freeze) { config->freeze = RTEST(val); }
1433
- else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
1434
- else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
1435
- else if (key == sym_decimal_class) {
1439
+ if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
1440
+ else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
1441
+ else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
1442
+ else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); }
1443
+ else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
1444
+ else if (key == sym_freeze) { config->freeze = RTEST(val); }
1445
+ else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
1446
+ else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
1447
+ else if (key == sym_decimal_class) {
1436
1448
  if (RTEST(val)) {
1437
1449
  if (rb_respond_to(val, i_try_convert)) {
1438
1450
  config->decimal_class = val;
@@ -1645,6 +1657,7 @@ void Init_parser(void)
1645
1657
  sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
1646
1658
  sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1647
1659
  sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
1660
+ sym_allow_control_characters = ID2SYM(rb_intern("allow_control_characters"));
1648
1661
  sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
1649
1662
  sym_freeze = ID2SYM(rb_intern("freeze"));
1650
1663
  sym_on_load = ID2SYM(rb_intern("on_load"));
@@ -500,11 +500,6 @@ module JSON
500
500
 
501
501
  private
502
502
 
503
- def json_shift(state)
504
- state.object_nl.empty? or return ''
505
- state.indent * state.depth
506
- end
507
-
508
503
  def json_transform(state)
509
504
  depth = state.depth += 1
510
505
 
data/lib/json/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JSON
4
- VERSION = '2.17.0'
4
+ VERSION = '2.18.0'
5
5
  end
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.17.0
4
+ version: 2.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank