json 2.18.1 → 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.
@@ -7,8 +7,9 @@ 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_allow_control_characters, sym_symbolize_names, sym_freeze,
11
- sym_decimal_class, sym_on_load, sym_allow_duplicate_key;
10
+ static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_control_characters,
11
+ sym_allow_invalid_escape, sym_symbolize_names, sym_freeze, sym_decimal_class, sym_on_load,
12
+ sym_allow_duplicate_key;
12
13
 
13
14
  static int binary_encindex;
14
15
  static int utf8_encindex;
@@ -240,17 +241,27 @@ static void rvalue_stack_mark(void *ptr)
240
241
  {
241
242
  rvalue_stack *stack = (rvalue_stack *)ptr;
242
243
  long index;
243
- for (index = 0; index < stack->head; index++) {
244
- rb_gc_mark(stack->ptr[index]);
244
+ if (stack && stack->ptr) {
245
+ for (index = 0; index < stack->head; index++) {
246
+ rb_gc_mark(stack->ptr[index]);
247
+ }
245
248
  }
246
249
  }
247
250
 
251
+ static void rvalue_stack_free_buffer(rvalue_stack *stack)
252
+ {
253
+ ruby_xfree(stack->ptr);
254
+ stack->ptr = NULL;
255
+ }
256
+
248
257
  static void rvalue_stack_free(void *ptr)
249
258
  {
250
259
  rvalue_stack *stack = (rvalue_stack *)ptr;
251
260
  if (stack) {
252
- ruby_xfree(stack->ptr);
261
+ rvalue_stack_free_buffer(stack);
262
+ #ifndef HAVE_RUBY_TYPED_EMBEDDABLE
253
263
  ruby_xfree(stack);
264
+ #endif
254
265
  }
255
266
  }
256
267
 
@@ -261,14 +272,13 @@ static size_t rvalue_stack_memsize(const void *ptr)
261
272
  }
262
273
 
263
274
  static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
264
- "JSON::Ext::Parser/rvalue_stack",
265
- {
275
+ .wrap_struct_name = "JSON::Ext::Parser/rvalue_stack",
276
+ .function = {
266
277
  .dmark = rvalue_stack_mark,
267
278
  .dfree = rvalue_stack_free,
268
279
  .dsize = rvalue_stack_memsize,
269
280
  },
270
- 0, 0,
271
- RUBY_TYPED_FREE_IMMEDIATELY,
281
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE,
272
282
  };
273
283
 
274
284
  static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
@@ -290,8 +300,12 @@ static void rvalue_stack_eagerly_release(VALUE handle)
290
300
  if (handle) {
291
301
  rvalue_stack *stack;
292
302
  TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
293
- RTYPEDDATA_DATA(handle) = NULL;
303
+ #ifdef HAVE_RUBY_TYPED_EMBEDDABLE
304
+ rvalue_stack_free_buffer(stack);
305
+ #else
294
306
  rvalue_stack_free(stack);
307
+ RTYPEDDATA_DATA(handle) = NULL;
308
+ #endif
295
309
  }
296
310
  }
297
311
 
@@ -336,12 +350,13 @@ typedef struct JSON_ParserStruct {
336
350
  bool allow_nan;
337
351
  bool allow_trailing_comma;
338
352
  bool allow_control_characters;
353
+ bool allow_invalid_escape;
339
354
  bool symbolize_names;
340
355
  bool freeze;
341
356
  } JSON_ParserConfig;
342
357
 
343
358
  typedef struct JSON_ParserStateStruct {
344
- VALUE stack_handle;
359
+ VALUE *stack_handle;
345
360
  const char *start;
346
361
  const char *cursor;
347
362
  const char *end;
@@ -349,6 +364,7 @@ typedef struct JSON_ParserStateStruct {
349
364
  rvalue_cache name_cache;
350
365
  int in_array;
351
366
  int current_nesting;
367
+ unsigned int emitted_deprecations;
352
368
  } JSON_ParserState;
353
369
 
354
370
  static inline size_t rest(JSON_ParserState *state) {
@@ -400,14 +416,9 @@ static void emit_parse_warning(const char *message, JSON_ParserState *state)
400
416
 
401
417
  #define PARSE_ERROR_FRAGMENT_LEN 32
402
418
 
403
- #ifdef RBIMPL_ATTR_NORETURN
404
- RBIMPL_ATTR_NORETURN()
405
- #endif
406
- static void raise_parse_error(const char *format, JSON_ParserState *state)
419
+ static VALUE build_parse_error_message(const char *format, JSON_ParserState *state, long line, long column)
407
420
  {
408
421
  unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3];
409
- long line, column;
410
- cursor_position(state, &line, &column);
411
422
 
412
423
  const char *ptr = "EOF";
413
424
  if (state->cursor && state->cursor < state->end) {
@@ -439,20 +450,28 @@ static void raise_parse_error(const char *format, JSON_ParserState *state)
439
450
  }
440
451
  }
441
452
 
442
- VALUE msg = rb_sprintf(format, ptr);
443
- VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column);
444
- 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);
455
+ return message;
456
+ }
445
457
 
458
+ static VALUE parse_error_new(VALUE message, long line, long column)
459
+ {
446
460
  VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message);
447
461
  rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line));
448
462
  rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column));
449
- rb_exc_raise(exc);
463
+ return exc;
450
464
  }
451
465
 
452
- #ifdef RBIMPL_ATTR_NORETURN
453
- RBIMPL_ATTR_NORETURN()
454
- #endif
455
- static void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at)
466
+ NORETURN(static) void raise_parse_error(const char *format, JSON_ParserState *state)
467
+ {
468
+ long line, column;
469
+ cursor_position(state, &line, &column);
470
+ VALUE message = build_parse_error_message(format, state, line, column);
471
+ rb_exc_raise(parse_error_new(message, line, column));
472
+ }
473
+
474
+ NORETURN(static) void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at)
456
475
  {
457
476
  state->cursor = at;
458
477
  raise_parse_error(format, state);
@@ -752,6 +771,10 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser
752
771
  }
753
772
  raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
754
773
  }
774
+ }
775
+
776
+ if (config->allow_invalid_escape) {
777
+ APPEND_CHAR(*pe);
755
778
  } else {
756
779
  raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
757
780
  }
@@ -776,20 +799,39 @@ NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_Parser
776
799
  }
777
800
 
778
801
  #define MAX_FAST_INTEGER_SIZE 18
802
+ #define MAX_NUMBER_STACK_BUFFER 128
803
+
804
+ typedef VALUE (*json_number_decode_func_t)(const char *ptr);
805
+
806
+ static inline VALUE json_decode_large_number(const char *start, long len, json_number_decode_func_t func)
807
+ {
808
+ if (RB_LIKELY(len < MAX_NUMBER_STACK_BUFFER)) {
809
+ char buffer[MAX_NUMBER_STACK_BUFFER];
810
+ MEMCPY(buffer, start, char, len);
811
+ buffer[len] = '\0';
812
+ return func(buffer);
813
+ } else {
814
+ VALUE buffer_v = rb_str_tmp_new(len);
815
+ char *buffer = RSTRING_PTR(buffer_v);
816
+ MEMCPY(buffer, start, char, len);
817
+ buffer[len] = '\0';
818
+ VALUE number = func(buffer);
819
+ RB_GC_GUARD(buffer_v);
820
+ return number;
821
+ }
822
+ }
779
823
 
780
- static VALUE json_decode_large_integer(const char *start, long len)
824
+ static VALUE json_decode_inum(const char *buffer)
781
825
  {
782
- VALUE buffer_v;
783
- char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
784
- MEMCPY(buffer, start, char, len);
785
- buffer[len] = '\0';
786
- VALUE number = rb_cstr2inum(buffer, 10);
787
- RB_ALLOCV_END(buffer_v);
788
- return number;
826
+ return rb_cstr2inum(buffer, 10);
789
827
  }
790
828
 
791
- static inline VALUE
792
- json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const char *start, const char *end)
829
+ NOINLINE(static) VALUE json_decode_large_integer(const char *start, long len)
830
+ {
831
+ return json_decode_large_number(start, len, json_decode_inum);
832
+ }
833
+
834
+ static inline VALUE json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const char *start, const char *end)
793
835
  {
794
836
  if (RB_LIKELY(mantissa_digits < MAX_FAST_INTEGER_SIZE)) {
795
837
  if (negative) {
@@ -801,28 +843,20 @@ json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const
801
843
  return json_decode_large_integer(start, end - start);
802
844
  }
803
845
 
804
- static VALUE json_decode_large_float(const char *start, long len)
846
+ static VALUE json_decode_dnum(const char *buffer)
805
847
  {
806
- if (RB_LIKELY(len < 64)) {
807
- char buffer[64];
808
- MEMCPY(buffer, start, char, len);
809
- buffer[len] = '\0';
810
- return DBL2NUM(rb_cstr_to_dbl(buffer, 1));
811
- }
848
+ return DBL2NUM(rb_cstr_to_dbl(buffer, 1));
849
+ }
812
850
 
813
- VALUE buffer_v;
814
- char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
815
- MEMCPY(buffer, start, char, len);
816
- buffer[len] = '\0';
817
- VALUE number = DBL2NUM(rb_cstr_to_dbl(buffer, 1));
818
- RB_ALLOCV_END(buffer_v);
819
- return number;
851
+ NOINLINE(static) VALUE json_decode_large_float(const char *start, long len)
852
+ {
853
+ return json_decode_large_number(start, len, json_decode_dnum);
820
854
  }
821
855
 
822
856
  /* Ruby JSON optimized float decoder using vendored Ryu algorithm
823
857
  * Accepts pre-extracted mantissa and exponent from first-pass validation
824
858
  */
825
- static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits, int32_t exponent, bool negative,
859
+ static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits, int64_t exponent, bool negative,
826
860
  const char *start, const char *end)
827
861
  {
828
862
  if (RB_UNLIKELY(config->decimal_class)) {
@@ -830,13 +864,21 @@ static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantis
830
864
  return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text);
831
865
  }
832
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
+
833
875
  // Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
834
876
  // Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
835
877
  if (RB_UNLIKELY(mantissa_digits > 17 || mantissa_digits + exponent < -307)) {
836
878
  return json_decode_large_float(start, end - start);
837
879
  }
838
880
 
839
- 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));
840
882
  }
841
883
 
842
884
  static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
@@ -868,7 +910,7 @@ static VALUE json_find_duplicated_key(size_t count, const VALUE *pairs)
868
910
  return Qfalse;
869
911
  }
870
912
 
871
- static void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
913
+ NOINLINE(static) void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
872
914
  {
873
915
  VALUE message = rb_sprintf(
874
916
  "detected duplicate key %"PRIsVALUE" in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`",
@@ -879,18 +921,17 @@ static void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_
879
921
  RB_GC_GUARD(message);
880
922
  }
881
923
 
882
- #ifdef RBIMPL_ATTR_NORETURN
883
- RBIMPL_ATTR_NORETURN()
884
- #endif
885
- static void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
924
+ NORETURN(static) void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
886
925
  {
887
926
  VALUE message = rb_sprintf(
888
927
  "duplicate key %"PRIsVALUE,
889
928
  rb_inspect(duplicate_key)
890
929
  );
891
930
 
892
- raise_parse_error(RSTRING_PTR(message), state);
893
- RB_GC_GUARD(message);
931
+ long line, column;
932
+ cursor_position(state, &line, &column);
933
+ rb_str_concat(message, build_parse_error_message("", state, line, column)) ;
934
+ rb_exc_raise(parse_error_new(message, line, column));
894
935
  }
895
936
 
896
937
  static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
@@ -905,7 +946,12 @@ static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfi
905
946
  case JSON_IGNORE:
906
947
  break;
907
948
  case JSON_DEPRECATED:
908
- emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
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
+
909
955
  break;
910
956
  case JSON_RAISE:
911
957
  raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
@@ -927,7 +973,7 @@ static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *
927
973
  if (RB_UNLIKELY(config->on_load_proc)) {
928
974
  value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
929
975
  }
930
- rvalue_stack_push(state->stack, value, &state->stack_handle, &state->stack);
976
+ rvalue_stack_push(state->stack, value, state->stack_handle, &state->stack);
931
977
  return value;
932
978
  }
933
979
 
@@ -1112,7 +1158,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
1112
1158
  const char first_digit = *state->cursor;
1113
1159
 
1114
1160
  // Variables for Ryu optimization - extract digits during parsing
1115
- int32_t exponent = 0;
1161
+ int64_t exponent = 0;
1116
1162
  int decimal_point_pos = -1;
1117
1163
  uint64_t mantissa = 0;
1118
1164
 
@@ -1156,7 +1202,11 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig
1156
1202
  raise_parse_error_at("invalid number: %s", state, start);
1157
1203
  }
1158
1204
 
1159
- exponent = negative_exponent ? -((int32_t)abs_exponent) : ((int32_t)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
+ }
1160
1210
  }
1161
1211
 
1162
1212
  if (integer) {
@@ -1411,39 +1461,56 @@ static void json_ensure_eof(JSON_ParserState *state)
1411
1461
 
1412
1462
  static VALUE convert_encoding(VALUE source)
1413
1463
  {
1414
- int encindex = RB_ENCODING_GET(source);
1464
+ StringValue(source);
1465
+ int encindex = RB_ENCODING_GET(source);
1466
+
1467
+ if (RB_LIKELY(encindex == utf8_encindex)) {
1468
+ return source;
1469
+ }
1415
1470
 
1416
- if (RB_LIKELY(encindex == utf8_encindex)) {
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
+ }
1475
+
1476
+ source = rb_funcall(source, i_encode, 1, Encoding_UTF_8);
1477
+ StringValue(source);
1417
1478
  return source;
1418
- }
1479
+ }
1419
1480
 
1420
- if (encindex == binary_encindex) {
1421
- // For historical reason, we silently reinterpret binary strings as UTF-8
1422
- return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
1423
- }
1481
+ struct parser_config_init_args {
1482
+ JSON_ParserConfig *config;
1483
+ VALUE self;
1484
+ };
1424
1485
 
1425
- return rb_funcall(source, i_encode, 1, Encoding_UTF_8);
1486
+ static void parser_config_wb_write(VALUE self, VALUE *dest, VALUE val)
1487
+ {
1488
+ *dest = val;
1489
+ if (self) RB_OBJ_WRITTEN(self, Qundef, val);
1426
1490
  }
1427
1491
 
1428
1492
  static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1429
1493
  {
1430
- JSON_ParserConfig *config = (JSON_ParserConfig *)data;
1494
+ struct parser_config_init_args *args = (struct parser_config_init_args *)data;
1495
+ JSON_ParserConfig *config = args->config;
1496
+ VALUE self = args->self;
1431
1497
 
1432
1498
  if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
1433
1499
  else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
1434
1500
  else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
1435
1501
  else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); }
1502
+ else if (key == sym_allow_invalid_escape) { config->allow_invalid_escape = RTEST(val); }
1436
1503
  else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
1437
1504
  else if (key == sym_freeze) { config->freeze = RTEST(val); }
1438
- else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
1505
+ else if (key == sym_on_load) { parser_config_wb_write(self, &config->on_load_proc, RTEST(val) ? val : Qfalse); }
1439
1506
  else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
1440
1507
  else if (key == sym_decimal_class) {
1441
1508
  if (RTEST(val)) {
1442
1509
  if (rb_respond_to(val, i_try_convert)) {
1443
- config->decimal_class = val;
1510
+ parser_config_wb_write(self, &config->decimal_class, val);
1444
1511
  config->decimal_method_id = i_try_convert;
1445
1512
  } else if (rb_respond_to(val, i_new)) {
1446
- config->decimal_class = val;
1513
+ parser_config_wb_write(self, &config->decimal_class, val);
1447
1514
  config->decimal_method_id = i_new;
1448
1515
  } else if (RB_TYPE_P(val, T_CLASS)) {
1449
1516
  VALUE name = rb_class_name(val);
@@ -1452,7 +1519,7 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1452
1519
  if (last_colon) {
1453
1520
  const char *mod_path_end = last_colon - 1;
1454
1521
  VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
1455
- config->decimal_class = rb_path_to_class(mod_path);
1522
+ parser_config_wb_write(self, &config->decimal_class, rb_path_to_class(mod_path));
1456
1523
 
1457
1524
  const char *method_name_beg = last_colon + 1;
1458
1525
  long before_len = method_name_beg - name_cstr;
@@ -1460,7 +1527,7 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1460
1527
  VALUE method_name = rb_str_substr(name, before_len, len);
1461
1528
  config->decimal_method_id = SYM2ID(rb_str_intern(method_name));
1462
1529
  } else {
1463
- config->decimal_class = rb_mKernel;
1530
+ parser_config_wb_write(self, &config->decimal_class, rb_mKernel);
1464
1531
  config->decimal_method_id = SYM2ID(rb_str_intern(name));
1465
1532
  }
1466
1533
  }
@@ -1470,16 +1537,21 @@ static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
1470
1537
  return ST_CONTINUE;
1471
1538
  }
1472
1539
 
1473
- static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
1540
+ static void parser_config_init(JSON_ParserConfig *config, VALUE opts, VALUE self)
1474
1541
  {
1475
1542
  config->max_nesting = 100;
1476
1543
 
1544
+ struct parser_config_init_args args = {
1545
+ .config = config,
1546
+ .self = self,
1547
+ };
1548
+
1477
1549
  if (!NIL_P(opts)) {
1478
1550
  Check_Type(opts, T_HASH);
1479
1551
  if (RHASH_SIZE(opts) > 0) {
1480
1552
  // We assume in most cases few keys are set so it's faster to go over
1481
1553
  // the provided keys than to check all possible keys.
1482
- rb_hash_foreach(opts, parser_config_init_i, (VALUE)config);
1554
+ rb_hash_foreach(opts, parser_config_init_i, (VALUE)&args);
1483
1555
  }
1484
1556
 
1485
1557
  }
@@ -1513,17 +1585,21 @@ static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
1513
1585
  rb_check_frozen(self);
1514
1586
  GET_PARSER_CONFIG;
1515
1587
 
1516
- parser_config_init(config, opts);
1517
-
1518
- RB_OBJ_WRITTEN(self, Qundef, config->decimal_class);
1588
+ parser_config_init(config, opts, self);
1519
1589
 
1520
1590
  return self;
1521
1591
  }
1522
1592
 
1523
- static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1593
+ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE src)
1524
1594
  {
1525
- Vsource = convert_encoding(StringValue(Vsource));
1526
- 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
+ }
1527
1603
 
1528
1604
  VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
1529
1605
  rvalue_stack stack = {
@@ -1534,13 +1610,16 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1534
1610
 
1535
1611
  long len;
1536
1612
  const char *start;
1613
+
1537
1614
  RSTRING_GETMEM(Vsource, start, len);
1538
1615
 
1616
+ VALUE stack_handle = 0;
1539
1617
  JSON_ParserState _state = {
1540
1618
  .start = start,
1541
1619
  .cursor = start,
1542
1620
  .end = start + len,
1543
1621
  .stack = &stack,
1622
+ .stack_handle = &stack_handle,
1544
1623
  };
1545
1624
  JSON_ParserState *state = &_state;
1546
1625
 
@@ -1548,8 +1627,9 @@ static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
1548
1627
 
1549
1628
  // This may be skipped in case of exception, but
1550
1629
  // it won't cause a leak.
1551
- rvalue_stack_eagerly_release(state->stack_handle);
1552
-
1630
+ rvalue_stack_eagerly_release(stack_handle);
1631
+ RB_GC_GUARD(stack_handle);
1632
+ RB_GC_GUARD(Vsource);
1553
1633
  json_ensure_eof(state);
1554
1634
 
1555
1635
  return result;
@@ -1570,12 +1650,9 @@ static VALUE cParserConfig_parse(VALUE self, VALUE Vsource)
1570
1650
 
1571
1651
  static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
1572
1652
  {
1573
- Vsource = convert_encoding(StringValue(Vsource));
1574
- StringValue(Vsource);
1575
-
1576
1653
  JSON_ParserConfig _config = {0};
1577
1654
  JSON_ParserConfig *config = &_config;
1578
- parser_config_init(config, opts);
1655
+ parser_config_init(config, opts, false);
1579
1656
 
1580
1657
  return cParser_parse(config, Vsource);
1581
1658
  }
@@ -1587,26 +1664,19 @@ static void JSON_ParserConfig_mark(void *ptr)
1587
1664
  rb_gc_mark(config->decimal_class);
1588
1665
  }
1589
1666
 
1590
- static void JSON_ParserConfig_free(void *ptr)
1591
- {
1592
- JSON_ParserConfig *config = ptr;
1593
- ruby_xfree(config);
1594
- }
1595
-
1596
1667
  static size_t JSON_ParserConfig_memsize(const void *ptr)
1597
1668
  {
1598
1669
  return sizeof(JSON_ParserConfig);
1599
1670
  }
1600
1671
 
1601
1672
  static const rb_data_type_t JSON_ParserConfig_type = {
1602
- "JSON::Ext::Parser/ParserConfig",
1603
- {
1673
+ .wrap_struct_name = "JSON::Ext::Parser/ParserConfig",
1674
+ .function = {
1604
1675
  JSON_ParserConfig_mark,
1605
- JSON_ParserConfig_free,
1676
+ RUBY_DEFAULT_FREE,
1606
1677
  JSON_ParserConfig_memsize,
1607
1678
  },
1608
- 0, 0,
1609
- RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
1679
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_EMBEDDABLE,
1610
1680
  };
1611
1681
 
1612
1682
  static VALUE cJSON_parser_s_allocate(VALUE klass)
@@ -1651,6 +1721,7 @@ void Init_parser(void)
1651
1721
  sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
1652
1722
  sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
1653
1723
  sym_allow_control_characters = ID2SYM(rb_intern("allow_control_characters"));
1724
+ sym_allow_invalid_escape = ID2SYM(rb_intern("allow_invalid_escape"));
1654
1725
  sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
1655
1726
  sym_freeze = ID2SYM(rb_intern("freeze"));
1656
1727
  sym_on_load = ID2SYM(rb_intern("on_load"));
@@ -133,16 +133,6 @@ ALWAYS_INLINE(static) int string_scan_simd_neon(const char **ptr, const char *en
133
133
  return 0;
134
134
  }
135
135
 
136
- static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
137
- {
138
- uint8x16x4_t tab;
139
- tab.val[0] = vld1q_u8(table);
140
- tab.val[1] = vld1q_u8(table+16);
141
- tab.val[2] = vld1q_u8(table+32);
142
- tab.val[3] = vld1q_u8(table+48);
143
- return tab;
144
- }
145
-
146
136
  #endif /* ARM Neon Support.*/
147
137
 
148
138
  #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
data/lib/json/common.rb CHANGED
@@ -156,15 +156,17 @@ module JSON
156
156
  def generator=(generator) # :nodoc:
157
157
  old, $VERBOSE = $VERBOSE, nil
158
158
  @generator = generator
159
- generator_methods = generator::GeneratorMethods
160
- for const in generator_methods.constants
161
- klass = const_get(const)
162
- modul = generator_methods.const_get(const)
163
- klass.class_eval do
164
- instance_methods(false).each do |m|
165
- m.to_s == 'to_json' and remove_method m
159
+ if generator.const_defined?(:GeneratorMethods)
160
+ generator_methods = generator::GeneratorMethods
161
+ for const in generator_methods.constants
162
+ klass = const_get(const)
163
+ modul = generator_methods.const_get(const)
164
+ klass.class_eval do
165
+ instance_methods(false).each do |m|
166
+ m.to_s == 'to_json' and remove_method m
167
+ end
168
+ include modul
166
169
  end
167
- include modul
168
170
  end
169
171
  end
170
172
  self.state = generator::State
@@ -878,7 +880,7 @@ module JSON
878
880
  end
879
881
  end
880
882
 
881
- if opts[:allow_blank] && (source.nil? || source.empty?)
883
+ if opts[:allow_blank] && (source.nil? || (String === source && source.empty?))
882
884
  source = 'null'
883
885
  end
884
886
 
@@ -1036,7 +1038,8 @@ module JSON
1036
1038
  # JSON.new(options = nil, &block)
1037
1039
  #
1038
1040
  # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
1039
- # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
1041
+ # See {Parsing Options}[rdoc-ref:JSON@Parsing+Options],
1042
+ # and {Generating Options}[rdoc-ref:JSON@Generating+Options].
1040
1043
  #
1041
1044
  # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
1042
1045
  # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
@@ -1095,6 +1098,30 @@ module JSON
1095
1098
  load(File.read(path, encoding: Encoding::UTF_8))
1096
1099
  end
1097
1100
  end
1101
+
1102
+ module GeneratorMethods
1103
+ # call-seq: to_json(*)
1104
+ #
1105
+ # Converts this object into a JSON string.
1106
+ # If this object doesn't directly maps to a JSON native type,
1107
+ # first convert it to a string (calling #to_s), then converts
1108
+ # it to a JSON string, and returns the result.
1109
+ # This is a fallback, if no special method #to_json was defined for some object.
1110
+ def to_json(state = nil, *)
1111
+ obj = case self
1112
+ when nil, false, true, Integer, Float, Array, Hash
1113
+ self
1114
+ else
1115
+ "#{self}"
1116
+ end
1117
+
1118
+ if state.nil?
1119
+ JSON::State._generate_no_fallback(obj, nil, nil)
1120
+ else
1121
+ JSON::State.from_state(state)._generate_no_fallback(obj)
1122
+ end
1123
+ end
1124
+ end
1098
1125
  end
1099
1126
 
1100
1127
  module ::Kernel
@@ -1140,3 +1167,7 @@ module ::Kernel
1140
1167
  JSON[object, opts]
1141
1168
  end
1142
1169
  end
1170
+
1171
+ class Object
1172
+ include JSON::GeneratorMethods
1173
+ end
@@ -9,7 +9,7 @@ module JSON
9
9
  # Instantiates a new State object, configured by _opts_.
10
10
  #
11
11
  # Argument +opts+, if given, contains a \Hash of options for the generation.
12
- # See {Generating Options}[#module-JSON-label-Generating+Options].
12
+ # See {Generating Options}[rdoc-ref:JSON@Generating+Options].
13
13
  def initialize(opts = nil)
14
14
  if opts && !opts.empty?
15
15
  configure(opts)