oj 2.15.1 → 2.16.0
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.
- data/README.md +6 -2
- data/ext/oj/oj.c +10 -1
- data/ext/oj/oj.h +1 -0
- data/ext/oj/parse.c +7 -2
- data/ext/oj/sparse.c +8 -2
- data/lib/oj/version.rb +1 -1
- data/test/test_various.rb +22 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -170,9 +170,13 @@ Oj.default_options = {:mode => :compat }
|
|
170
170
|
|
171
171
|
## Releases
|
172
172
|
|
173
|
-
**Release 2.
|
173
|
+
**Release 2.16.0**
|
174
174
|
|
175
|
-
-
|
175
|
+
- Added option to allow invalid unicode characters. This is not a suggested
|
176
|
+
option in a majority of the cases.
|
177
|
+
|
178
|
+
- Fixed float parsing for 32 bit systems so that it does not roll over to
|
179
|
+
BigDecimal until more than 15 significant digits.
|
176
180
|
|
177
181
|
[Older release notes](http://www.ohler.com/dev/oj_misc/release_notes.html).
|
178
182
|
|
data/ext/oj/oj.c
CHANGED
@@ -106,6 +106,7 @@ VALUE oj_struct_class;
|
|
106
106
|
VALUE oj_slash_string;
|
107
107
|
|
108
108
|
static VALUE allow_gc_sym;
|
109
|
+
static VALUE allow_invalid_unicode_sym;
|
109
110
|
static VALUE ascii_only_sym;
|
110
111
|
static VALUE ascii_sym;
|
111
112
|
static VALUE auto_define_sym;
|
@@ -181,6 +182,7 @@ struct _Options oj_default_options = {
|
|
181
182
|
No, // nilnil
|
182
183
|
Yes, // allow_gc
|
183
184
|
Yes, // quirks_mode
|
185
|
+
No, // allow_invalid
|
184
186
|
json_class, // create_id
|
185
187
|
10, // create_id_len
|
186
188
|
9, // sec_prec
|
@@ -224,6 +226,7 @@ static VALUE define_mimic_json(int argc, VALUE *argv, VALUE self);
|
|
224
226
|
* - nilnil: [true|false|nil] if true a nil input to load will return nil and not raise an Exception
|
225
227
|
* - allow_gc: [true|false|nil] allow or prohibit GC during parsing, default is true (allow)
|
226
228
|
* - quirks_mode: [true,|false|nil] Allow single JSON values instead of documents, default is true (allow)
|
229
|
+
* - allow_invalid_unicode: [true,|false|nil] Allow invalid unicode, default is false (don't allow)
|
227
230
|
* - indent_str: [String|nil] String to use for indentation, overriding the indent option is not nil
|
228
231
|
* - space: [String|nil] String to use for the space after the colon in JSON object fields
|
229
232
|
* - space_before: [String|nil] String to use before the colon separator in JSON object fields
|
@@ -251,6 +254,7 @@ get_def_opts(VALUE self) {
|
|
251
254
|
rb_hash_aset(opts, nilnil_sym, (Yes == oj_default_options.nilnil) ? Qtrue : ((No == oj_default_options.nilnil) ? Qfalse : Qnil));
|
252
255
|
rb_hash_aset(opts, allow_gc_sym, (Yes == oj_default_options.allow_gc) ? Qtrue : ((No == oj_default_options.allow_gc) ? Qfalse : Qnil));
|
253
256
|
rb_hash_aset(opts, quirks_mode_sym, (Yes == oj_default_options.quirks_mode) ? Qtrue : ((No == oj_default_options.quirks_mode) ? Qfalse : Qnil));
|
257
|
+
rb_hash_aset(opts, allow_invalid_unicode_sym, (Yes == oj_default_options.allow_invalid) ? Qtrue : ((No == oj_default_options.allow_invalid) ? Qfalse : Qnil));
|
254
258
|
rb_hash_aset(opts, float_prec_sym, INT2FIX(oj_default_options.float_prec));
|
255
259
|
switch (oj_default_options.mode) {
|
256
260
|
case StrictMode: rb_hash_aset(opts, mode_sym, strict_sym); break;
|
@@ -331,6 +335,7 @@ get_def_opts(VALUE self) {
|
|
331
335
|
* @param [true|false|nil] :nilnil if true a nil input to load will return nil and not raise an Exception
|
332
336
|
* @param [true|false|nil] :allow_gc allow or prohibit GC during parsing, default is true (allow)
|
333
337
|
* @param [true|false|nil] :quirks_mode allow single JSON values instead of documents, default is true (allow)
|
338
|
+
* @param [true|false|nil] :allow_invalid_unicode allow invalid unicode, default is false (don't allow)
|
334
339
|
* @param [String|nil] :space String to use for the space after the colon in JSON object fields
|
335
340
|
* @param [String|nil] :space_before String to use before the colon separator in JSON object fields
|
336
341
|
* @param [String|nil] :object_nl String to use after a JSON object field value
|
@@ -358,6 +363,7 @@ oj_parse_options(VALUE ropts, Options copts) {
|
|
358
363
|
{ nilnil_sym, &copts->nilnil },
|
359
364
|
{ allow_gc_sym, &copts->allow_gc },
|
360
365
|
{ quirks_mode_sym, &copts->quirks_mode },
|
366
|
+
{ allow_invalid_unicode_sym, &copts->allow_invalid },
|
361
367
|
{ Qnil, 0 }
|
362
368
|
};
|
363
369
|
YesNoOpt o;
|
@@ -1765,6 +1771,7 @@ mimic_parse(int argc, VALUE *argv, VALUE self) {
|
|
1765
1771
|
pi.options = oj_default_options;
|
1766
1772
|
pi.options.auto_define = No;
|
1767
1773
|
pi.options.quirks_mode = No;
|
1774
|
+
pi.options.allow_invalid = No;
|
1768
1775
|
|
1769
1776
|
if (2 <= argc) {
|
1770
1777
|
VALUE ropts = argv[1];
|
@@ -1845,6 +1852,7 @@ static struct _Options mimic_object_to_json_options = {
|
|
1845
1852
|
Yes, // nilnil
|
1846
1853
|
Yes, // allow_gc
|
1847
1854
|
Yes, // quirks_mode
|
1855
|
+
No, // allow_invalid
|
1848
1856
|
json_class, // create_id
|
1849
1857
|
10, // create_id_len
|
1850
1858
|
9, // sec_prec
|
@@ -2170,13 +2178,14 @@ void Init_oj() {
|
|
2170
2178
|
indent_sym = ID2SYM(rb_intern("indent")); rb_gc_register_address(&indent_sym);
|
2171
2179
|
json_sym = ID2SYM(rb_intern("json")); rb_gc_register_address(&json_sym);
|
2172
2180
|
mode_sym = ID2SYM(rb_intern("mode")); rb_gc_register_address(&mode_sym);
|
2173
|
-
nan_sym = ID2SYM(rb_intern("nan"));
|
2181
|
+
nan_sym = ID2SYM(rb_intern("nan")); rb_gc_register_address(&nan_sym);
|
2174
2182
|
newline_sym = ID2SYM(rb_intern("newline")); rb_gc_register_address(&newline_sym);
|
2175
2183
|
nilnil_sym = ID2SYM(rb_intern("nilnil")); rb_gc_register_address(&nilnil_sym);
|
2176
2184
|
null_sym = ID2SYM(rb_intern("null")); rb_gc_register_address(&null_sym);
|
2177
2185
|
object_nl_sym = ID2SYM(rb_intern("object_nl")); rb_gc_register_address(&object_nl_sym);
|
2178
2186
|
object_sym = ID2SYM(rb_intern("object")); rb_gc_register_address(&object_sym);
|
2179
2187
|
quirks_mode_sym = ID2SYM(rb_intern("quirks_mode")); rb_gc_register_address(&quirks_mode_sym);
|
2188
|
+
allow_invalid_unicode_sym = ID2SYM(rb_intern("allow_invalid_unicode"));rb_gc_register_address(&allow_invalid_unicode_sym);
|
2180
2189
|
raise_sym = ID2SYM(rb_intern("raise")); rb_gc_register_address(&raise_sym);
|
2181
2190
|
ruby_sym = ID2SYM(rb_intern("ruby")); rb_gc_register_address(&ruby_sym);
|
2182
2191
|
sec_prec_sym = ID2SYM(rb_intern("second_precision"));rb_gc_register_address(&sec_prec_sym);
|
data/ext/oj/oj.h
CHANGED
@@ -156,6 +156,7 @@ typedef struct _Options {
|
|
156
156
|
char nilnil; // YesNo
|
157
157
|
char allow_gc; // allow GC during parse
|
158
158
|
char quirks_mode; // allow single JSON values instead of documents
|
159
|
+
char allow_invalid; // YesNo - allow invalid unicode
|
159
160
|
const char *create_id; // 0 or string
|
160
161
|
size_t create_id_len; // length of create_id
|
161
162
|
int sec_prec; // second precision when dumping time
|
data/ext/oj/parse.c
CHANGED
@@ -255,6 +255,11 @@ read_escaped_str(ParseInfo pi, const char *start) {
|
|
255
255
|
|
256
256
|
s++;
|
257
257
|
if ('\\' != *s || 'u' != *(s + 1)) {
|
258
|
+
if (Yes == pi->options.allow_invalid) {
|
259
|
+
s--;
|
260
|
+
unicode_to_chars(pi, &buf, code);
|
261
|
+
break;
|
262
|
+
}
|
258
263
|
pi->cur = s;
|
259
264
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
260
265
|
buf_cleanup(&buf);
|
@@ -437,7 +442,7 @@ read_num(ParseInfo pi) {
|
|
437
442
|
int d = (*pi->cur - '0');
|
438
443
|
|
439
444
|
ni.i = ni.i * 10 + d;
|
440
|
-
if (
|
445
|
+
if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
|
441
446
|
ni.big = 1;
|
442
447
|
}
|
443
448
|
}
|
@@ -453,7 +458,7 @@ read_num(ParseInfo pi) {
|
|
453
458
|
ni.num = ni.num * 10 + d;
|
454
459
|
ni.div *= 10;
|
455
460
|
ni.di++;
|
456
|
-
if (
|
461
|
+
if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
|
457
462
|
ni.big = 1;
|
458
463
|
}
|
459
464
|
}
|
data/ext/oj/sparse.c
CHANGED
@@ -265,6 +265,12 @@ read_escaped_str(ParseInfo pi) {
|
|
265
265
|
c = reader_get(&pi->rd);
|
266
266
|
ch2 = reader_get(&pi->rd);
|
267
267
|
if ('\\' != c || 'u' != ch2) {
|
268
|
+
if (Yes == pi->options.allow_invalid) {
|
269
|
+
unicode_to_chars(pi, &buf, code);
|
270
|
+
reader_backup(&pi->rd);
|
271
|
+
reader_backup(&pi->rd);
|
272
|
+
break;
|
273
|
+
}
|
268
274
|
oj_set_error_at(pi, oj_parse_error_class, __FILE__, __LINE__, "invalid escaped character");
|
269
275
|
buf_cleanup(&buf);
|
270
276
|
return;
|
@@ -440,7 +446,7 @@ read_num(ParseInfo pi) {
|
|
440
446
|
int d = (c - '0');
|
441
447
|
|
442
448
|
ni.i = ni.i * 10 + d;
|
443
|
-
if (
|
449
|
+
if (INT64_MAX <= ni.i || DEC_MAX < dec_cnt) {
|
444
450
|
ni.big = 1;
|
445
451
|
}
|
446
452
|
}
|
@@ -456,7 +462,7 @@ read_num(ParseInfo pi) {
|
|
456
462
|
ni.num = ni.num * 10 + d;
|
457
463
|
ni.div *= 10;
|
458
464
|
ni.di++;
|
459
|
-
if (
|
465
|
+
if (INT64_MAX <= ni.div || DEC_MAX < dec_cnt) {
|
460
466
|
ni.big = 1;
|
461
467
|
}
|
462
468
|
}
|
data/lib/oj/version.rb
CHANGED
data/test/test_various.rb
CHANGED
@@ -106,6 +106,7 @@ class Juice < Minitest::Test
|
|
106
106
|
:nilnil=>false,
|
107
107
|
:allow_gc=>true,
|
108
108
|
:quirks_mode=>true,
|
109
|
+
:allow_invalid_unicode=>false,
|
109
110
|
:float_precision=>15,
|
110
111
|
:mode=>:object,
|
111
112
|
:escape_mode=>:json,
|
@@ -128,6 +129,7 @@ class Juice < Minitest::Test
|
|
128
129
|
:nilnil=>true,
|
129
130
|
:allow_gc=>false,
|
130
131
|
:quirks_mode=>false,
|
132
|
+
:allow_invalid_unicode=>true,
|
131
133
|
:float_precision=>13,
|
132
134
|
:mode=>:strict,
|
133
135
|
:escape_mode=>:ascii,
|
@@ -288,6 +290,26 @@ class Juice < Minitest::Test
|
|
288
290
|
assert_equal(json, json2)
|
289
291
|
end
|
290
292
|
|
293
|
+
def test_invalid_unicode_raise
|
294
|
+
# validate that an invalid unicode raises unless the :allow_invalid_unicode is true
|
295
|
+
json = %{"x\\ud83dy"}
|
296
|
+
begin
|
297
|
+
obj = Oj.load(json)
|
298
|
+
rescue Exception
|
299
|
+
assert(true)
|
300
|
+
return
|
301
|
+
end
|
302
|
+
assert(false, "*** expected an exception")
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_invalid_unicode_ok
|
306
|
+
# validate that an invalid unicode raises unless the :allow_invalid_unicode is true
|
307
|
+
json = %{"x\\ud83dy"}
|
308
|
+
obj = Oj.load(json, :allow_invalid_unicode => true)
|
309
|
+
# The same as what ruby would do with the invalid encoding.
|
310
|
+
assert_equal("x\xED\xA0\xBDy", obj.to_s)
|
311
|
+
end
|
312
|
+
|
291
313
|
def test_dump_options
|
292
314
|
json = Oj.dump({ 'a' => 1, 'b' => [true, false]},
|
293
315
|
:mode => :compat,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oj
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.16.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-06-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake-compiler
|