json_pure 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }