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 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.5
35
+ ### Release 1.3.6
36
36
 
37
- - Fixed mimic_JSON so it convinces Ruby that the **ALL** versions of the json gem are already loaded.
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
 
@@ -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);
@@ -29,8 +29,9 @@
29
29
  */
30
30
 
31
31
  #ifdef SAFE_CACHE
32
- #include <pthread.h> // TBD LOCK
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);
@@ -1,5 +1,5 @@
1
1
 
2
2
  module Oj
3
3
  # Current version of the module.
4
- VERSION = '1.3.5'
4
+ VERSION = '1.3.6'
5
5
  end
@@ -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
- assert_equal(%{"2012-01-05T23:58:07.123456000+%02d:%02d"} % [tz / 3600, tz / 60 % 60], json)
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
- assert_equal(%{"2012-01-05T23:58:07+%02d:%02d"} % [tz / 3600, tz / 60 % 60], json)
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.5
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-09-25 00:00:00.000000000 Z
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