oj 3.13.14 → 3.13.15

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: 6b0eec52170402a3d26527fa072d57fef1647f767e8559b8462893ced4f4cf21
4
- data.tar.gz: 93bba77447858ae77366ff7d8c05ad3199457e2b55a3584dcb6ccca3288d0d4a
3
+ metadata.gz: 2dd6fd9c107efe5095ca235c398e2fb7cc4fb9cdd9feffb4f27fef1ed1e3faa3
4
+ data.tar.gz: 072e3744f4cbb880f1e5296ad1abba448341d9934173fa101ba1d65efe20de64
5
5
  SHA512:
6
- metadata.gz: 9c95fa98149c6b8686376ab6d0f5744ca8a1312f62336a04c23da68d1e76c66c1d0a82ed755e945478623abfae85dac0d58ea84715d61d42dc0441455c3982d6
7
- data.tar.gz: 00eb3b90452e1adc6cf58e4eec3be107076ee99544c7b0d70b7cff6aa9a758b9a330391669a0622f95681cf3e4dc3cf47bdc2be8496a322f1d9432f2557b052a
6
+ metadata.gz: 76fbaa3e575553ffbf37e45447429b58da392d58e59afa82491363a17ee3ab7cacf5283986db7242f1cf8b0340449d8a1d97a6f54c288076110a2fdc5ccebf30
7
+ data.tar.gz: 116f07d7db9124f62007eff33a2583f4de5a1338009fec59eca267a483be229285a7ec66c6fbb1feb92f05284afe76ae39629aca2e8f2a7ff20caa27adddc0c4
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 3.13.15 - 2022-07-03
4
+
5
+ - Fixed issue dumping NaN value in object mode.
6
+
3
7
  ## 3.13.14 - 2022-06-03
4
8
 
5
9
  - Double fclose() due to bad merger fixed by tonobo.
data/ext/oj/dump.c CHANGED
@@ -32,6 +32,7 @@ static const char nan_val[] = NAN_VAL;
32
32
  typedef unsigned long ulong;
33
33
 
34
34
  static size_t hibit_friendly_size(const uint8_t *str, size_t len);
35
+ static size_t slash_friendly_size(const uint8_t *str, size_t len);
35
36
  static size_t xss_friendly_size(const uint8_t *str, size_t len);
36
37
  static size_t ascii_friendly_size(const uint8_t *str, size_t len);
37
38
 
@@ -59,6 +60,17 @@ static char hibit_friendly_chars[256] = "\
59
60
  11111111111111111111111111111111\
60
61
  11111111111111111111111111111111";
61
62
 
63
+ // JSON standard but escape forward slashes `/`
64
+ static char slash_friendly_chars[256] = "\
65
+ 66666666222622666666666666666666\
66
+ 11211111111111121111111111111111\
67
+ 11111111111111111111111111112111\
68
+ 11111111111111111111111111111111\
69
+ 11111111111111111111111111111111\
70
+ 11111111111111111111111111111111\
71
+ 11111111111111111111111111111111\
72
+ 11111111111111111111111111111111";
73
+
62
74
  // High bit set characters are always encoded as unicode. Worse case is 3
63
75
  // bytes per character in the output. That makes this conservative.
64
76
  static char ascii_friendly_chars[256] = "\
@@ -143,6 +155,10 @@ inline static size_t hibit_friendly_size(const uint8_t *str, size_t len) {
143
155
  return calculate_string_size(str, len, hibit_friendly_chars);
144
156
  }
145
157
 
158
+ inline static size_t slash_friendly_size(const uint8_t *str, size_t len) {
159
+ return calculate_string_size(str, len, slash_friendly_chars);
160
+ }
161
+
146
162
  inline static size_t ascii_friendly_size(const uint8_t *str, size_t len) {
147
163
  return calculate_string_size(str, len, ascii_friendly_chars);
148
164
  }
@@ -365,7 +381,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
365
381
  long long sec;
366
382
  long long nsec;
367
383
 
368
- #ifdef HAVE_RB_TIME_TIMESPEC
369
384
  // rb_time_timespec as well as rb_time_timeeval have a bug that causes an
370
385
  // exception to be raised if a time is before 1970 on 32 bit systems so
371
386
  // check the timespec size and use the ruby calls if a 32 bit system.
@@ -378,10 +393,6 @@ void oj_dump_time(VALUE obj, Out out, int withZone) {
378
393
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
379
394
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
380
395
  }
381
- #else
382
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
383
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
384
- #endif
385
396
 
386
397
  *b-- = '\0';
387
398
  if (withZone) {
@@ -467,7 +478,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
467
478
  int tzhour, tzmin;
468
479
  char tzsign = '+';
469
480
 
470
- #ifdef HAVE_RB_TIME_TIMESPEC
471
481
  if (16 <= sizeof(struct timespec)) {
472
482
  struct timespec ts = rb_time_timespec(obj);
473
483
 
@@ -477,10 +487,6 @@ void oj_dump_xml_time(VALUE obj, Out out) {
477
487
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
478
488
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
479
489
  }
480
- #else
481
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
482
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
483
- #endif
484
490
 
485
491
  assure_size(out, 36);
486
492
  if (9 > out->opts->sec_prec) {
@@ -756,6 +762,11 @@ void oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out ou
756
762
  cmap = ascii_friendly_chars;
757
763
  size = ascii_friendly_size((uint8_t *)str, cnt);
758
764
  break;
765
+ case SlashEsc:
766
+ has_hi = true;
767
+ cmap = slash_friendly_chars;
768
+ size = slash_friendly_size((uint8_t *)str, cnt);
769
+ break;
759
770
  case XSSEsc:
760
771
  cmap = xss_friendly_chars;
761
772
  size = xss_friendly_size((uint8_t *)str, cnt);
@@ -1130,7 +1141,7 @@ void oj_dump_float(VALUE obj, int depth, Out out, bool as_ok) {
1130
1141
  } else if (isnan(d)) {
1131
1142
  if (ObjectMode == out->opts->mode) {
1132
1143
  strcpy(buf, nan_val);
1133
- cnt = sizeof(ninf_val) - 1;
1144
+ cnt = sizeof(nan_val) - 1;
1134
1145
  } else {
1135
1146
  NanDump nd = out->opts->dump_opts.nan_dump;
1136
1147
 
data/ext/oj/dump_compat.c CHANGED
@@ -444,7 +444,6 @@ time_alt(VALUE obj, int depth, Out out) {
444
444
  time_t sec;
445
445
  long long nsec;
446
446
 
447
- #ifdef HAVE_RB_TIME_TIMESPEC
448
447
  if (16 <= sizeof(struct timespec)) {
449
448
  struct timespec ts = rb_time_timespec(obj);
450
449
 
@@ -454,10 +453,6 @@ time_alt(VALUE obj, int depth, Out out) {
454
453
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
455
454
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
456
455
  }
457
- #else
458
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
459
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
460
- #endif
461
456
 
462
457
  attrs[0].num = sec;
463
458
  attrs[1].num = nsec;
data/ext/oj/dump_object.c CHANGED
@@ -315,7 +315,6 @@ static void dump_hash_class(VALUE obj, VALUE clas, int depth, Out out) {
315
315
  *out->cur = '\0';
316
316
  }
317
317
 
318
- #ifdef HAVE_RB_IVAR_FOREACH
319
318
  static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
320
319
  Out out = (Out)ov;
321
320
  int depth = out->depth;
@@ -358,7 +357,6 @@ static int dump_attr_cb(ID key, VALUE value, VALUE ov) {
358
357
 
359
358
  return ST_CONTINUE;
360
359
  }
361
- #endif
362
360
 
363
361
  static void dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
364
362
  dump_hash_class(obj, rb_obj_class(obj), depth, out);
@@ -510,19 +508,8 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
510
508
  default: break;
511
509
  }
512
510
  {
513
- int cnt;
514
- #ifdef HAVE_RB_IVAR_COUNT
515
- cnt = (int)rb_ivar_count(obj);
516
- #else
517
- volatile VALUE vars = rb_funcall2(obj, oj_instance_variables_id, 0, 0);
518
- VALUE * np = RARRAY_PTR(vars);
519
- ID vid;
520
- const char * attr;
521
- int i;
522
- int first = 1;
523
-
524
- cnt = (int)RARRAY_LEN(vars);
525
- #endif
511
+ int cnt = (int)rb_ivar_count(obj);
512
+
526
513
  if (Qundef != clas && 0 < cnt) {
527
514
  *out->cur++ = ',';
528
515
  }
@@ -535,52 +522,10 @@ static void dump_obj_attrs(VALUE obj, VALUE clas, slot_t id, int depth, Out out)
535
522
  }
536
523
  }
537
524
  out->depth = depth + 1;
538
- #ifdef HAVE_RB_IVAR_FOREACH
539
525
  rb_ivar_foreach(obj, dump_attr_cb, (VALUE)out);
540
526
  if (',' == *(out->cur - 1)) {
541
527
  out->cur--; // backup to overwrite last comma
542
528
  }
543
- #else
544
- size = d2 * out->indent + 1;
545
- for (i = cnt; 0 < i; i--, np++) {
546
- VALUE value;
547
-
548
- vid = rb_to_id(*np);
549
- attr = rb_id2name(vid);
550
- if (Yes == out->opts->ignore_under && '@' == *attr && '_' == attr[1]) {
551
- continue;
552
- }
553
- value = rb_ivar_get(obj, vid);
554
-
555
- if (dump_ignore(out->opts, value)) {
556
- continue;
557
- }
558
- if (out->omit_nil && Qnil == value) {
559
- continue;
560
- }
561
- if (first) {
562
- first = 0;
563
- } else {
564
- *out->cur++ = ',';
565
- }
566
- assure_size(out, size);
567
- fill_indent(out, d2);
568
- if ('@' == *attr) {
569
- attr++;
570
- oj_dump_cstr(attr, strlen(attr), 0, 0, out);
571
- } else {
572
- char buf[32];
573
-
574
- *buf = '~';
575
- strncpy(buf + 1, attr, sizeof(buf) - 2);
576
- buf[sizeof(buf) - 1] = '\0';
577
- oj_dump_cstr(buf, strlen(attr) + 1, 0, 0, out);
578
- }
579
- *out->cur++ = ':';
580
- oj_dump_obj_val(value, d2, out);
581
- assure_size(out, 2);
582
- }
583
- #endif
584
529
  if (rb_obj_is_kind_of(obj, rb_eException)) {
585
530
  volatile VALUE rv;
586
531
 
data/ext/oj/extconf.rb CHANGED
@@ -23,14 +23,10 @@ dflags = {
23
23
  'RSTRUCT_LEN_RETURNS_INTEGER_OBJECT' => ('ruby' == type && '2' == version[0] && '4' == version[1] && '1' >= version[2]) ? 1 : 0,
24
24
  }
25
25
 
26
- have_func('rb_time_timespec')
27
- have_func('rb_ivar_count')
28
- have_func('rb_ivar_foreach')
29
26
  # Support for compaction.
30
27
  have_func('rb_gc_mark_movable')
31
28
  have_func('stpcpy')
32
29
  have_func('pthread_mutex_init')
33
- have_func('rb_enc_associate')
34
30
  have_func('rb_enc_interned_str')
35
31
  have_func('rb_ext_ractor_safe', 'ruby.h')
36
32
  # rb_hash_bulk_insert is deep down in a header not included in normal build and that seems to fool have_func.
@@ -38,6 +34,11 @@ have_func('rb_hash_bulk_insert', 'ruby.h') unless '2' == version[0] && '6' == ve
38
34
 
39
35
  dflags['OJ_DEBUG'] = true unless ENV['OJ_DEBUG'].nil?
40
36
 
37
+ if try_cflags('-msse4.2')
38
+ $CPPFLAGS += ' -msse4.2'
39
+ dflags['OJ_USE_SSE4_2'] = 1
40
+ end
41
+
41
42
  dflags.each do |k,v|
42
43
  if v.nil?
43
44
  $CPPFLAGS += " -D#{k}"
data/ext/oj/mimic_json.c CHANGED
@@ -388,6 +388,10 @@ static VALUE mimic_generate_core(int argc, VALUE *argv, Options copts) {
388
388
  VALUE active_hack[1];
389
389
 
390
390
  if (Qundef == state_class) {
391
+ rb_warn(
392
+ "Oj::Rails.mimic_JSON was called implicitly. "
393
+ "Call it explicitly beforehand if you want to remove this warning."
394
+ );
391
395
  oj_define_mimic_json(0, NULL, Qnil);
392
396
  }
393
397
  active_hack[0] = rb_funcall(state_class, oj_new_id, 0);
@@ -481,6 +485,10 @@ oj_mimic_pretty_generate(int argc, VALUE *argv, VALUE self) {
481
485
  rb_hash_aset(h, oj_array_nl_sym, rb_str_new2("\n"));
482
486
  }
483
487
  if (Qundef == state_class) {
488
+ rb_warn(
489
+ "Oj::Rails.mimic_JSON was called implicitly. "
490
+ "Call it explicitly beforehand if you want to remove this warning."
491
+ );
484
492
  oj_define_mimic_json(0, NULL, Qnil);
485
493
  }
486
494
  rargs[1] = rb_funcall(state_class, oj_new_id, 1, h);
@@ -536,14 +544,6 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE info) {
536
544
  }
537
545
  } else if (oj_decimal_class_sym == k) {
538
546
  pi->options.compat_bigdec = (oj_bigdecimal_class == v);
539
- } else if (oj_max_nesting_sym == k) {
540
- if (Qtrue == v) {
541
- pi->max_depth = 100;
542
- } else if (Qfalse == v || Qnil == v) {
543
- pi->max_depth = 0;
544
- } else if (T_FIXNUM == rb_type(v)) {
545
- pi->max_depth = NUM2INT(v);
546
- }
547
547
  }
548
548
  return ST_CONTINUE;
549
549
  }
@@ -573,11 +573,21 @@ static VALUE mimic_parse_core(int argc, VALUE *argv, VALUE self, bool bang) {
573
573
  pi.max_depth = 100;
574
574
 
575
575
  if (Qnil != ropts) {
576
+ VALUE v;
577
+
576
578
  if (T_HASH != rb_type(ropts)) {
577
579
  rb_raise(rb_eArgError, "options must be a hash.");
578
580
  }
579
581
 
580
582
  rb_hash_foreach(ropts, parse_options_cb, (VALUE)&pi);
583
+ v = rb_hash_lookup(ropts, oj_max_nesting_sym);
584
+ if (Qtrue == v) {
585
+ pi.max_depth = 100;
586
+ } else if (Qfalse == v || Qnil == v) {
587
+ pi.max_depth = 0;
588
+ } else if (T_FIXNUM == rb_type(v)) {
589
+ pi.max_depth = NUM2INT(v);
590
+ }
581
591
  oj_parse_opt_match_string(&pi.options.str_rx, ropts);
582
592
  if (Yes == pi.options.create_ok && Yes == pi.options.sym_key) {
583
593
  rb_raise(rb_eArgError, ":symbolize_names and :create_additions can not both be true.");
data/ext/oj/oj.c CHANGED
@@ -45,7 +45,6 @@ ID oj_hash_key_id;
45
45
  ID oj_hash_set_id;
46
46
  ID oj_hash_start_id;
47
47
  ID oj_iconv_id;
48
- ID oj_instance_variables_id;
49
48
  ID oj_json_create_id;
50
49
  ID oj_length_id;
51
50
  ID oj_new_id;
@@ -137,6 +136,7 @@ static VALUE rails_sym;
137
136
  static VALUE raise_sym;
138
137
  static VALUE ruby_sym;
139
138
  static VALUE sec_prec_sym;
139
+ static VALUE slash_sym;
140
140
  static VALUE strict_sym;
141
141
  static VALUE symbol_keys_sym;
142
142
  static VALUE time_format_sym;
@@ -405,6 +405,7 @@ static VALUE get_def_opts(VALUE self) {
405
405
  switch (oj_default_options.escape_mode) {
406
406
  case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
407
407
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
408
+ case SlashEsc: rb_hash_aset(opts, escape_mode_sym, slash_sym); break;
408
409
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
409
410
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
410
411
  case JXEsc: rb_hash_aset(opts, escape_mode_sym, unicode_xss_sym); break;
@@ -734,6 +735,8 @@ static int parse_options_cb(VALUE k, VALUE v, VALUE opts) {
734
735
  copts->escape_mode = NLEsc;
735
736
  } else if (json_sym == v) {
736
737
  copts->escape_mode = JSONEsc;
738
+ } else if (slash_sym == v) {
739
+ copts->escape_mode = SlashEsc;
737
740
  } else if (xss_safe_sym == v) {
738
741
  copts->escape_mode = XSSEsc;
739
742
  } else if (ascii_sym == v) {
@@ -1148,7 +1151,17 @@ static VALUE load_file(int argc, VALUE *argv, VALUE self) {
1148
1151
  }
1149
1152
  }
1150
1153
  path = StringValuePtr(*argv);
1151
- if (0 == (fd = open(path, O_RDONLY))) {
1154
+ #ifdef _WIN32
1155
+ {
1156
+ WCHAR *wide_path;
1157
+ wide_path = rb_w32_mbstr_to_wstr(CP_UTF8, path, -1, NULL);
1158
+ fd = rb_w32_wopen(wide_path, O_RDONLY);
1159
+ free(wide_path);
1160
+ }
1161
+ #else
1162
+ fd = open(path, O_RDONLY);
1163
+ #endif
1164
+ if (0 == fd) {
1152
1165
  rb_raise(rb_eIOError, "%s", strerror(errno));
1153
1166
  }
1154
1167
  switch (mode) {
@@ -1814,7 +1827,6 @@ void Init_oj(void) {
1814
1827
  oj_hash_set_id = rb_intern("hash_set");
1815
1828
  oj_hash_start_id = rb_intern("hash_start");
1816
1829
  oj_iconv_id = rb_intern("iconv");
1817
- oj_instance_variables_id = rb_intern("instance_variables");
1818
1830
  oj_json_create_id = rb_intern("json_create");
1819
1831
  oj_length_id = rb_intern("length");
1820
1832
  oj_new_id = rb_intern("new");
@@ -1977,6 +1989,8 @@ void Init_oj(void) {
1977
1989
  rb_gc_register_address(&ruby_sym);
1978
1990
  sec_prec_sym = ID2SYM(rb_intern("second_precision"));
1979
1991
  rb_gc_register_address(&sec_prec_sym);
1992
+ slash_sym = ID2SYM(rb_intern("slash"));
1993
+ rb_gc_register_address(&slash_sym);
1980
1994
  strict_sym = ID2SYM(rb_intern("strict"));
1981
1995
  rb_gc_register_address(&strict_sym);
1982
1996
  symbol_keys_sym = ID2SYM(rb_intern("symbol_keys"));
data/ext/oj/oj.h CHANGED
@@ -66,6 +66,7 @@ typedef enum { UnixTime = 'u', UnixZTime = 'z', XmlTime = 'x', RubyTime = 'r' }
66
66
  typedef enum {
67
67
  NLEsc = 'n',
68
68
  JSONEsc = 'j',
69
+ SlashEsc = 's',
69
70
  XSSEsc = 'x',
70
71
  ASCIIEsc = 'a',
71
72
  JXEsc = 'g', // json gem
@@ -346,7 +347,6 @@ extern ID oj_hash_key_id;
346
347
  extern ID oj_hash_set_id;
347
348
  extern ID oj_hash_start_id;
348
349
  extern ID oj_iconv_id;
349
- extern ID oj_instance_variables_id;
350
350
  extern ID oj_json_create_id;
351
351
  extern ID oj_length_id;
352
352
  extern ID oj_new_id;
data/ext/oj/parse.c CHANGED
@@ -327,26 +327,61 @@ static void read_escaped_str(ParseInfo pi, const char *start) {
327
327
  buf_cleanup(&buf);
328
328
  }
329
329
 
330
- static void read_str(ParseInfo pi) {
331
- const char *str = pi->cur;
332
- Val parent = stack_peek(&pi->stack);
333
-
330
+ static inline void scan_string_noSIMD(ParseInfo pi) {
334
331
  for (; '"' != *pi->cur; pi->cur++) {
335
- if (pi->end <= pi->cur) {
336
- oj_set_error_at(pi,
337
- oj_parse_error_class,
338
- __FILE__,
339
- __LINE__,
340
- "quoted string not terminated");
332
+ if (pi->end <= pi->cur || '\0' == *pi->cur || '\\' == *pi->cur) {
341
333
  return;
342
- } else if ('\0' == *pi->cur) {
343
- oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
344
- return;
345
- } else if ('\\' == *pi->cur) {
346
- read_escaped_str(pi, str);
334
+ }
335
+ }
336
+ }
337
+
338
+ #if defined(OJ_USE_SSE4_2)
339
+ #include <nmmintrin.h>
340
+
341
+ static inline void scan_string_SIMD(ParseInfo pi) {
342
+ static const char chars[16] = "\x00\\\"";
343
+ const __m128i terminate = _mm_loadu_si128((const __m128i *)&chars[0]);
344
+ const char *end = (const char *)(pi->end - 16);
345
+
346
+ for (; pi->cur <= end; pi->cur += 16) {
347
+ const __m128i string = _mm_loadu_si128((const __m128i *)pi->cur);
348
+ const int r = _mm_cmpestri(terminate, 3, string, 16, _SIDD_UBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_LEAST_SIGNIFICANT);
349
+ if (r != 16) {
350
+ pi->cur = (const char*)(pi->cur + r);
347
351
  return;
348
352
  }
349
353
  }
354
+
355
+ scan_string_noSIMD(pi);
356
+ }
357
+ #endif
358
+
359
+ static void read_str(ParseInfo pi) {
360
+ const char *str = pi->cur;
361
+ Val parent = stack_peek(&pi->stack);
362
+
363
+ #if defined(OJ_USE_SSE4_2)
364
+ scan_string_SIMD(pi);
365
+ #else
366
+ scan_string_noSIMD(pi);
367
+ #endif
368
+ if (RB_UNLIKELY(pi->end <= pi->cur)) {
369
+ oj_set_error_at(pi,
370
+ oj_parse_error_class,
371
+ __FILE__,
372
+ __LINE__,
373
+ "quoted string not terminated");
374
+ return;
375
+ }
376
+ if (RB_UNLIKELY('\0' == *pi->cur)) {
377
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "NULL byte in string");
378
+ return;
379
+ }
380
+ if ('\\' == *pi->cur) {
381
+ read_escaped_str(pi, str);
382
+ return;
383
+ }
384
+
350
385
  if (0 == parent) { // simple add
351
386
  pi->add_cstr(pi, str, pi->cur - str, str);
352
387
  } else {
data/ext/oj/rails.c CHANGED
@@ -320,7 +320,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
320
320
  long long sec;
321
321
  long long nsec;
322
322
 
323
- #ifdef HAVE_RB_TIME_TIMESPEC
324
323
  if (16 <= sizeof(struct timespec)) {
325
324
  struct timespec ts = rb_time_timespec(obj);
326
325
 
@@ -330,10 +329,6 @@ static void dump_time(VALUE obj, int depth, Out out, bool as_ok) {
330
329
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
331
330
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
332
331
  }
333
- #else
334
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
335
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
336
- #endif
337
332
  dump_sec_nano(obj, sec, nsec, out);
338
333
  }
339
334
 
data/ext/oj/sparse.c CHANGED
@@ -953,7 +953,11 @@ CLEANUP:
953
953
  }
954
954
  stack_cleanup(&pi->stack);
955
955
  if (0 != fd) {
956
+ #ifdef _WIN32
957
+ rb_w32_close(fd);
958
+ #else
956
959
  close(fd);
960
+ #endif
957
961
  }
958
962
  if (err_has(&pi->err)) {
959
963
  rb_set_errinfo(Qnil);
data/ext/oj/wab.c CHANGED
@@ -194,7 +194,6 @@ static void dump_time(VALUE obj, Out out) {
194
194
  time_t sec;
195
195
  long long nsec;
196
196
 
197
- #ifdef HAVE_RB_TIME_TIMESPEC
198
197
  if (16 <= sizeof(struct timespec)) {
199
198
  struct timespec ts = rb_time_timespec(obj);
200
199
 
@@ -204,10 +203,6 @@ static void dump_time(VALUE obj, Out out) {
204
203
  sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
205
204
  nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
206
205
  }
207
- #else
208
- sec = NUM2LL(rb_funcall2(obj, oj_tv_sec_id, 0, 0));
209
- nsec = NUM2LL(rb_funcall2(obj, oj_tv_nsec_id, 0, 0));
210
- #endif
211
206
 
212
207
  assure_size(out, 36);
213
208
  // 2012-01-05T23:58:07.123456000Z
data/lib/oj/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.13.14'
4
+ VERSION = '3.13.15'
5
5
  end
data/test/bar.rb CHANGED
@@ -6,4 +6,11 @@ $: << File.join(File.dirname(__FILE__), "../ext")
6
6
 
7
7
  require 'oj'
8
8
 
9
- Oj.load(%|{"time":"2021-08-16 12:12:15","a":"5","b":"5"|)
9
+ puts Oj.dump({
10
+ "float_test" => 0.25,
11
+ "nan_test" => Float::NAN,
12
+ "inf_test" => Float::INFINITY,
13
+ "minus_inf_test" => -Float::INFINITY,
14
+ "min_test" => Float::MIN,
15
+ "max_test" => Float::MAX,
16
+ }, mode: :object) # => {"float_test":0.25,"nan_test":3.3e14159265358979323846
@@ -269,6 +269,13 @@ EOT
269
269
  assert_equal too_deep_ary, ok
270
270
  ok = JSON.parse too_deep, :max_nesting => 0
271
271
  assert_equal too_deep_ary, ok
272
+
273
+ unless ENV['REAL_JSON_GEM']
274
+ # max_nesting should be reset to 0 if not included in options
275
+ # This behavior is not compatible with Ruby standard JSON gem
276
+ ok = JSON.parse too_deep, {}
277
+ assert_equal too_deep_ary, ok
278
+ end
272
279
  end
273
280
 
274
281
  def test_backslash
data/test/test_compat.rb CHANGED
@@ -488,6 +488,22 @@ class CompatJuice < Minitest::Test
488
488
  assert_equal([1,2], Oj.load(s, :mode => :compat))
489
489
  end
490
490
 
491
+ def test_parse_large_string
492
+ error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaa\0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}|) }
493
+ assert(error.message.include?('NULL byte in string'))
494
+
495
+ error = assert_raises() { Oj.load(%|{"a":"aaaaaaaaaaaaaaaaaaaa }|) }
496
+ assert(error.message.include?('quoted string not terminated'))
497
+
498
+ json =<<~JSON
499
+ {
500
+ "a": "\\u3074\\u30fc\\u305f\\u30fc",
501
+ "b": "aaaaaaaaaaaaaaaaaaaaaaaaaaaa"
502
+ }
503
+ JSON
504
+ assert_equal("ぴーたー", Oj.load(json)['a'])
505
+ end
506
+
491
507
  def dump_and_load(obj, trace=false)
492
508
  json = Oj.dump(obj)
493
509
  puts json if trace
data/test/test_file.rb CHANGED
@@ -212,6 +212,24 @@ class FileJuice < Minitest::Test
212
212
  dump_and_load(DateTime.new(2012, 6, 19), false)
213
213
  end
214
214
 
215
+ def test_load_unicode_path
216
+ json =<<~JSON
217
+ {
218
+ "x":true,
219
+ "y":58,
220
+ "z": [1,2,3]
221
+ }
222
+ JSON
223
+
224
+ Tempfile.create('file_test_conceição1.json') do |f|
225
+ f.write(json)
226
+ f.close
227
+
228
+ objects = Oj.load_file(f.path)
229
+ assert_equal(Oj.load(json), objects)
230
+ end
231
+ end
232
+
215
233
  def dump_and_load(obj, trace=false)
216
234
  filename = File.join(File.dirname(__FILE__), 'file_test.json')
217
235
  File.open(filename, "w") { |f|
data/test/test_various.rb CHANGED
@@ -345,6 +345,12 @@ class Juice < Minitest::Test
345
345
  out = Oj.dump hash
346
346
  assert_equal(%{{"key":"I \\u003c3 this"}}, out)
347
347
  end
348
+ def test_escapes_slashes_by_default_when_configured_to_do_so
349
+ hash = {'key' => "I <3 this </script>"}
350
+ Oj.default_options = {:escape_mode => :slash}
351
+ out = Oj.dump hash
352
+ assert_equal(%{{"key":"I <3 this <\\/script>"}}, out)
353
+ end
348
354
  def test_escapes_entities_when_asked_to
349
355
  hash = {'key' => "I <3 this"}
350
356
  out = Oj.dump(hash, :escape_mode => :xss_safe)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oj
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.13.14
4
+ version: 3.13.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-03 00:00:00.000000000 Z
11
+ date: 2022-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -303,108 +303,4 @@ rubygems_version: 3.3.3
303
303
  signing_key:
304
304
  specification_version: 4
305
305
  summary: A fast JSON parser and serializer.
306
- test_files:
307
- - test/_test_active.rb
308
- - test/_test_active_mimic.rb
309
- - test/_test_mimic_rails.rb
310
- - test/activerecord/result_test.rb
311
- - test/activesupport4/decoding_test.rb
312
- - test/activesupport4/encoding_test.rb
313
- - test/activesupport4/test_helper.rb
314
- - test/activesupport5/abstract_unit.rb
315
- - test/activesupport5/decoding_test.rb
316
- - test/activesupport5/encoding_test.rb
317
- - test/activesupport5/encoding_test_cases.rb
318
- - test/activesupport5/test_helper.rb
319
- - test/activesupport5/time_zone_test_helpers.rb
320
- - test/activesupport6/abstract_unit.rb
321
- - test/activesupport6/decoding_test.rb
322
- - test/activesupport6/encoding_test.rb
323
- - test/activesupport6/encoding_test_cases.rb
324
- - test/activesupport6/test_common.rb
325
- - test/activesupport6/test_helper.rb
326
- - test/activesupport6/time_zone_test_helpers.rb
327
- - test/activesupport7/abstract_unit.rb
328
- - test/activesupport7/decoding_test.rb
329
- - test/activesupport7/encoding_test.rb
330
- - test/activesupport7/encoding_test_cases.rb
331
- - test/activesupport7/time_zone_test_helpers.rb
332
- - test/bar.rb
333
- - test/baz.rb
334
- - test/bug.rb
335
- - test/files.rb
336
- - test/foo.rb
337
- - test/helper.rb
338
- - test/isolated/shared.rb
339
- - test/isolated/test_mimic_after.rb
340
- - test/isolated/test_mimic_alone.rb
341
- - test/isolated/test_mimic_as_json.rb
342
- - test/isolated/test_mimic_before.rb
343
- - test/isolated/test_mimic_define.rb
344
- - test/isolated/test_mimic_rails_after.rb
345
- - test/isolated/test_mimic_rails_before.rb
346
- - test/isolated/test_mimic_redefine.rb
347
- - test/json_gem/json_addition_test.rb
348
- - test/json_gem/json_common_interface_test.rb
349
- - test/json_gem/json_encoding_test.rb
350
- - test/json_gem/json_ext_parser_test.rb
351
- - test/json_gem/json_fixtures_test.rb
352
- - test/json_gem/json_generator_test.rb
353
- - test/json_gem/json_generic_object_test.rb
354
- - test/json_gem/json_parser_test.rb
355
- - test/json_gem/json_string_matching_test.rb
356
- - test/json_gem/test_helper.rb
357
- - test/mem.rb
358
- - test/perf.rb
359
- - test/perf_compat.rb
360
- - test/perf_dump.rb
361
- - test/perf_fast.rb
362
- - test/perf_file.rb
363
- - test/perf_object.rb
364
- - test/perf_once.rb
365
- - test/perf_parser.rb
366
- - test/perf_saj.rb
367
- - test/perf_scp.rb
368
- - test/perf_simple.rb
369
- - test/perf_strict.rb
370
- - test/perf_wab.rb
371
- - test/prec.rb
372
- - test/sample/change.rb
373
- - test/sample/dir.rb
374
- - test/sample/doc.rb
375
- - test/sample/file.rb
376
- - test/sample/group.rb
377
- - test/sample/hasprops.rb
378
- - test/sample/layer.rb
379
- - test/sample/line.rb
380
- - test/sample/oval.rb
381
- - test/sample/rect.rb
382
- - test/sample/shape.rb
383
- - test/sample/text.rb
384
- - test/sample.rb
385
- - test/sample_json.rb
386
- - test/test_compat.rb
387
- - test/test_custom.rb
388
- - test/test_debian.rb
389
- - test/test_fast.rb
390
- - test/test_file.rb
391
- - test/test_gc.rb
392
- - test/test_generate.rb
393
- - test/test_hash.rb
394
- - test/test_integer_range.rb
395
- - test/test_null.rb
396
- - test/test_object.rb
397
- - test/test_parser.rb
398
- - test/test_parser_saj.rb
399
- - test/test_parser_usual.rb
400
- - test/test_rails.rb
401
- - test/test_saj.rb
402
- - test/test_scp.rb
403
- - test/test_strict.rb
404
- - test/test_various.rb
405
- - test/test_wab.rb
406
- - test/test_writer.rb
407
- - test/tests.rb
408
- - test/tests_mimic.rb
409
- - test/tests_mimic_addition.rb
410
- - test/zoo.rb
306
+ test_files: []