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 +4 -4
- data/README.md +4 -23
- data/ext/oj/dump.c +28 -1
- data/ext/oj/object.c +14 -0
- data/ext/oj/oj.c +13 -5
- data/ext/oj/oj.h +1 -0
- data/ext/oj/strict.c +9 -3
- data/lib/oj/version.rb +1 -1
- data/test/test_file.rb +3 -0
- data/test/test_various.rb +36 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 080ee5fb844d326ce444282c5df529a135cf125b
|
4
|
+
data.tar.gz: 6461af3c663d8974e0eea8c8b4e3e811500a7397
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
29
|
+
### Current Release 2.9.8
|
30
30
|
|
31
|
-
- Changed
|
31
|
+
- Changed escaping back to previous release and added a new escape mode.
|
32
32
|
|
33
|
-
-
|
34
|
-
|
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
|
|
data/ext/oj/dump.c
CHANGED
@@ -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
|
-
|
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);
|
data/ext/oj/object.c
CHANGED
@@ -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
|
}
|
data/ext/oj/oj.c
CHANGED
@@ -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 (
|
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, :
|
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);
|
data/ext/oj/oj.h
CHANGED
data/ext/oj/strict.c
CHANGED
@@ -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
|
|
data/lib/oj/version.rb
CHANGED
data/test/test_file.rb
CHANGED
@@ -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
|
data/test/test_various.rb
CHANGED
@@ -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
|
-
#
|
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.
|
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-
|
11
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|