oj 3.0.7 → 3.0.8

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
  SHA1:
3
- metadata.gz: 5a9a1e933a2b0c03c3fb9c0e0b8ef0447edf2438
4
- data.tar.gz: 588b81842eb490fd7beb6021a048f7703ddeb28a
3
+ metadata.gz: a944529c2d9fc9f12e3be88cb7edd568e3c32de9
4
+ data.tar.gz: d40180c12d6ae9ee8e50fa13bbe49374674e5eb3
5
5
  SHA512:
6
- metadata.gz: e74ce695c617c00f6124a523294f949eb291b6c80f8da2c1e122d088b0c381473142bb3650ddd634693458c2356f37185ecebb03adf4c682e5337cbccf1b10de
7
- data.tar.gz: e8eb16851a194c06a5a41527c63c149001bee902132e4591fbf3f46544b17ec942924ca5e5f7abf7bda5cc4fcf24623c1dd03c12afc9525561f52231b68486e8
6
+ metadata.gz: a46eb91148fd3200c0226d38a7ad9bff977a037a0ebd93ddcda9b082f515e2561e815c01694c58ec17af7d9be9f83075a4f630c35b077c862b1de048173f1627
7
+ data.tar.gz: af1bfff262e48d2f46282b5314247a98ea919fbb17f8b653fca03736f93944f61e1fba25b00df894020372ae0f3b1e3bddd2732c3be65dfe2c17bec6140d77e2
@@ -157,11 +157,15 @@ inline static size_t
157
157
  hixss_friendly_size(const uint8_t *str, size_t len) {
158
158
  size_t size = 0;
159
159
  size_t i = len;
160
-
160
+ bool check = false;
161
+
161
162
  for (; 0 < i; str++, i--) {
162
163
  size += hixss_friendly_chars[*str];
164
+ if (0 != (0x80 & *str)) {
165
+ check = true;
166
+ }
163
167
  }
164
- return size - len * (size_t)'0';
168
+ return size - len * (size_t)'0' + check;
165
169
  }
166
170
 
167
171
  inline static size_t
@@ -279,6 +283,34 @@ dump_unicode(const char *str, const char *end, Out out) {
279
283
  return str - 1;
280
284
  }
281
285
 
286
+ static const char*
287
+ check_unicode(const char *str, const char *end) {
288
+ uint8_t b = *(uint8_t*)str;
289
+ int cnt;
290
+
291
+ if (0xC0 == (0xE0 & b)) {
292
+ cnt = 1;
293
+ } else if (0xE0 == (0xF0 & b)) {
294
+ cnt = 2;
295
+ } else if (0xF0 == (0xF8 & b)) {
296
+ cnt = 3;
297
+ } else if (0xF8 == (0xFC & b)) {
298
+ cnt = 4;
299
+ } else if (0xFC == (0xFE & b)) {
300
+ cnt = 5;
301
+ } else {
302
+ rb_raise(oj_json_generator_error_class, "Invalid Unicode");
303
+ }
304
+ str++;
305
+ for (; 0 < cnt; cnt--, str++) {
306
+ b = *(uint8_t*)str;
307
+ if (end <= str || 0x80 != (0xC0 & b)) {
308
+ rb_raise(oj_json_generator_error_class, "Invalid Unicode");
309
+ }
310
+ }
311
+ return str;
312
+ }
313
+
282
314
  // Returns 0 if not using circular references, -1 if no further writing is
283
315
  // needed (duplicate), and a positive value if the object was added to the
284
316
  // cache.
@@ -707,6 +739,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
707
739
  *out->cur++ = '"';
708
740
  } else {
709
741
  const char *end = str + cnt;
742
+ const char *check_start = str;
710
743
 
711
744
  if (is_sym) {
712
745
  *out->cur++ = ':';
@@ -714,6 +747,15 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
714
747
  for (; str < end; str++) {
715
748
  switch (cmap[(uint8_t)*str]) {
716
749
  case '1':
750
+ if (JXEsc == out->opts->escape_mode && check_start <= str) {
751
+ if (0 != (0x80 & (uint8_t)*str)) {
752
+ if (0xC0 == (0xC0 & (uint8_t)*str)) {
753
+ check_start = check_unicode(str, end);
754
+ } else {
755
+ rb_raise(oj_json_generator_error_class, "Invalid Unicode");
756
+ }
757
+ }
758
+ }
717
759
  *out->cur++ = *str;
718
760
  break;
719
761
  case '2':
@@ -734,6 +776,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
734
776
  str = dump_unicode(str, end, out);
735
777
  } else {
736
778
  *out->cur++ = *str;
779
+ check_start = str + 3;
737
780
  }
738
781
  break;
739
782
  }
@@ -773,7 +816,7 @@ oj_dump_cstr(const char *str, size_t cnt, bool is_sym, bool escape1, Out out) {
773
816
  break;
774
817
  case 2:
775
818
  if (0xE0 != (0xF0 & c)) {
776
- rb_raise(oj_json_generator_error_class, "Partial character in string. 2");
819
+ rb_raise(oj_json_generator_error_class, "Partial character in string.");
777
820
  }
778
821
  break;
779
822
  case 3:
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include "code.h"
7
7
  #include "dump.h"
8
+ #include "rails.h"
8
9
 
9
10
  // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
10
11
  #define OJ_INFINITY (1.0/0.0)
@@ -612,9 +613,13 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
612
613
  } else if (d == (double)(long long int)d) {
613
614
  //cnt = snprintf(buf, sizeof(buf), "%.1Lf", (long double)d);
614
615
  cnt = snprintf(buf, sizeof(buf), "%.1f", d);
615
- } else {
616
- //cnt = snprintf(buf, sizeof(buf), "%0.16Lg", (long double)d);
616
+ } else if (oj_rails_float_opt) {
617
617
  cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
618
+ } else {
619
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
620
+
621
+ strcpy(buf, rb_string_value_ptr((VALUE*)&rstr));
622
+ cnt = RSTRING_LEN(rstr);
618
623
  }
619
624
  assure_size(out, cnt);
620
625
  for (b = buf; '\0' != *b; b++) {
@@ -669,7 +669,7 @@ static struct _Options mimic_object_to_json_options = {
669
669
  10, // create_id_len
670
670
  3, // sec_prec
671
671
  16, // float_prec
672
- "%0.15g", // float_fmt
672
+ "%0.16g", // float_fmt
673
673
  Qnil, // hash_class
674
674
  Qnil, // array_class
675
675
  { // dump_opts
@@ -1000,6 +1000,7 @@ to_json(int argc, VALUE *argv, VALUE self) {
1000
1000
  if (1 > argc) {
1001
1001
  rb_raise(rb_eArgError, "wrong number of arguments (0 for 1).");
1002
1002
  }
1003
+ copts.escape_mode = JXEsc;
1003
1004
  copts.dump_opts.nan_dump = false;
1004
1005
  if (2 == argc) {
1005
1006
  oj_parse_mimic_dump_options(argv[1], &copts);
@@ -1600,4 +1601,3 @@ Init_oj() {
1600
1601
  #endif
1601
1602
  oj_init_doc();
1602
1603
  }
1603
-
@@ -19,6 +19,7 @@ typedef struct _Encoder {
19
19
 
20
20
  bool oj_rails_hash_opt = false;
21
21
  bool oj_rails_array_opt = false;
22
+ bool oj_rails_float_opt = false;
22
23
 
23
24
  static void dump_rails_val(VALUE obj, int depth, Out out, bool as_ok);
24
25
 
@@ -187,7 +188,6 @@ dump_struct(VALUE obj, int depth, Out out, bool as_ok) {
187
188
  *out->cur = '\0';
188
189
  }
189
190
 
190
-
191
191
  static ID to_a_id = 0;
192
192
 
193
193
  static void
@@ -484,11 +484,12 @@ optimize(int argc, VALUE *argv, ROptTable rot, bool on) {
484
484
  oj_rails_hash_opt = on;
485
485
  } else if (rb_cArray == *argv) {
486
486
  oj_rails_array_opt = on;
487
+ } else if (rb_cFloat == *argv) {
488
+ oj_rails_float_opt = on;
487
489
  } else if (NULL != (ro = oj_rails_get_opt(rot, *argv)) ||
488
490
  NULL != (ro = create_opt(rot, *argv))) {
489
491
  ro->on = on;
490
492
  }
491
- // TBD recurse if there are subclasses
492
493
  }
493
494
  }
494
495
 
@@ -936,8 +937,13 @@ dump_float(VALUE obj, int depth, Out out, bool as_ok) {
936
937
  cnt = 4;
937
938
  } else if (d == (double)(long long int)d) {
938
939
  cnt = snprintf(buf, sizeof(buf), "%.1f", d);
939
- } else {
940
+ } else if (oj_rails_float_opt) {
940
941
  cnt = snprintf(buf, sizeof(buf), "%0.16g", d);
942
+ } else {
943
+ volatile VALUE rstr = rb_funcall(obj, oj_to_s_id, 0);
944
+
945
+ strcpy(buf, rb_string_value_ptr((VALUE*)&rstr));
946
+ cnt = RSTRING_LEN(rstr);
941
947
  }
942
948
  }
943
949
  assure_size(out, cnt);
@@ -1091,8 +1097,7 @@ dump_hash(VALUE obj, int depth, Out out, bool as_ok) {
1091
1097
  return;
1092
1098
  }
1093
1099
  }
1094
- //if (!oj_rails_hash_opt && 0 < out->argc && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1095
- if (0 < out->argc && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1100
+ if ((!oj_rails_hash_opt || 0 < out->argc) && as_ok && rb_respond_to(obj, oj_as_json_id)) {
1096
1101
  dump_as_json(obj, depth, out, false);
1097
1102
  return;
1098
1103
  }
@@ -13,6 +13,7 @@ extern ROpt oj_rails_get_opt(ROptTable rot, VALUE clas);
13
13
 
14
14
  extern bool oj_rails_hash_opt;
15
15
  extern bool oj_rails_array_opt;
16
+ extern bool oj_rails_float_opt;
16
17
 
17
18
  extern VALUE oj_optimize_rails(VALUE self);
18
19
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '3.0.7'
4
+ VERSION = '3.0.8'
5
5
  end
@@ -61,6 +61,7 @@ Oj::Rails.optimize is called with no arguments are:
61
61
 
62
62
  * Array
63
63
  * BigDecimal
64
+ * Float
64
65
  * Hash
65
66
  * Range
66
67
  * Regexp
@@ -72,3 +73,16 @@ Oj::Rails.optimize is called with no arguments are:
72
73
 
73
74
  The ActiveSupport decoder is the JSON.parse() method. Calling the
74
75
  Oj::Rails.set_decoder() method replaces that method with the Oj equivelant.
76
+
77
+ ### Notes:
78
+
79
+ 1. Optimized Floats set the significant digits to 16. This is different than
80
+ Ruby which is used by the json gem and by Rails. Ruby varies the
81
+ significant digits which can be either 16 or 17 depending on the value.
82
+
83
+ 2. Optimized Hashs do not collapse keys that become the same in the output. As
84
+ an example, a non-String object that has a to_s() method will become the
85
+ return value of the to_s() method in the output without checking to see if
86
+ that has already been used. This could occur is a mix of String and Symbols
87
+ are used as keys or if a other non-String objects such as Numerics are mixed
88
+ with numbers as Strings.
@@ -283,7 +283,6 @@ class CompatJuice < Minitest::Test
283
283
  end
284
284
  x = Oj.load('Infinity', :mode => :compat)
285
285
  assert_equal('Infinity', x.to_s)
286
-
287
286
  end
288
287
 
289
288
  # Time
@@ -461,6 +460,24 @@ class CompatJuice < Minitest::Test
461
460
  assert_equal(%|{"args":"[{:max_nesting=>40}]"}|, json)
462
461
  end
463
462
 
463
+ def test_bad_unicode
464
+ begin
465
+ Oj.to_json("\xE4xy")
466
+ fail()
467
+ rescue Exception
468
+ assert(true)
469
+ end
470
+ end
471
+
472
+ def test_bad_unicode_start
473
+ begin
474
+ Oj.to_json("\x8abc")
475
+ fail()
476
+ rescue Exception
477
+ assert(true)
478
+ end
479
+ end
480
+
464
481
  def dump_and_load(obj, trace=false)
465
482
  json = Oj.dump(obj)
466
483
  puts json if trace
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.0.7
4
+ version: 3.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Ohler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-10 00:00:00.000000000 Z
11
+ date: 2017-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler