json 2.15.1 → 2.15.2.1

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: 981ed5b9d1d88ec48021ed8ab7757ab595dbb2bb5a16e9b3595dc4aae5c1f193
4
- data.tar.gz: 1fc86464fa02dead5539e47dc37c3dcb3d068707ee8d1e32c574893e1bb702de
3
+ metadata.gz: e0a73f62257d521165faeb372eafe66beb01fe47b4790256840f4316aa762510
4
+ data.tar.gz: 135d0b30fd72cd54b91b84050fe86a67b1aaf909f2024f5a545288cfbe3a2088
5
5
  SHA512:
6
- metadata.gz: c06d2e27a811c7b2368ed364f1fd72c0423922094ed29ec0de07a75db7aa53d3f2662aa80220f6d094fe39400603d2919b97308010fcc5c0efab86307089848b
7
- data.tar.gz: c032759c67a721b378518dd3c555e4e1c3f1ca34ff00f1bb21a2f136b626399efdd9c5a701aa018c3c9d5da050d0c110ee98e29853d4949db125f524fad1fdae
6
+ metadata.gz: d51c8d7de86d2581845d73638053da3f7c5aea014da4a960630fd78bba234647e37b301dec74f93069cc584d7f2495a394dc4a5d5514f543dee195413a863ebf
7
+ data.tar.gz: 3a871434b7427979f6c860e7ec33772ff61ddd0d272ac40de51fc887a14f50e65653d70b8276b2b535870a20801d7e6c2068b6f5bfb68293fc0e0de3a82aa729
data/CHANGES.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  ### Unreleased
4
4
 
5
+ ### 2026-03-18 (2.15.2.1)
6
+
7
+ * Fix a format string injection vulnerability in JSON.parse(doc, allow_duplicate_key: false).
8
+
9
+ ### 2025-10-25 (2.15.2)
10
+
11
+ * Fix `JSON::Coder` to have one dedicated depth counter per invocation.
12
+ After encountering a circular reference in `JSON::Coder#dump`, any further `#dump` call would raise `JSON::NestingError`.
13
+
5
14
  ### 2025-10-07 (2.15.1)
6
15
 
7
16
  * Fix incorrect escaping in the JRuby extension when encoding shared strings.
@@ -1124,7 +1124,7 @@ static inline long increase_depth(struct generate_json_data *data)
1124
1124
  JSON_Generator_State *state = data->state;
1125
1125
  long depth = ++state->depth;
1126
1126
  if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
1127
- rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
1127
+ rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --state->depth);
1128
1128
  }
1129
1129
  return depth;
1130
1130
  }
@@ -1491,10 +1491,39 @@ static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
1491
1491
  rb_check_arity(argc, 1, 2);
1492
1492
  VALUE obj = argv[0];
1493
1493
  VALUE io = argc > 1 ? argv[1] : Qnil;
1494
- VALUE result = cState_partial_generate(self, obj, generate_json, io);
1494
+ return cState_partial_generate(self, obj, generate_json, io);
1495
+ }
1496
+
1497
+ static VALUE cState_generate_new(int argc, VALUE *argv, VALUE self)
1498
+ {
1499
+ rb_check_arity(argc, 1, 2);
1500
+ VALUE obj = argv[0];
1501
+ VALUE io = argc > 1 ? argv[1] : Qnil;
1502
+
1495
1503
  GET_STATE(self);
1496
- (void)state;
1497
- return result;
1504
+
1505
+ JSON_Generator_State new_state;
1506
+ MEMCPY(&new_state, state, JSON_Generator_State, 1);
1507
+
1508
+ // FIXME: depth shouldn't be part of JSON_Generator_State, as that prevents it from being used concurrently.
1509
+ new_state.depth = 0;
1510
+
1511
+ char stack_buffer[FBUFFER_STACK_SIZE];
1512
+ FBuffer buffer = {
1513
+ .io = RTEST(io) ? io : Qfalse,
1514
+ };
1515
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
1516
+
1517
+ struct generate_json_data data = {
1518
+ .buffer = &buffer,
1519
+ .vstate = Qfalse,
1520
+ .state = &new_state,
1521
+ .obj = obj,
1522
+ .func = generate_json
1523
+ };
1524
+ rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
1525
+
1526
+ return fbuffer_finalize(&buffer);
1498
1527
  }
1499
1528
 
1500
1529
  static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
@@ -2072,7 +2101,7 @@ void Init_generator(void)
2072
2101
  rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
2073
2102
  rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
2074
2103
  rb_define_method(cState, "generate", cState_generate, -1);
2075
- rb_define_alias(cState, "generate_new", "generate"); // :nodoc:
2104
+ rb_define_method(cState, "generate_new", cState_generate_new, -1); // :nodoc:
2076
2105
 
2077
2106
  rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
2078
2107
 
@@ -428,14 +428,9 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state)
428
428
 
429
429
  #define PARSE_ERROR_FRAGMENT_LEN 32
430
430
 
431
- #ifdef RBIMPL_ATTR_NORETURN
432
- RBIMPL_ATTR_NORETURN()
433
- #endif
434
- static void raise_parse_error(const char *format, JSON_ParserState *state)
431
+ static VALUE build_parse_error_message(const char *format, JSON_ParserState *state, long line, long column)
435
432
  {
436
433
  unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3];
437
- long line, column;
438
- cursor_position(state, &line, &column);
439
434
 
440
435
  const char *ptr = "EOF";
441
436
  if (state->cursor && state->cursor < state->end) {
@@ -470,11 +465,23 @@ static void raise_parse_error(const char *format, JSON_ParserState *state)
470
465
  VALUE msg = rb_sprintf(format, ptr);
471
466
  VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column);
472
467
  RB_GC_GUARD(msg);
468
+ return message;
469
+ }
473
470
 
471
+ static VALUE parse_error_new(VALUE message, long line, long column)
472
+ {
474
473
  VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message);
475
474
  rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line));
476
475
  rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column));
477
- rb_exc_raise(exc);
476
+ return exc;
477
+ }
478
+
479
+ NORETURN(static) void raise_parse_error(const char *format, JSON_ParserState *state)
480
+ {
481
+ long line, column;
482
+ cursor_position(state, &line, &column);
483
+ VALUE message = build_parse_error_message(format, state, line, column);
484
+ rb_exc_raise(parse_error_new(message, line, column));
478
485
  }
479
486
 
480
487
  #ifdef RBIMPL_ATTR_NORETURN
@@ -875,6 +882,11 @@ static void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_k
875
882
  rb_inspect(duplicate_key)
876
883
  );
877
884
 
885
+ long line, column;
886
+ cursor_position(state, &line, &column);
887
+ rb_str_concat(message, build_parse_error_message("", state, line, column)) ;
888
+ rb_exc_raise(parse_error_new(message, line, column));
889
+
878
890
  raise_parse_error(RSTRING_PTR(message), state);
879
891
  RB_GC_GUARD(message);
880
892
  }
@@ -212,7 +212,7 @@ module JSON
212
212
  return if @max_nesting.zero?
213
213
  current_nesting = depth + 1
214
214
  current_nesting > @max_nesting and
215
- raise NestingError, "nesting of #{current_nesting} is too deep"
215
+ raise NestingError, "nesting of #{current_nesting} is too deep. Did you try to serialize objects with circular references?"
216
216
  end
217
217
 
218
218
  # Returns true, if circular data structures are checked,
@@ -347,6 +347,10 @@ module JSON
347
347
  dup.generate(obj, anIO)
348
348
  end
349
349
 
350
+ private def initialize_copy(_orig)
351
+ @depth = 0
352
+ end
353
+
350
354
  # Handles @allow_nan, @buffer_initial_length, other ivars must be the default value (see above)
351
355
  private def generate_json(obj, buf)
352
356
  case obj
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.15.1'
4
+ VERSION = '2.15.2.1'
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.15.1
4
+ version: 2.15.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  requirements: []
85
- rubygems_version: 3.6.9
85
+ rubygems_version: 4.0.3
86
86
  specification_version: 4
87
87
  summary: JSON Implementation for Ruby
88
88
  test_files: []