oj 3.0.7 → 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
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