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 +13 -2
- data/README +3 -2
- data/RUBY +58 -0
- data/Rakefile +4 -3
- data/VERSION +1 -1
- data/ext/json/ext/generator/unicode.c +1 -1
- data/ext/json/ext/parser/parser.c +146 -99
- data/ext/json/ext/parser/parser.rl +70 -16
- data/lib/json.rb +2 -3
- data/lib/json/common.rb +11 -2
- data/lib/json/editor.rb +1295 -1207
- data/lib/json/pure/parser.rb +35 -8
- data/lib/json/version.rb +1 -1
- data/tests/fixtures/{pass18.json → fail18.json} +0 -0
- data/tests/fixtures/{fail15.json → pass15.json} +0 -0
- data/tests/fixtures/{fail16.json → pass16.json} +0 -0
- data/tests/fixtures/{fail17.json → pass17.json} +0 -0
- data/tests/fixtures/{fail26.json → pass26.json} +0 -0
- data/tests/test_json.rb +19 -0
- data/tests/test_json_fixtures.rb +1 -1
- data/tools/fuzz.rb +1 -1
- metadata +8 -7
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
|
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
|
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
|
-
|
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} | #{
|
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} | #{
|
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
|
1
|
+
1.1.0
|
@@ -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
|
36
|
+
#line 58 "parser.rl"
|
38
37
|
|
39
38
|
|
40
39
|
|
41
|
-
#line
|
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
|
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
|
62
|
+
#line 63 "parser.c"
|
59
63
|
{
|
60
64
|
cs = JSON_object_start;
|
61
65
|
}
|
62
|
-
#line
|
66
|
+
#line 105 "parser.rl"
|
63
67
|
|
64
|
-
#line
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
411
|
+
#line 412 "parser.c"
|
408
412
|
{
|
409
413
|
cs = JSON_value_start;
|
410
414
|
}
|
411
|
-
#line
|
415
|
+
#line 184 "parser.rl"
|
412
416
|
|
413
|
-
#line
|
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
|
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
|
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
|
457
|
+
#line 150 "parser.rl"
|
454
458
|
{
|
455
|
-
char *np
|
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
|
467
|
+
#line 158 "parser.rl"
|
461
468
|
{
|
462
|
-
char *np
|
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
|
477
|
+
#line 130 "parser.rl"
|
468
478
|
{
|
469
479
|
*result = Qfalse;
|
470
480
|
}
|
471
481
|
goto st12;
|
472
482
|
tr14:
|
473
|
-
#line
|
483
|
+
#line 127 "parser.rl"
|
474
484
|
{
|
475
485
|
*result = Qnil;
|
476
486
|
}
|
477
487
|
goto st12;
|
478
488
|
tr17:
|
479
|
-
#line
|
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
|
498
|
+
#line 166 "parser.rl"
|
489
499
|
{ goto _out12; }
|
490
|
-
#line
|
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
|
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
|
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
|
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
|
613
|
+
#line 614 "parser.c"
|
604
614
|
{
|
605
615
|
cs = JSON_integer_start;
|
606
616
|
}
|
607
|
-
#line
|
617
|
+
#line 208 "parser.rl"
|
608
618
|
json->memo = p;
|
609
619
|
|
610
|
-
#line
|
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
|
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
|
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
|
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
|
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
|
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
|
705
|
+
#line 706 "parser.c"
|
696
706
|
{
|
697
707
|
cs = JSON_float_start;
|
698
708
|
}
|
699
|
-
#line
|
709
|
+
#line 239 "parser.rl"
|
700
710
|
json->memo = p;
|
701
711
|
|
702
|
-
#line
|
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
|
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
|
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
|
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
|
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
|
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
|
869
|
+
#line 870 "parser.c"
|
856
870
|
{
|
857
871
|
cs = JSON_array_start;
|
858
872
|
}
|
859
|
-
#line
|
873
|
+
#line 289 "parser.rl"
|
860
874
|
|
861
|
-
#line
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
1169
|
+
#line 1170 "parser.c"
|
1152
1170
|
{
|
1153
1171
|
cs = JSON_string_start;
|
1154
1172
|
}
|
1155
|
-
#line
|
1173
|
+
#line 376 "parser.rl"
|
1156
1174
|
json->memo = p;
|
1157
1175
|
|
1158
|
-
#line
|
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
|
1200
|
+
#line 360 "parser.rl"
|
1183
1201
|
{
|
1184
|
-
*result =
|
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
|
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
|
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
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
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
|
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
|
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
|
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
|
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
|
1399
|
+
#line 1400 "parser.c"
|
1359
1400
|
{
|
1360
1401
|
cs = JSON_start;
|
1361
1402
|
}
|
1362
|
-
#line
|
1403
|
+
#line 505 "parser.rl"
|
1363
1404
|
p = json->source;
|
1364
1405
|
pe = p + json->len;
|
1365
1406
|
|
1366
|
-
#line
|
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
|
1462
|
+
#line 401 "parser.rl"
|
1422
1463
|
{
|
1423
|
-
char *np
|
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
|
1471
|
+
#line 394 "parser.rl"
|
1429
1472
|
{
|
1430
|
-
char *np
|
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
|
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
|
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
|
}
|