oj 1.3.5 → 1.3.6
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.
- data/README.md +4 -2
- data/ext/oj/fast.c +10 -0
- data/ext/oj/load.c +12 -1
- data/lib/oj/version.rb +1 -1
- data/test/tests.rb +14 -2
- metadata +2 -2
data/README.md
CHANGED
@@ -32,9 +32,11 @@ A fast JSON parser and Object marshaller as a Ruby gem.
|
|
32
32
|
|
33
33
|
## <a name="release">Release Notes</a>
|
34
34
|
|
35
|
-
### Release 1.3.
|
35
|
+
### Release 1.3.6
|
36
36
|
|
37
|
-
-
|
37
|
+
- Oj.load() now raises a SystemStackError if a JSON is too deeply nested. The loading is allowed to use on 75% of the stack.
|
38
|
+
|
39
|
+
- Oj::Doc.open() now raises a SystemStackError if a JSON is too deeply nested. The loading is allowed to use on 75% of the stack. Oj::Doc.open will allow much deeper nesting than Oj.load().
|
38
40
|
|
39
41
|
## <a name="description">Description</a>
|
40
42
|
|
data/ext/oj/fast.c
CHANGED
@@ -63,6 +63,7 @@ typedef struct _ParseInfo {
|
|
63
63
|
char *str; /* buffer being read from */
|
64
64
|
char *s; /* current position in buffer */
|
65
65
|
Doc doc;
|
66
|
+
uint64_t stack_min;
|
66
67
|
} *ParseInfo;
|
67
68
|
|
68
69
|
static void leaf_init(Leaf leaf, int type);
|
@@ -477,6 +478,9 @@ static Leaf
|
|
477
478
|
read_next(ParseInfo pi) {
|
478
479
|
Leaf leaf = 0;
|
479
480
|
|
481
|
+
if ((uint64_t)&leaf < pi->stack_min) {
|
482
|
+
rb_raise(rb_eSysStackError, "JSON is too deeply nested");
|
483
|
+
}
|
480
484
|
next_non_white(pi); // skip white space
|
481
485
|
switch (*pi->s) {
|
482
486
|
case '{':
|
@@ -827,6 +831,7 @@ parse_json(VALUE clas, char *json, int given, int allocated) {
|
|
827
831
|
VALUE result = Qnil;
|
828
832
|
Doc doc;
|
829
833
|
int ex = 0;
|
834
|
+
struct rlimit lim;
|
830
835
|
|
831
836
|
if (given) {
|
832
837
|
doc = ALLOCA_N(struct _Doc, 1);
|
@@ -837,6 +842,11 @@ parse_json(VALUE clas, char *json, int given, int allocated) {
|
|
837
842
|
pi.s = pi.str;
|
838
843
|
doc_init(doc);
|
839
844
|
pi.doc = doc;
|
845
|
+
if (0 == getrlimit(RLIMIT_STACK, &lim)) {
|
846
|
+
pi.stack_min = (uint64_t)&lim - (lim.rlim_cur / 4 * 3); // let 3/4ths of the stack be used only
|
847
|
+
} else {
|
848
|
+
pi.stack_min = 0; // indicates not to check stack limit
|
849
|
+
}
|
840
850
|
// last arg is free func void* func(void*)
|
841
851
|
doc->self = rb_data_object_alloc(clas, doc, 0, free_doc_cb);
|
842
852
|
rb_gc_register_address(&doc->self);
|
data/ext/oj/load.c
CHANGED
@@ -29,8 +29,9 @@
|
|
29
29
|
*/
|
30
30
|
|
31
31
|
#ifdef SAFE_CACHE
|
32
|
-
#include <pthread.h>
|
32
|
+
#include <pthread.h>
|
33
33
|
#endif
|
34
|
+
#include <sys/resource.h>
|
34
35
|
#include <stdlib.h>
|
35
36
|
#include <stdio.h>
|
36
37
|
#include <string.h>
|
@@ -59,6 +60,7 @@ typedef struct _ParseInfo {
|
|
59
60
|
char *s; /* current position in buffer */
|
60
61
|
CircArray circ_array;
|
61
62
|
Options options;
|
63
|
+
uint64_t stack_min;
|
62
64
|
} *ParseInfo;
|
63
65
|
|
64
66
|
static CircArray circ_array_new(void);
|
@@ -319,6 +321,9 @@ static VALUE
|
|
319
321
|
read_next(ParseInfo pi, int hint) {
|
320
322
|
VALUE obj;
|
321
323
|
|
324
|
+
if ((uint64_t)&obj < pi->stack_min) {
|
325
|
+
rb_raise(rb_eSysStackError, "JSON is too deeply nested");
|
326
|
+
}
|
322
327
|
next_non_white(pi); // skip white space
|
323
328
|
switch (*pi->s) {
|
324
329
|
case '{':
|
@@ -998,6 +1003,7 @@ VALUE
|
|
998
1003
|
oj_parse(char *json, Options options) {
|
999
1004
|
VALUE obj;
|
1000
1005
|
struct _ParseInfo pi;
|
1006
|
+
struct rlimit lim;
|
1001
1007
|
|
1002
1008
|
if (0 == json) {
|
1003
1009
|
raise_error("Invalid arg, xml string can not be null", json, 0);
|
@@ -1010,6 +1016,11 @@ oj_parse(char *json, Options options) {
|
|
1010
1016
|
pi.circ_array = circ_array_new();
|
1011
1017
|
}
|
1012
1018
|
pi.options = options;
|
1019
|
+
if (0 == getrlimit(RLIMIT_STACK, &lim)) {
|
1020
|
+
pi.stack_min = (uint64_t)&lim - (lim.rlim_cur / 4 * 3); // let 3/4ths of the stack be used only
|
1021
|
+
} else {
|
1022
|
+
pi.stack_min = 0; // indicates not to check stack limit
|
1023
|
+
}
|
1013
1024
|
obj = read_next(&pi, 0);
|
1014
1025
|
if (Yes == options->circular) {
|
1015
1026
|
circ_array_free(pi.circ_array);
|
data/lib/oj/version.rb
CHANGED
data/test/tests.rb
CHANGED
@@ -275,7 +275,13 @@ class Juice < ::Test::Unit::TestCase
|
|
275
275
|
t = Time.local(2012, 1, 5, 23, 58, 7, 123456)
|
276
276
|
json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
|
277
277
|
tz = t.utc_offset
|
278
|
-
|
278
|
+
# Ruby does not handle a %+02d properly so...
|
279
|
+
sign = '+'
|
280
|
+
if 0 > tz
|
281
|
+
sign = '-'
|
282
|
+
tz = -tz
|
283
|
+
end
|
284
|
+
assert_equal(%{"2012-01-05T23:58:07.123456000%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
|
279
285
|
end
|
280
286
|
end
|
281
287
|
def test_xml_time_compat_no_secs
|
@@ -288,7 +294,13 @@ class Juice < ::Test::Unit::TestCase
|
|
288
294
|
t = Time.local(2012, 1, 5, 23, 58, 7, 0)
|
289
295
|
json = Oj.dump(t, :mode => :compat, :time_format => :xmlschema)
|
290
296
|
tz = t.utc_offset
|
291
|
-
|
297
|
+
# Ruby does not handle a %+02d properly so...
|
298
|
+
sign = '+'
|
299
|
+
if 0 > tz
|
300
|
+
sign = '-'
|
301
|
+
tz = -tz
|
302
|
+
end
|
303
|
+
assert_equal(%{"2012-01-05T23:58:07%s%02d:%02d"} % [sign, tz / 3600, tz / 60 % 60], json)
|
292
304
|
end
|
293
305
|
end
|
294
306
|
def test_xml_time_compat_zulu
|
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: 1.3.
|
4
|
+
version: 1.3.6
|
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: 2012-
|
12
|
+
date: 2012-10-04 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: ! 'The fastest JSON parser and object serializer. '
|
15
15
|
email: peter@ohler.com
|