json 1.0.4 → 1.1.0

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

Potentially problematic release.


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

data/CHANGES CHANGED
@@ -1,3 +1,14 @@
1
+ 2007-05-21 (1.1.0)
2
+ * Implemented max_nesting feature for parser to avoid stack overflows for
3
+ data from untrusted sources. If you trust the source, you can disable it
4
+ with the option max_nesting => false.
5
+ * Piers Cawley <pdcawley@bofh.org.uk> reported a bug, that not every
6
+ character can be escaped by ?\ as required by RFC4627. There's a
7
+ contradiction between David Crockford's JSON checker test vectors (in
8
+ tests/fixtures) and RFC4627, though. I decided to stick to the RFC, because
9
+ the JSON checker seems to be a bit older than the RFC.
10
+ * Extended license to Ruby License, which includes the GPL.
11
+ * Added keyboard shortcuts, and 'Open location' menu item to edit_json.rb.
1
12
  2007-05-09 (1.0.4)
2
13
  * Applied a patch from Yui NARUSE <naruse@airemix.com> to make JSON compile
3
14
  under Ruby 1.9. Thank you very much for mailing it to me!
@@ -10,7 +21,7 @@
10
21
  2007-03-24 (1.0.2)
11
22
  * Ext Parser didn't parse 0e0 correctly into 0.0: Fixed!
12
23
  2007-03-24 (1.0.1)
13
- * Forgot some object files in the build dir. I really like that- not!
24
+ * Forgot some object files in the build dir. I really like that - not!
14
25
  2007-03-24 (1.0.0)
15
26
  * Added C implementations for the JSON generator and a ragel based JSON
16
27
  parser in C.
@@ -25,7 +36,7 @@
25
36
  well.
26
37
  * Added aliases generate and pretty_generate of unparse and pretty_unparse.
27
38
  * Fixed a test case.
28
- * Catch an Іconv::InvalidEncoding exception, that seems to occur on some Sun
39
+ * Catch an Iconv::InvalidEncoding exception, that seems to occur on some Sun
29
40
  boxes with SunOS 5.8, if iconv doesn't support utf16 conversions. This was
30
41
  reported by Andrew R Jackson <andrewj@bcm.tmc.edu>, thanks a bunch!
31
42
  2006-08-25 (0.4.2)
data/README CHANGED
@@ -73,5 +73,6 @@ Florian Frank <flori@ping.de>
73
73
  License
74
74
  =======
75
75
 
76
- GNU General Public License (GPL), Version 2
77
-
76
+ Ruby License, see the RUBY file included in the source distribution. The Ruby
77
+ License includes the GNU General Public License (GPL), Version 2, so see the
78
+ file GPL as well.
data/RUBY ADDED
@@ -0,0 +1,58 @@
1
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
2
+ You can redistribute it and/or modify it under either the terms of the GPL
3
+ (see COPYING.txt file), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) rename any non-standard executables so the names do not conflict
21
+ with standard executables, which must also be provided.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or executable
26
+ form, provided that you do at least ONE of the following:
27
+
28
+ a) distribute the executables and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard executables non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under this terms.
43
+
44
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
45
+ files under the ./missing directory. See each file for the copying
46
+ condition.
47
+
48
+ 5. The scripts and library files supplied as input to or produced as
49
+ output from the software do not automatically fall under the
50
+ copyright of the software, but belong to whomever generated them,
51
+ and may be sold commercially, and may be aggregated with this
52
+ software.
53
+
54
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
55
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
56
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57
+ PURPOSE.
58
+
data/Rakefile CHANGED
@@ -19,6 +19,7 @@ EXT_GENERATOR_DIR = "#{EXT_ROOT_DIR}/generator"
19
19
  EXT_GENERATOR_DL = "#{EXT_ROOT_DIR}/generator.#{CONFIG['DLEXT']}"
20
20
  EXT_GENERATOR_SRC = "#{EXT_GENERATOR_DIR}/generator.c"
21
21
  RAGEL_CODEGEN = %w[rlcodegen rlgen-cd].find { |c| system(c, '-v') }
22
+ RAGEL_DOTGEN = %w[rlgen-dot rlgen-cd].find { |c| system(c, '-v') }
22
23
  RAGEL_PATH = "#{EXT_PARSER_DIR}/parser.rl"
23
24
  CLEAN.include 'doc', 'coverage', FileList['diagrams/*.*'],
24
25
  FileList["ext/**/*.{so,bundle,#{CONFIG['DLEXT']},o,obj,pdb,lib,manifest,exp,def}"],
@@ -94,7 +95,7 @@ task :ragel_dot_ps do
94
95
  specs = []
95
96
  File.new(RAGEL_PATH).grep(/^\s*machine\s*(\S+);\s*$/) { specs << $1 }
96
97
  for s in specs
97
- sh "ragel #{RAGEL_PATH} -S#{s} | #{RAGEL_CODEGEN} -p -V|dot -Tps -o#{root}/#{s}.ps"
98
+ sh "ragel #{RAGEL_PATH} -S#{s} | #{RAGEL_DOTGEN} -p|dot -Tps -o#{root}/#{s}.ps"
98
99
  end
99
100
  end
100
101
 
@@ -104,7 +105,7 @@ task :ragel_dot_png do
104
105
  specs = []
105
106
  File.new(RAGEL_PATH).grep(/^\s*machine\s*(\S+);\s*$/) { specs << $1 }
106
107
  for s in specs
107
- sh "ragel #{RAGEL_PATH} -S#{s} | #{RAGEL_CODEGEN} -p -V|dot -Tpng -o#{root}/#{s}.png"
108
+ sh "ragel #{RAGEL_PATH} -S#{s} | #{RAGEL_DOTGEN} -p|dot -Tpng -o#{root}/#{s}.png"
108
109
  end
109
110
  end
110
111
 
@@ -252,7 +253,7 @@ task :package_win => :compile do
252
253
  s.require_paths << 'lib'
253
254
 
254
255
  s.bindir = "bin"
255
- s.executables = ["edit_json.rb"]
256
+ s.executables = ["edit_json.rb", "prettify_json.rb"]
256
257
  s.default_executable = "edit_json.rb"
257
258
 
258
259
  s.has_rdoc = true
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.4
1
+ 1.1.0
@@ -3,7 +3,7 @@
3
3
  #include "unicode.h"
4
4
 
5
5
  #define unicode_escape(buffer, character) \
6
- sprintf(buf, "\\u%04x", (unsigned int) (character)); \
6
+ snprintf(buf, 7, "\\u%04x", (unsigned int) (character)); \
7
7
  rb_str_buf_cat(buffer, buf, 6);
8
8
 
9
9
  /*
@@ -3,17 +3,14 @@
3
3
 
4
4
  #include "ruby.h"
5
5
  #include "re.h"
6
+ #include "st.h"
6
7
  #include "unicode.h"
7
8
 
8
- #ifndef swap16
9
- #define swap16(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
10
- #endif
11
-
12
9
  #define EVIL 0x666
13
10
 
14
- static VALUE mJSON, mExt, cParser, eParserError;
11
+ static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
15
12
 
16
- static ID i_json_creatable_p, i_json_create, i_create_id, i_chr;
13
+ static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting;
17
14
 
18
15
  typedef struct JSON_ParserStruct {
19
16
  VALUE Vsource;
@@ -21,6 +18,8 @@ typedef struct JSON_ParserStruct {
21
18
  long len;
22
19
  char *memo;
23
20
  VALUE create_id;
21
+ int max_nesting;
22
+ int current_nesting;
24
23
  } JSON_Parser;
25
24
 
26
25
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
@@ -34,34 +33,39 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
34
33
  JSON_Parser *json; \
35
34
  Data_Get_Struct(self, JSON_Parser, json);
36
35
 
37
- #line 59 "parser.rl"
36
+ #line 58 "parser.rl"
38
37
 
39
38
 
40
39
 
41
- #line 42 "parser.c"
40
+ #line 41 "parser.c"
42
41
  static const int JSON_object_start = 1;
43
42
  static const int JSON_object_first_final = 27;
44
43
  static const int JSON_object_error = 0;
45
44
 
46
45
  static const int JSON_object_en_main = 1;
47
46
 
48
- #line 92 "parser.rl"
47
+ #line 91 "parser.rl"
49
48
 
50
49
 
51
50
  static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
52
51
  {
53
52
  int cs = EVIL;
54
53
  VALUE last_name = Qnil;
54
+
55
+ if (json->max_nesting && json->current_nesting > json->max_nesting) {
56
+ rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
57
+ }
58
+
55
59
  *result = rb_hash_new();
56
60
 
57
61
 
58
- #line 59 "parser.c"
62
+ #line 63 "parser.c"
59
63
  {
60
64
  cs = JSON_object_start;
61
65
  }
62
- #line 101 "parser.rl"
66
+ #line 105 "parser.rl"
63
67
 
64
- #line 65 "parser.c"
68
+ #line 69 "parser.c"
65
69
  {
66
70
  if ( p == pe )
67
71
  goto _out;
@@ -88,7 +92,7 @@ case 2:
88
92
  goto st2;
89
93
  goto st0;
90
94
  tr2:
91
- #line 78 "parser.rl"
95
+ #line 77 "parser.rl"
92
96
  {
93
97
  char *np = JSON_parse_string(json, p, pe, &last_name);
94
98
  if (np == NULL) goto _out3; else {p = (( np))-1;}
@@ -98,7 +102,7 @@ st3:
98
102
  if ( ++p == pe )
99
103
  goto _out3;
100
104
  case 3:
101
- #line 102 "parser.c"
105
+ #line 106 "parser.c"
102
106
  switch( (*p) ) {
103
107
  case 13: goto st3;
104
108
  case 32: goto st3;
@@ -163,7 +167,7 @@ case 8:
163
167
  goto st8;
164
168
  goto st0;
165
169
  tr11:
166
- #line 67 "parser.rl"
170
+ #line 66 "parser.rl"
167
171
  {
168
172
  VALUE v = Qnil;
169
173
  char *np = JSON_parse_value(json, p, pe, &v);
@@ -179,7 +183,7 @@ st9:
179
183
  if ( ++p == pe )
180
184
  goto _out9;
181
185
  case 9:
182
- #line 183 "parser.c"
186
+ #line 187 "parser.c"
183
187
  switch( (*p) ) {
184
188
  case 13: goto st9;
185
189
  case 32: goto st9;
@@ -268,14 +272,14 @@ case 18:
268
272
  goto st9;
269
273
  goto st18;
270
274
  tr4:
271
- #line 83 "parser.rl"
275
+ #line 82 "parser.rl"
272
276
  { goto _out27; }
273
277
  goto st27;
274
278
  st27:
275
279
  if ( ++p == pe )
276
280
  goto _out27;
277
281
  case 27:
278
- #line 279 "parser.c"
282
+ #line 283 "parser.c"
279
283
  goto st0;
280
284
  st19:
281
285
  if ( ++p == pe )
@@ -372,7 +376,7 @@ case 26:
372
376
 
373
377
  _out: {}
374
378
  }
375
- #line 102 "parser.rl"
379
+ #line 106 "parser.rl"
376
380
 
377
381
  if (cs >= JSON_object_first_final) {
378
382
  VALUE klassname = rb_hash_aref(*result, json->create_id);
@@ -389,14 +393,14 @@ case 26:
389
393
  }
390
394
 
391
395
 
392
- #line 393 "parser.c"
396
+ #line 397 "parser.c"
393
397
  static const int JSON_value_start = 1;
394
398
  static const int JSON_value_first_final = 12;
395
399
  static const int JSON_value_error = 0;
396
400
 
397
401
  static const int JSON_value_en_main = 1;
398
402
 
399
- #line 167 "parser.rl"
403
+ #line 177 "parser.rl"
400
404
 
401
405
 
402
406
  static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -404,13 +408,13 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
404
408
  int cs = EVIL;
405
409
 
406
410
 
407
- #line 408 "parser.c"
411
+ #line 412 "parser.c"
408
412
  {
409
413
  cs = JSON_value_start;
410
414
  }
411
- #line 174 "parser.rl"
415
+ #line 184 "parser.rl"
412
416
 
413
- #line 414 "parser.c"
417
+ #line 418 "parser.c"
414
418
  {
415
419
  if ( p == pe )
416
420
  goto _out;
@@ -432,14 +436,14 @@ case 1:
432
436
  st0:
433
437
  goto _out0;
434
438
  tr0:
435
- #line 132 "parser.rl"
439
+ #line 136 "parser.rl"
436
440
  {
437
441
  char *np = JSON_parse_string(json, p, pe, result);
438
442
  if (np == NULL) goto _out12; else {p = (( np))-1;}
439
443
  }
440
444
  goto st12;
441
445
  tr2:
442
- #line 137 "parser.rl"
446
+ #line 141 "parser.rl"
443
447
  {
444
448
  char *np;
445
449
  np = JSON_parse_float(json, p, pe, result);
@@ -450,33 +454,39 @@ tr2:
450
454
  }
451
455
  goto st12;
452
456
  tr3:
453
- #line 146 "parser.rl"
457
+ #line 150 "parser.rl"
454
458
  {
455
- char *np = JSON_parse_array(json, p, pe, result);
459
+ char *np;
460
+ json->current_nesting += 1;
461
+ np = JSON_parse_array(json, p, pe, result);
462
+ json->current_nesting -= 1;
456
463
  if (np == NULL) goto _out12; else {p = (( np))-1;}
457
464
  }
458
465
  goto st12;
459
466
  tr7:
460
- #line 151 "parser.rl"
467
+ #line 158 "parser.rl"
461
468
  {
462
- char *np = JSON_parse_object(json, p, pe, result);
469
+ char *np;
470
+ json->current_nesting += 1;
471
+ np = JSON_parse_object(json, p, pe, result);
472
+ json->current_nesting -= 1;
463
473
  if (np == NULL) goto _out12; else {p = (( np))-1;}
464
474
  }
465
475
  goto st12;
466
476
  tr11:
467
- #line 126 "parser.rl"
477
+ #line 130 "parser.rl"
468
478
  {
469
479
  *result = Qfalse;
470
480
  }
471
481
  goto st12;
472
482
  tr14:
473
- #line 123 "parser.rl"
483
+ #line 127 "parser.rl"
474
484
  {
475
485
  *result = Qnil;
476
486
  }
477
487
  goto st12;
478
488
  tr17:
479
- #line 129 "parser.rl"
489
+ #line 133 "parser.rl"
480
490
  {
481
491
  *result = Qtrue;
482
492
  }
@@ -485,9 +495,9 @@ st12:
485
495
  if ( ++p == pe )
486
496
  goto _out12;
487
497
  case 12:
488
- #line 156 "parser.rl"
498
+ #line 166 "parser.rl"
489
499
  { goto _out12; }
490
- #line 491 "parser.c"
500
+ #line 501 "parser.c"
491
501
  goto st0;
492
502
  st2:
493
503
  if ( ++p == pe )
@@ -575,7 +585,7 @@ case 11:
575
585
 
576
586
  _out: {}
577
587
  }
578
- #line 175 "parser.rl"
588
+ #line 185 "parser.rl"
579
589
 
580
590
  if (cs >= JSON_value_first_final) {
581
591
  return p;
@@ -585,14 +595,14 @@ case 11:
585
595
  }
586
596
 
587
597
 
588
- #line 589 "parser.c"
598
+ #line 599 "parser.c"
589
599
  static const int JSON_integer_start = 1;
590
600
  static const int JSON_integer_first_final = 5;
591
601
  static const int JSON_integer_error = 0;
592
602
 
593
603
  static const int JSON_integer_en_main = 1;
594
604
 
595
- #line 191 "parser.rl"
605
+ #line 201 "parser.rl"
596
606
 
597
607
 
598
608
  static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -600,14 +610,14 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
600
610
  int cs = EVIL;
601
611
 
602
612
 
603
- #line 604 "parser.c"
613
+ #line 614 "parser.c"
604
614
  {
605
615
  cs = JSON_integer_start;
606
616
  }
607
- #line 198 "parser.rl"
617
+ #line 208 "parser.rl"
608
618
  json->memo = p;
609
619
 
610
- #line 611 "parser.c"
620
+ #line 621 "parser.c"
611
621
  {
612
622
  if ( p == pe )
613
623
  goto _out;
@@ -640,14 +650,14 @@ case 3:
640
650
  goto st0;
641
651
  goto tr4;
642
652
  tr4:
643
- #line 188 "parser.rl"
653
+ #line 198 "parser.rl"
644
654
  { goto _out5; }
645
655
  goto st5;
646
656
  st5:
647
657
  if ( ++p == pe )
648
658
  goto _out5;
649
659
  case 5:
650
- #line 651 "parser.c"
660
+ #line 661 "parser.c"
651
661
  goto st0;
652
662
  st4:
653
663
  if ( ++p == pe )
@@ -665,7 +675,7 @@ case 4:
665
675
 
666
676
  _out: {}
667
677
  }
668
- #line 200 "parser.rl"
678
+ #line 210 "parser.rl"
669
679
 
670
680
  if (cs >= JSON_integer_first_final) {
671
681
  long len = p - json->memo;
@@ -677,14 +687,14 @@ case 4:
677
687
  }
678
688
 
679
689
 
680
- #line 681 "parser.c"
690
+ #line 691 "parser.c"
681
691
  static const int JSON_float_start = 1;
682
692
  static const int JSON_float_first_final = 10;
683
693
  static const int JSON_float_error = 0;
684
694
 
685
695
  static const int JSON_float_en_main = 1;
686
696
 
687
- #line 222 "parser.rl"
697
+ #line 232 "parser.rl"
688
698
 
689
699
 
690
700
  static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -692,14 +702,14 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
692
702
  int cs = EVIL;
693
703
 
694
704
 
695
- #line 696 "parser.c"
705
+ #line 706 "parser.c"
696
706
  {
697
707
  cs = JSON_float_start;
698
708
  }
699
- #line 229 "parser.rl"
709
+ #line 239 "parser.rl"
700
710
  json->memo = p;
701
711
 
702
- #line 703 "parser.c"
712
+ #line 713 "parser.c"
703
713
  {
704
714
  if ( p == pe )
705
715
  goto _out;
@@ -756,14 +766,14 @@ case 5:
756
766
  goto st0;
757
767
  goto tr7;
758
768
  tr7:
759
- #line 216 "parser.rl"
769
+ #line 226 "parser.rl"
760
770
  { goto _out10; }
761
771
  goto st10;
762
772
  st10:
763
773
  if ( ++p == pe )
764
774
  goto _out10;
765
775
  case 10:
766
- #line 767 "parser.c"
776
+ #line 777 "parser.c"
767
777
  goto st0;
768
778
  st6:
769
779
  if ( ++p == pe )
@@ -823,7 +833,7 @@ case 9:
823
833
 
824
834
  _out: {}
825
835
  }
826
- #line 231 "parser.rl"
836
+ #line 241 "parser.rl"
827
837
 
828
838
  if (cs >= JSON_float_first_final) {
829
839
  long len = p - json->memo;
@@ -836,29 +846,33 @@ case 9:
836
846
 
837
847
 
838
848
 
839
- #line 840 "parser.c"
849
+ #line 850 "parser.c"
840
850
  static const int JSON_array_start = 1;
841
851
  static const int JSON_array_first_final = 17;
842
852
  static const int JSON_array_error = 0;
843
853
 
844
854
  static const int JSON_array_en_main = 1;
845
855
 
846
- #line 267 "parser.rl"
856
+ #line 277 "parser.rl"
847
857
 
848
858
 
849
859
  static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
850
860
  {
851
861
  int cs = EVIL;
862
+
863
+ if (json->max_nesting && json->current_nesting > json->max_nesting) {
864
+ rb_raise(eNestingError, "nesting of %d is to deep", json->current_nesting);
865
+ }
852
866
  *result = rb_ary_new();
853
867
 
854
868
 
855
- #line 856 "parser.c"
869
+ #line 870 "parser.c"
856
870
  {
857
871
  cs = JSON_array_start;
858
872
  }
859
- #line 275 "parser.rl"
873
+ #line 289 "parser.rl"
860
874
 
861
- #line 862 "parser.c"
875
+ #line 876 "parser.c"
862
876
  {
863
877
  if ( p == pe )
864
878
  goto _out;
@@ -894,7 +908,7 @@ case 2:
894
908
  goto st2;
895
909
  goto st0;
896
910
  tr2:
897
- #line 248 "parser.rl"
911
+ #line 258 "parser.rl"
898
912
  {
899
913
  VALUE v = Qnil;
900
914
  char *np = JSON_parse_value(json, p, pe, &v);
@@ -910,7 +924,7 @@ st3:
910
924
  if ( ++p == pe )
911
925
  goto _out3;
912
926
  case 3:
913
- #line 914 "parser.c"
927
+ #line 928 "parser.c"
914
928
  switch( (*p) ) {
915
929
  case 13: goto st3;
916
930
  case 32: goto st3;
@@ -1008,14 +1022,14 @@ case 12:
1008
1022
  goto st3;
1009
1023
  goto st12;
1010
1024
  tr4:
1011
- #line 259 "parser.rl"
1025
+ #line 269 "parser.rl"
1012
1026
  { goto _out17; }
1013
1027
  goto st17;
1014
1028
  st17:
1015
1029
  if ( ++p == pe )
1016
1030
  goto _out17;
1017
1031
  case 17:
1018
- #line 1019 "parser.c"
1032
+ #line 1033 "parser.c"
1019
1033
  goto st0;
1020
1034
  st13:
1021
1035
  if ( ++p == pe )
@@ -1070,7 +1084,7 @@ case 16:
1070
1084
 
1071
1085
  _out: {}
1072
1086
  }
1073
- #line 276 "parser.rl"
1087
+ #line 290 "parser.rl"
1074
1088
 
1075
1089
  if(cs >= JSON_array_first_final) {
1076
1090
  return p + 1;
@@ -1079,7 +1093,7 @@ case 16:
1079
1093
  }
1080
1094
  }
1081
1095
 
1082
- static VALUE json_string_escape(char *p, char *pe)
1096
+ static VALUE json_string_unescape(char *p, char *pe)
1083
1097
  {
1084
1098
  VALUE result = rb_str_buf_new(pe - p + 1);
1085
1099
 
@@ -1120,6 +1134,10 @@ static VALUE json_string_escape(char *p, char *pe)
1120
1134
  p = JSON_convert_UTF16_to_UTF8(result, p, pe, strictConversion);
1121
1135
  }
1122
1136
  break;
1137
+ default:
1138
+ rb_str_buf_cat(result, p, 1);
1139
+ p++;
1140
+ break;
1123
1141
  }
1124
1142
  } else {
1125
1143
  char *q = p;
@@ -1132,14 +1150,14 @@ static VALUE json_string_escape(char *p, char *pe)
1132
1150
  }
1133
1151
 
1134
1152
 
1135
- #line 1136 "parser.c"
1153
+ #line 1154 "parser.c"
1136
1154
  static const int JSON_string_start = 1;
1137
1155
  static const int JSON_string_first_final = 8;
1138
1156
  static const int JSON_string_error = 0;
1139
1157
 
1140
1158
  static const int JSON_string_en_main = 1;
1141
1159
 
1142
- #line 350 "parser.rl"
1160
+ #line 368 "parser.rl"
1143
1161
 
1144
1162
 
1145
1163
  static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1148,14 +1166,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
1148
1166
 
1149
1167
  *result = rb_str_new("", 0);
1150
1168
 
1151
- #line 1152 "parser.c"
1169
+ #line 1170 "parser.c"
1152
1170
  {
1153
1171
  cs = JSON_string_start;
1154
1172
  }
1155
- #line 358 "parser.rl"
1173
+ #line 376 "parser.rl"
1156
1174
  json->memo = p;
1157
1175
 
1158
- #line 1159 "parser.c"
1176
+ #line 1177 "parser.c"
1159
1177
  {
1160
1178
  if ( p == pe )
1161
1179
  goto _out;
@@ -1179,36 +1197,29 @@ case 2:
1179
1197
  goto st0;
1180
1198
  goto st2;
1181
1199
  tr2:
1182
- #line 342 "parser.rl"
1200
+ #line 360 "parser.rl"
1183
1201
  {
1184
- *result = json_string_escape(json->memo + 1, p);
1202
+ *result = json_string_unescape(json->memo + 1, p);
1185
1203
  if (NIL_P(*result)) goto _out8; else {p = (( p + 1))-1;}
1186
1204
  }
1187
- #line 347 "parser.rl"
1205
+ #line 365 "parser.rl"
1188
1206
  { goto _out8; }
1189
1207
  goto st8;
1190
1208
  st8:
1191
1209
  if ( ++p == pe )
1192
1210
  goto _out8;
1193
1211
  case 8:
1194
- #line 1195 "parser.c"
1212
+ #line 1213 "parser.c"
1195
1213
  goto st0;
1196
1214
  st3:
1197
1215
  if ( ++p == pe )
1198
1216
  goto _out3;
1199
1217
  case 3:
1200
- switch( (*p) ) {
1201
- case 34: goto st2;
1202
- case 47: goto st2;
1203
- case 92: goto st2;
1204
- case 98: goto st2;
1205
- case 102: goto st2;
1206
- case 110: goto st2;
1207
- case 114: goto st2;
1208
- case 116: goto st2;
1209
- case 117: goto st4;
1210
- }
1211
- goto st0;
1218
+ if ( (*p) == 117 )
1219
+ goto st4;
1220
+ if ( 0 <= (*p) && (*p) <= 31 )
1221
+ goto st0;
1222
+ goto st2;
1212
1223
  st4:
1213
1224
  if ( ++p == pe )
1214
1225
  goto _out4;
@@ -1273,7 +1284,7 @@ case 7:
1273
1284
 
1274
1285
  _out: {}
1275
1286
  }
1276
- #line 360 "parser.rl"
1287
+ #line 378 "parser.rl"
1277
1288
 
1278
1289
  if (cs >= JSON_string_first_final) {
1279
1290
  return p + 1;
@@ -1284,14 +1295,14 @@ case 7:
1284
1295
 
1285
1296
 
1286
1297
 
1287
- #line 1288 "parser.c"
1298
+ #line 1299 "parser.c"
1288
1299
  static const int JSON_start = 1;
1289
1300
  static const int JSON_first_final = 10;
1290
1301
  static const int JSON_error = 0;
1291
1302
 
1292
1303
  static const int JSON_en_main = 1;
1293
1304
 
1294
- #line 390 "parser.rl"
1305
+ #line 412 "parser.rl"
1295
1306
 
1296
1307
 
1297
1308
  /*
@@ -1307,21 +1318,51 @@ static const int JSON_en_main = 1;
1307
1318
  */
1308
1319
 
1309
1320
  /*
1310
- * call-seq: new(source)
1321
+ * call-seq: new(source, opts => {})
1322
+ *
1323
+ * Creates a new JSON::Ext::Parser instance for the string _source_.
1311
1324
  *
1312
1325
  * Creates a new JSON::Ext::Parser instance for the string _source_.
1326
+ *
1327
+ * It will be configured by the _opts_ hash. _opts_ can have the following
1328
+ * keys:
1329
+ *
1330
+ * _opts_ can have the following keys:
1331
+ * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
1332
+ * structures. Disable depth checking with :max_nesting => false.
1313
1333
  */
1314
- static VALUE cParser_initialize(VALUE self, VALUE source)
1334
+ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
1315
1335
  {
1316
1336
  char *ptr;
1317
1337
  long len;
1338
+ VALUE source, opts;
1318
1339
  GET_STRUCT;
1340
+ rb_scan_args(argc, argv, "11", &source, &opts);
1319
1341
  source = StringValue(source);
1320
1342
  ptr = RSTRING_PTR(source);
1321
1343
  len = RSTRING_LEN(source);
1322
1344
  if (len < 2) {
1323
1345
  rb_raise(eParserError, "A JSON text must at least contain two octets!");
1324
1346
  }
1347
+ json->max_nesting = 19;
1348
+ if (!NIL_P(opts)) {
1349
+ opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
1350
+ if (NIL_P(opts)) {
1351
+ rb_raise(rb_eArgError, "opts needs to be like a hash");
1352
+ } else {
1353
+ VALUE s_max_nesting = ID2SYM(i_max_nesting);
1354
+ if (st_lookup(RHASH(opts)->tbl, s_max_nesting, 0)) {
1355
+ VALUE max_nesting = rb_hash_aref(opts, s_max_nesting);
1356
+ if (RTEST(max_nesting)) {
1357
+ Check_Type(max_nesting, T_FIXNUM);
1358
+ json->max_nesting = FIX2INT(max_nesting);
1359
+ } else {
1360
+ json->max_nesting = 0;
1361
+ }
1362
+ }
1363
+ }
1364
+ }
1365
+ json->current_nesting = 0;
1325
1366
  /*
1326
1367
  Convert these?
1327
1368
  if (len >= 4 && ptr[0] == 0 && ptr[1] == 0 && ptr[2] == 0) {
@@ -1355,15 +1396,15 @@ static VALUE cParser_parse(VALUE self)
1355
1396
  GET_STRUCT;
1356
1397
 
1357
1398
 
1358
- #line 1359 "parser.c"
1399
+ #line 1400 "parser.c"
1359
1400
  {
1360
1401
  cs = JSON_start;
1361
1402
  }
1362
- #line 453 "parser.rl"
1403
+ #line 505 "parser.rl"
1363
1404
  p = json->source;
1364
1405
  pe = p + json->len;
1365
1406
 
1366
- #line 1367 "parser.c"
1407
+ #line 1408 "parser.c"
1367
1408
  {
1368
1409
  if ( p == pe )
1369
1410
  goto _out;
@@ -1418,16 +1459,20 @@ case 5:
1418
1459
  goto st1;
1419
1460
  goto st5;
1420
1461
  tr3:
1421
- #line 381 "parser.rl"
1462
+ #line 401 "parser.rl"
1422
1463
  {
1423
- char *np = JSON_parse_array(json, p, pe, &result);
1464
+ char *np;
1465
+ json->current_nesting = 1;
1466
+ np = JSON_parse_array(json, p, pe, &result);
1424
1467
  if (np == NULL) goto _out10; else {p = (( np))-1;}
1425
1468
  }
1426
1469
  goto st10;
1427
1470
  tr4:
1428
- #line 376 "parser.rl"
1471
+ #line 394 "parser.rl"
1429
1472
  {
1430
- char *np = JSON_parse_object(json, p, pe, &result);
1473
+ char *np;
1474
+ json->current_nesting = 1;
1475
+ np = JSON_parse_object(json, p, pe, &result);
1431
1476
  if (np == NULL) goto _out10; else {p = (( np))-1;}
1432
1477
  }
1433
1478
  goto st10;
@@ -1435,7 +1480,7 @@ st10:
1435
1480
  if ( ++p == pe )
1436
1481
  goto _out10;
1437
1482
  case 10:
1438
- #line 1439 "parser.c"
1483
+ #line 1484 "parser.c"
1439
1484
  switch( (*p) ) {
1440
1485
  case 13: goto st10;
1441
1486
  case 32: goto st10;
@@ -1491,7 +1536,7 @@ case 9:
1491
1536
 
1492
1537
  _out: {}
1493
1538
  }
1494
- #line 456 "parser.rl"
1539
+ #line 508 "parser.rl"
1495
1540
 
1496
1541
  if (cs >= JSON_first_final && p == pe) {
1497
1542
  return result;
@@ -1542,8 +1587,9 @@ void Init_parser()
1542
1587
  mExt = rb_define_module_under(mJSON, "Ext");
1543
1588
  cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
1544
1589
  eParserError = rb_path2class("JSON::ParserError");
1590
+ eNestingError = rb_path2class("JSON::NestingError");
1545
1591
  rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
1546
- rb_define_method(cParser, "initialize", cParser_initialize, 1);
1592
+ rb_define_method(cParser, "initialize", cParser_initialize, -1);
1547
1593
  rb_define_method(cParser, "parse", cParser_parse, 0);
1548
1594
  rb_define_method(cParser, "source", cParser_source, 0);
1549
1595
 
@@ -1551,4 +1597,5 @@ void Init_parser()
1551
1597
  i_json_create = rb_intern("json_create");
1552
1598
  i_create_id = rb_intern("create_id");
1553
1599
  i_chr = rb_intern("chr");
1600
+ i_max_nesting = rb_intern("max_nesting");
1554
1601
  }