oj 2.9.7 → 2.9.8

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of oj might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46cf0f951fe71b68f7df69debe2b80be4fa37539
4
- data.tar.gz: 3988bbf389028c52969cdd2702671b37d78a7f9f
3
+ metadata.gz: 080ee5fb844d326ce444282c5df529a135cf125b
4
+ data.tar.gz: 6461af3c663d8974e0eea8c8b4e3e811500a7397
5
5
  SHA512:
6
- metadata.gz: 0a2e47552a218ebe9d1c0e58e134fa1a5eb36ad0754e72c638d15a528ff12093b5cc1a7587ab61c4491ea046a4c5186562f2f0916f936485a6b31296ba37de0a
7
- data.tar.gz: d996faa5d574f3e5146e872bb4e863f2a286d6b9017d2679db7d570154341f4d0813bd06db5bf672e704d73a184c14769e653280a032e6286286035e71acd76d
6
+ metadata.gz: 5e241a43f3b733fad07606b48f36ec364fce3a516d59596e9684fd7d87bcbc45ea07321ed37719d95f6803d53877f76443813559a42b6c0c86b0f07d19bd0ee6
7
+ data.tar.gz: a01b9b8f1f84de6297b5d240c96680dd212851a95d55d6ffced9b1cd79c98553c29e4a9b7358e4c8f2bcc0b080a855cab85dc17cf30bdf9f4f562bf91f5d459c
data/README.md CHANGED
@@ -26,31 +26,12 @@ Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announceme
26
26
 
27
27
  [![Build Status](https://secure.travis-ci.org/ohler55/oj.png?branch=master)](http://travis-ci.org/ohler55/oj)
28
28
 
29
- ### Current Release 2.9.7
29
+ ### Current Release 2.9.8
30
30
 
31
- - Changed dump to use raw / and raw \n in output instead of escaping.
31
+ - Changed escaping back to previous release and added a new escape mode.
32
32
 
33
- - Changed the writer to always put a new line at the end of a top level JSON
34
- object. It makes output easier to view and edit with minimal impact on size.
35
-
36
- - TBD Worked around the file.gets look ahead caching as long as it is not
37
- called while parsing (of course).
38
-
39
- - Thanks to lautis for a new parse option. quirks_mode allows Oj to behave
40
- quirky like the JSON gem. Actually the JSON gem has it backwards with quirky
41
- mode supporting the JSON spec and non-quirky limiting parsing to objects and
42
- arrays. Oj stays consistent with the JSON gem to avoid confusion.
43
-
44
- - Fixed problem with sc_parse not terminating the string when loaded from a file.
45
-
46
- - Thanks go to dchelimsky for expanding the code sample for the ScHandler.
47
-
48
- ### Release 2.9.6
49
-
50
- - Fixed bug using StringIO with SCParser.
51
-
52
- - Tightened up JSON mimic to raise an exception if JSON.parse is called on
53
- a JSON documents that returns a primitive type.
33
+ - Strict mode and compat mode no longer parse Infinity or NaN as a valid
34
+ number. Both are valid in object mode still.
54
35
 
55
36
  [Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
56
37
 
@@ -111,7 +111,8 @@ static void dump_leaf_hash(Leaf leaf, int depth, Out out);
111
111
 
112
112
  static const char hex_chars[17] = "0123456789abcdef";
113
113
 
114
- static char hibit_friendly_chars[256] = "\
114
+ // JSON standard except newlines are no escaped
115
+ static char newline_friendly_chars[256] = "\
115
116
  66666666221622666666666666666666\
116
117
  11211111111111111111111111111111\
117
118
  11111111111111111111111111112111\
@@ -121,6 +122,17 @@ static char hibit_friendly_chars[256] = "\
121
122
  11111111111111111111111111111111\
122
123
  11111111111111111111111111111111";
123
124
 
125
+ // JSON standard
126
+ static char hibit_friendly_chars[256] = "\
127
+ 66666666222622666666666666666666\
128
+ 11211111111111111111111111111111\
129
+ 11111111111111111111111111112111\
130
+ 11111111111111111111111111111111\
131
+ 11111111111111111111111111111111\
132
+ 11111111111111111111111111111111\
133
+ 11111111111111111111111111111111\
134
+ 11111111111111111111111111111111";
135
+
124
136
  // High bit set characters are always encoded as unicode. Worse case is 3
125
137
  // bytes per character in the output. That makes this conservative.
126
138
  static char ascii_friendly_chars[256] = "\
@@ -133,6 +145,7 @@ static char ascii_friendly_chars[256] = "\
133
145
  33333333333333333333333333333333\
134
146
  33333333333333333333333333333333";
135
147
 
148
+ // XSS safe mode
136
149
  static char xss_friendly_chars[256] = "\
137
150
  66666666222622666666666666666666\
138
151
  11211161111111121111111111116161\
@@ -143,6 +156,16 @@ static char xss_friendly_chars[256] = "\
143
156
  33333333333333333333333333333333\
144
157
  33333333333333333333333333333333";
145
158
 
159
+ inline static size_t
160
+ newline_friendly_size(const uint8_t *str, size_t len) {
161
+ size_t size = 0;
162
+
163
+ for (; 0 < len; str++, len--) {
164
+ size += newline_friendly_chars[*str];
165
+ }
166
+ return size - len * (size_t)'0';
167
+ }
168
+
146
169
  inline static size_t
147
170
  hibit_friendly_size(const uint8_t *str, size_t len) {
148
171
  size_t size = 0;
@@ -462,6 +485,10 @@ dump_cstr(const char *str, size_t cnt, int is_sym, int escape1, Out out) {
462
485
  char *cmap;
463
486
 
464
487
  switch (out->opts->escape_mode) {
488
+ case NLEsc:
489
+ cmap = newline_friendly_chars;
490
+ size = newline_friendly_size((uint8_t*)str, cnt);
491
+ break;
465
492
  case ASCIIEsc:
466
493
  cmap = ascii_friendly_chars;
467
494
  size = ascii_friendly_size((uint8_t*)str, cnt);
@@ -517,11 +517,21 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
517
517
  rb_ary_push(stack_peek(&pi->stack)->val, str_to_value(pi, str, len, orig));
518
518
  }
519
519
 
520
+ static void
521
+ array_append_num(ParseInfo pi, NumInfo ni) {
522
+ rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
523
+ }
524
+
520
525
  static void
521
526
  add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
522
527
  pi->stack.head->val = str_to_value(pi, str, len, orig);
523
528
  }
524
529
 
530
+ static void
531
+ add_num(ParseInfo pi, NumInfo ni) {
532
+ pi->stack.head->val = oj_num_as_value(ni);
533
+ }
534
+
525
535
  void
526
536
  oj_set_object_callbacks(ParseInfo pi) {
527
537
  oj_set_strict_callbacks(pi);
@@ -531,7 +541,9 @@ oj_set_object_callbacks(ParseInfo pi) {
531
541
  pi->hash_set_num = hash_set_num;
532
542
  pi->hash_set_value = hash_set_value;
533
543
  pi->add_cstr = add_cstr;
544
+ pi->add_num = add_num;
534
545
  pi->array_append_cstr = array_append_cstr;
546
+ pi->array_append_num = array_append_num;
535
547
  }
536
548
 
537
549
  VALUE
@@ -560,7 +572,9 @@ oj_object_parse_cstr(int argc, VALUE *argv, char *json, size_t len) {
560
572
  pi.hash_set_num = hash_set_num;
561
573
  pi.hash_set_value = hash_set_value;
562
574
  pi.add_cstr = add_cstr;
575
+ pi.add_num = add_num;
563
576
  pi.array_append_cstr = array_append_cstr;
577
+ pi.array_append_num = array_append_num;
564
578
 
565
579
  return oj_pi_parse(argc, argv, &pi, json, len, 1);
566
580
  }
@@ -114,6 +114,7 @@ static VALUE float_sym;
114
114
  static VALUE indent_sym;
115
115
  static VALUE json_sym;
116
116
  static VALUE mode_sym;
117
+ static VALUE newline_sym;
117
118
  static VALUE nilnil_sym;
118
119
  static VALUE null_sym;
119
120
  static VALUE object_sym;
@@ -180,7 +181,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
180
181
  * - circular: [true|false|nil] support circular references while dumping
181
182
  * - auto_define: [true|false|nil] automatically define classes if they do not exist
182
183
  * - symbol_keys: [true|false|nil] use symbols instead of strings for hash keys
183
- * - escape_mode: [:json|:xss_safe|:ascii|nil] determines the characters to escape
184
+ * - escape_mode: [:newline|:json|:xss_safe|:ascii|nil] determines the characters to escape
184
185
  * - class_cache: [true|false|nil] cache classes for faster parsing (if dynamically modifying classes or reloading classes then don't use this)
185
186
  * - mode: [:object|:strict|:compat|:null] load and dump modes to use for JSON
186
187
  * - time_format: [:unix|:xmlschema|:ruby] time format when dumping in :compat mode
@@ -217,6 +218,7 @@ get_def_opts(VALUE self) {
217
218
  default: rb_hash_aset(opts, mode_sym, object_sym); break;
218
219
  }
219
220
  switch (oj_default_options.escape_mode) {
221
+ case NLEsc: rb_hash_aset(opts, escape_mode_sym, newline_sym); break;
220
222
  case JSONEsc: rb_hash_aset(opts, escape_mode_sym, json_sym); break;
221
223
  case XSSEsc: rb_hash_aset(opts, escape_mode_sym, xss_safe_sym); break;
222
224
  case ASCIIEsc: rb_hash_aset(opts, escape_mode_sym, ascii_sym); break;
@@ -248,8 +250,9 @@ get_def_opts(VALUE self) {
248
250
  * @param [true|false|nil] :auto_define automatically define classes if they do not exist
249
251
  * @param [true|false|nil] :symbol_keys convert hash keys to symbols
250
252
  * @param [true|false|nil] :class_cache cache classes for faster parsing
251
- * @param [:json|:xss_safe|:ascii|nil] :escape mode encodes all high-bit characters as
253
+ * @param [:newline|:json|:xss_safe|:ascii|nil] :escape mode encodes all high-bit characters as
252
254
  * escaped sequences if :ascii, :json is standand UTF-8 JSON encoding,
255
+ * :newline is the same as :json but newlines are not escaped,
253
256
  * and :xss_safe escapes &, <, and >, and some others.
254
257
  * @param [true|false|nil] :bigdecimal_as_decimal dump BigDecimal as a decimal number or as a String
255
258
  * @param [:bigdecimal|:float|:auto|nil] :bigdecimal_load load decimals as BigDecimal instead of as a Float. :auto pick the most precise for the number of digits.
@@ -341,6 +344,8 @@ set_def_opts(VALUE self, VALUE opts) {
341
344
  v = rb_hash_lookup(opts, escape_mode_sym);
342
345
  if (Qnil == v) {
343
346
  // ignore
347
+ } else if (newline_sym == v) {
348
+ oj_default_options.escape_mode = NLEsc;
344
349
  } else if (json_sym == v) {
345
350
  oj_default_options.escape_mode = JSONEsc;
346
351
  } else if (xss_safe_sym == v) {
@@ -471,14 +476,16 @@ oj_parse_options(VALUE ropts, Options copts) {
471
476
  }
472
477
 
473
478
  if (Qnil != (v = rb_hash_lookup(ropts, escape_mode_sym))) {
474
- if (json_sym == v) {
479
+ if (newline_sym == v) {
480
+ copts->escape_mode = NLEsc;
481
+ } else if (json_sym == v) {
475
482
  copts->escape_mode = JSONEsc;
476
483
  } else if (xss_safe_sym == v) {
477
484
  copts->escape_mode = XSSEsc;
478
485
  } else if (ascii_sym == v) {
479
486
  copts->escape_mode = ASCIIEsc;
480
487
  } else {
481
- rb_raise(rb_eArgError, ":encoding must be :json, :rails, or :ascii.");
488
+ rb_raise(rb_eArgError, ":encoding must be :newline, :json, :xss_safe, or :ascii.");
482
489
  }
483
490
  }
484
491
 
@@ -1993,7 +2000,6 @@ void Init_oj() {
1993
2000
  bigdecimal_load_sym = ID2SYM(rb_intern("bigdecimal_load"));rb_gc_register_address(&bigdecimal_load_sym);
1994
2001
  bigdecimal_sym = ID2SYM(rb_intern("bigdecimal")); rb_gc_register_address(&bigdecimal_sym);
1995
2002
  circular_sym = ID2SYM(rb_intern("circular")); rb_gc_register_address(&circular_sym);
1996
- nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
1997
2003
  class_cache_sym = ID2SYM(rb_intern("class_cache")); rb_gc_register_address(&class_cache_sym);
1998
2004
  compat_sym = ID2SYM(rb_intern("compat")); rb_gc_register_address(&compat_sym);
1999
2005
  create_id_sym = ID2SYM(rb_intern("create_id")); rb_gc_register_address(&create_id_sym);
@@ -2002,6 +2008,8 @@ void Init_oj() {
2002
2008
  indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
2003
2009
  json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
2004
2010
  mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
2011
+ newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
2012
+ nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
2005
2013
  null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
2006
2014
  object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
2007
2015
  quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&quirks_mode_sym);
@@ -87,6 +87,7 @@ typedef enum {
87
87
  } TimeFormat;
88
88
 
89
89
  typedef enum {
90
+ NLEsc = 'n',
90
91
  JSONEsc = 'j',
91
92
  XSSEsc = 'x',
92
93
  ASCIIEsc = 'a'
@@ -38,9 +38,6 @@
38
38
  #include "parse.h"
39
39
  #include "encode.h"
40
40
 
41
- // Workaround in case INFINITY is not defined in math.h or if the OS is CentOS
42
- #define OJ_INFINITY (1.0/0.0)
43
-
44
41
  static void
45
42
  noop_end(struct _ParseInfo *pi) {
46
43
  }
@@ -60,6 +57,9 @@ add_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
60
57
 
61
58
  static void
62
59
  add_num(ParseInfo pi, NumInfo ni) {
60
+ if (ni->infinity || ni->nan) {
61
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
62
+ }
63
63
  pi->stack.head->val = oj_num_as_value(ni);
64
64
  }
65
65
 
@@ -89,6 +89,9 @@ hash_set_cstr(ParseInfo pi, const char *key, size_t klen, const char *str, size_
89
89
 
90
90
  static void
91
91
  hash_set_num(struct _ParseInfo *pi, const char *key, size_t klen, NumInfo ni) {
92
+ if (ni->infinity || ni->nan) {
93
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
94
+ }
92
95
  rb_hash_aset(stack_peek(&pi->stack)->val, hash_key(pi, key, klen), oj_num_as_value(ni));
93
96
  }
94
97
 
@@ -112,6 +115,9 @@ array_append_cstr(ParseInfo pi, const char *str, size_t len, const char *orig) {
112
115
 
113
116
  static void
114
117
  array_append_num(ParseInfo pi, NumInfo ni) {
118
+ if (ni->infinity || ni->nan) {
119
+ oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "not a number or other value");
120
+ }
115
121
  rb_ary_push(stack_peek(&pi->stack)->val, oj_num_as_value(ni));
116
122
  }
117
123
 
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '2.9.7'
4
+ VERSION = '2.9.8'
5
5
  end
@@ -79,6 +79,8 @@ class FileJuice < Minitest::Test
79
79
  end
80
80
 
81
81
  def test_float
82
+ mode = opts = Oj.default_options()[:mode]
83
+ Oj.default_options = {:mode => :object}
82
84
  dump_and_load(0.0, false)
83
85
  dump_and_load(12345.6789, false)
84
86
  dump_and_load(70.35, false)
@@ -87,6 +89,7 @@ class FileJuice < Minitest::Test
87
89
  dump_and_load(2.48e100 * 1.0e10, false)
88
90
  dump_and_load(-2.48e100 * 1.0e10, false)
89
91
  dump_and_load(1/0.0, false)
92
+ Oj.default_options = {:mode => mode}
90
93
  end
91
94
 
92
95
  def test_string
@@ -167,6 +167,8 @@ class Juice < Minitest::Test
167
167
  end
168
168
 
169
169
  def test_float
170
+ mode = opts = Oj.default_options()[:mode]
171
+ Oj.default_options = {:mode => :object}
170
172
  dump_and_load(0.0, false)
171
173
  dump_and_load(12345.6789, false)
172
174
  dump_and_load(70.35, false)
@@ -180,6 +182,7 @@ class Juice < Minitest::Test
180
182
  assert_equal('NaN', json)
181
183
  loaded = Oj.load(json);
182
184
  assert_equal(true, loaded.nan?)
185
+ Oj.default_options = {:mode => mode}
183
186
  end
184
187
 
185
188
  def test_string
@@ -241,7 +244,7 @@ class Juice < Minitest::Test
241
244
  assert(false, "*** expected an exception")
242
245
  end
243
246
 
244
- # rails encoding tests
247
+ # encoding tests
245
248
  def test_does_not_escape_entities_by_default
246
249
  Oj.default_options = { :escape_mode => :ascii } # set in mimic mode
247
250
  # use Oj to create the hash since some Rubies don't deal nicely with unicode.
@@ -271,6 +274,20 @@ class Juice < Minitest::Test
271
274
  out = Oj.dump(hash, :escape_mode => :xss_safe)
272
275
  assert_equal(%{{"key":"\\u003cscript\\u003ealert(123) \\u0026\\u0026 formatHD()\\u003c\\/script\\u003e"}}, out)
273
276
  end
277
+ def test_escape_newline_by_default
278
+ Oj.default_options = { :escape_mode => :json }
279
+ json = %{["one","two\\n2"]}
280
+ x = Oj.load(json)
281
+ out = Oj.dump(x)
282
+ assert_equal(json, out)
283
+ end
284
+ def test_does_not_escape_newline
285
+ Oj.default_options = { :escape_mode => :newline }
286
+ json = %{["one","two\n2"]}
287
+ x = Oj.load(json)
288
+ out = Oj.dump(x)
289
+ assert_equal(json, out)
290
+ end
274
291
 
275
292
  # Symbol
276
293
  def test_symbol_strict
@@ -878,6 +895,24 @@ class Juice < Minitest::Test
878
895
  assert_equal('-Infinity', json)
879
896
  end
880
897
 
898
+ def test_infinity
899
+ n = Oj.load('Infinity', :mode => :object)
900
+ assert_equal(Float::INFINITY, n);
901
+ begin
902
+ Oj.load('Infinity', :mode => :strict)
903
+ fail()
904
+ rescue Oj::ParseError
905
+ assert(true)
906
+ end
907
+ begin
908
+ Oj.load('Infinity', :mode => :compat)
909
+ fail()
910
+ rescue Oj::ParseError
911
+ assert(true)
912
+ end
913
+
914
+ end
915
+
881
916
  # Date
882
917
  def test_date_strict
883
918
  begin
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: 2.9.7
4
+ version: 2.9.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: 2014-06-24 00:00:00.000000000 Z
11
+ date: 2014-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler