json 2.19.6 → 2.19.7

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: d2f786d8fccfe7906f9ec68f2a8f1cb9b4fb458029b46e3bba7904a6e22e443f
4
- data.tar.gz: 3fe8d97828cc573a98f4a0ccd88c2dc1fb008437dc115a1cd4d631b7a16f9df1
3
+ metadata.gz: 579bc938143b2fc703d90623fb985af883a7b46f0641d874cc44a39a4ffae2dd
4
+ data.tar.gz: f69a8d12a9f83378e0e0e6b0abdda34cf23d7ebf026dcc114dc70089dd159190
5
5
  SHA512:
6
- metadata.gz: 6a39aec470a7ec7da944a8361ea219352f1216b3a4c4b2de7dd35fc87d4c791286f63b7744349ca4da607c37e53b1fecf450e62ef6cd02d0147eba0fb1edf5c2
7
- data.tar.gz: 8cd952ae28ad7bc52f92ce49cd5cc6411835e3801a2c5cfc4a4b6d503a4bdb3dea3d726a4c4b2f7a75f0d3ec68f2d948bec52588cda37669c7d80ced0d527bb8
6
+ metadata.gz: 3bb0a35502ac84a22a71f076a68feb5ea525ff802491e2532bd863653d1b6808de4715108886e6bb00cc5ef378ec298bea81e2d932a748886f1f4ec8b0637b03
7
+ data.tar.gz: e50b9b31f846e105a725807db54fe86f8176331d975ea772a1f9f666ed91e4555497f79008a4b01b08de3c2605cb1867671f87b86f196632b05d1f5a21872143
data/CHANGES.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2026-05-28 (2.19.7)
6
+
7
+ * Fix some more edge cases with out of range floats.
8
+ * Ensure the string provided to `JSON.parse` can't be mutated during parsing.
9
+ * Add missing write barriers in `State#dup`.
10
+ * Further validate generator `depth` config.
11
+
5
12
  ### 2026-05-28 (2.19.6)
6
13
 
7
14
  * Cleanly handle overly large `depth` generator argument.
@@ -1367,12 +1367,14 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
1367
1367
  if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
1368
1368
 
1369
1369
  MEMCPY(objState, origState, JSON_Generator_State, 1);
1370
- objState->indent = origState->indent;
1371
- objState->space = origState->space;
1372
- objState->space_before = origState->space_before;
1373
- objState->object_nl = origState->object_nl;
1374
- objState->array_nl = origState->array_nl;
1375
- objState->as_json = origState->as_json;
1370
+
1371
+ RB_OBJ_WRITTEN(obj, Qundef, objState->indent);
1372
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space);
1373
+ RB_OBJ_WRITTEN(obj, Qundef, objState->space_before);
1374
+ RB_OBJ_WRITTEN(obj, Qundef, objState->object_nl);
1375
+ RB_OBJ_WRITTEN(obj, Qundef, objState->array_nl);
1376
+ RB_OBJ_WRITTEN(obj, Qundef, objState->as_json);
1377
+
1376
1378
  return obj;
1377
1379
  }
1378
1380
 
@@ -1590,6 +1592,9 @@ static long depth_config(VALUE num)
1590
1592
  if (RB_UNLIKELY(d < 0)) {
1591
1593
  rb_raise(rb_eArgError, "depth must be >= 0 (got %ld)", d);
1592
1594
  }
1595
+ if (RB_UNLIKELY(d > INT_MAX)) {
1596
+ rb_raise(rb_eArgError, "depth is too large (got %ld)", d);
1597
+ }
1593
1598
  return d;
1594
1599
  }
1595
1600
 
@@ -1202,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
1202
1202
  raise_parse_error_at("invalid number: %s", state, start);
1203
1203
  }
1204
1204
 
1205
- exponent = negative_exponent ? -abs_exponent : abs_exponent;
1205
+ if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) {
1206
+ exponent = negative_exponent ? INT64_MIN : INT64_MAX;
1207
+ } else {
1208
+ exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent;
1209
+ }
1206
1210
  }
1207
1211
 
1208
1212
  if (integer) {
@@ -1457,18 +1461,21 @@ static void json_ensure_eof(JSON_ParserState *state)
1457
1461
 
1458
1462
  static VALUE convert_encoding(VALUE source)
1459
1463
  {
1460
- int encindex = RB_ENCODING_GET(source);
1464
+ StringValue(source);
1465
+ int encindex = RB_ENCODING_GET(source);
1461
1466
 
1462
- if (RB_LIKELY(encindex == utf8_encindex)) {
1463
- return source;
1464
- }
1467
+ if (RB_LIKELY(encindex == utf8_encindex)) {
1468
+ return source;
1469
+ }
1465
1470
 
1466
- if (encindex == binary_encindex) {
1467
- // For historical reason, we silently reinterpret binary strings as UTF-8
1468
- return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
1469
- }
1471
+ if (encindex == binary_encindex) {
1472
+ // For historical reason, we silently reinterpret binary strings as UTF-8
1473
+ return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
1474
+ }
1470
1475
 
1471
- return rb_funcall(source, i_encode, 1, Encoding_UTF_8);
1476
+ source = rb_funcall(source, i_encode, 1, Encoding_UTF_8);
1477
+ StringValue(source);
1478
+ return source;
1472
1479
  }
1473
1480
 
1474
1481
  struct parser_config_init_args {
@@ -1583,10 +1590,16 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
1583
1590
  return self;
1584
1591
  }
1585
1592
 
1586
- static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1593
+ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src)
1587
1594
  {
1588
- Vsource = convert_encoding(StringValue(Vsource));
1589
- StringValue(Vsource);
1595
+ VALUE Vsource = convert_encoding(src);
1596
+
1597
+ // Ensure the string isn't mutated under us.
1598
+ // The classic API to use is `rb_str_locktmp`, but then we'd
1599
+ // need to use `rb_protect` to make sure we always unlock.
1600
+ if (Vsource == src) {
1601
+ Vsource = rb_str_new_frozen(Vsource);
1602
+ }
1590
1603
 
1591
1604
  VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
1592
1605
  rvalue_stack stack = {
@@ -1597,6 +1610,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1597
1610
 
1598
1611
  long len;
1599
1612
  const char *start;
1613
+
1600
1614
  RSTRING_GETMEM(Vsource, start, len);
1601
1615
 
1602
1616
  VALUE stack_handle = 0;
@@ -1615,6 +1629,7 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1615
1629
  // it won't cause a leak.
1616
1630
  rvalue_stack_eagerly_release(stack_handle);
1617
1631
  RB_GC_GUARD(stack_handle);
1632
+ RB_GC_GUARD(Vsource);
1618
1633
  json_ensure_eof(state);
1619
1634
 
1620
1635
  return result;
@@ -1635,9 +1650,6 @@ static VALUE cParserConfig_parse(VALUE self, VALUE Vsource)
1635
1650
 
1636
1651
  static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
1637
1652
  {
1638
- Vsource = convert_encoding(StringValue(Vsource));
1639
- StringValue(Vsource);
1640
-
1641
1653
  JSON_ParserConfig _config = {0};
1642
1654
  JSON_ParserConfig *config = &_config;
1643
1655
  parser_config_init(config, opts, false);
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.19.6'
4
+ VERSION = '2.19.7'
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.19.6
4
+ version: 2.19.7
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.10
87
+ rubygems_version: 4.0.12
88
88
  specification_version: 4
89
89
  summary: JSON Implementation for Ruby
90
90
  test_files: []