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 +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
|
}
|