summaryrefslogtreecommitdiff
path: root/ext/json/ext/parser
diff options
context:
space:
mode:
Diffstat (limited to 'ext/json/ext/parser')
-rw-r--r--ext/json/ext/parser/extconf.rb4
-rw-r--r--ext/json/ext/parser/parser.c363
-rw-r--r--ext/json/ext/parser/parser.rl60
3 files changed, 302 insertions, 125 deletions
diff --git a/ext/json/ext/parser/extconf.rb b/ext/json/ext/parser/extconf.rb
index cef706a4b9..b2e7b051a4 100644
--- a/ext/json/ext/parser/extconf.rb
+++ b/ext/json/ext/parser/extconf.rb
@@ -2,8 +2,8 @@ require 'mkmf'
require 'rbconfig'
if CONFIG['CC'] =~ /gcc/
- #CONFIG['CC'] += ' -Wall -ggdb'
- CONFIG['CC'] += ' -Wall'
+ #$CFLAGS += ' -Wall -ggdb'
+ $CFLAGS += ' -Wall'
end
have_header 'st.h'
diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c
index 3b84110374..a1950b067a 100644
--- a/ext/json/ext/parser/parser.c
+++ b/ext/json/ext/parser/parser.c
@@ -9,8 +9,12 @@
#define EVIL 0x666
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
+static VALUE CNaN, CInfinity, CMinusInfinity;
-static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting;
+static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting,
+ i_allow_nan;
+
+#define MinusInfinity "-Infinity"
typedef struct JSON_ParserStruct {
VALUE Vsource;
@@ -20,6 +24,7 @@ typedef struct JSON_ParserStruct {
VALUE create_id;
int max_nesting;
int current_nesting;
+ int allow_nan;
} JSON_Parser;
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
@@ -33,18 +38,18 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
JSON_Parser *json; \
Data_Get_Struct(self, JSON_Parser, json);
-#line 58 "parser.rl"
+#line 66 "parser.rl"
-#line 41 "parser.c"
+#line 46 "parser.c"
static const int JSON_object_start = 1;
static const int JSON_object_first_final = 27;
static const int JSON_object_error = 0;
static const int JSON_object_en_main = 1;
-#line 91 "parser.rl"
+#line 99 "parser.rl"
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -59,13 +64,13 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_hash_new();
-#line 63 "parser.c"
+#line 68 "parser.c"
{
cs = JSON_object_start;
}
-#line 105 "parser.rl"
+#line 113 "parser.rl"
-#line 69 "parser.c"
+#line 74 "parser.c"
{
if ( p == pe )
goto _out;
@@ -92,7 +97,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 77 "parser.rl"
+#line 85 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, &last_name);
if (np == NULL) goto _out3; else {p = (( np))-1;}
@@ -102,7 +107,7 @@ st3:
if ( ++p == pe )
goto _out3;
case 3:
-#line 106 "parser.c"
+#line 111 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -154,6 +159,8 @@ case 8:
case 34: goto tr11;
case 45: goto tr11;
case 47: goto st19;
+ case 73: goto tr11;
+ case 78: goto tr11;
case 91: goto tr11;
case 102: goto tr11;
case 110: goto tr11;
@@ -167,7 +174,7 @@ case 8:
goto st8;
goto st0;
tr11:
-#line 66 "parser.rl"
+#line 74 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -183,7 +190,7 @@ st9:
if ( ++p == pe )
goto _out9;
case 9:
-#line 187 "parser.c"
+#line 194 "parser.c"
switch( (*p) ) {
case 13: goto st9;
case 32: goto st9;
@@ -272,14 +279,14 @@ case 18:
goto st9;
goto st18;
tr4:
-#line 82 "parser.rl"
+#line 90 "parser.rl"
{ goto _out27; }
goto st27;
st27:
if ( ++p == pe )
goto _out27;
case 27:
-#line 283 "parser.c"
+#line 290 "parser.c"
goto st0;
st19:
if ( ++p == pe )
@@ -376,7 +383,7 @@ case 26:
_out: {}
}
-#line 106 "parser.rl"
+#line 114 "parser.rl"
if (cs >= JSON_object_first_final) {
VALUE klassname = rb_hash_aref(*result, json->create_id);
@@ -393,14 +400,14 @@ case 26:
}
-#line 397 "parser.c"
+#line 404 "parser.c"
static const int JSON_value_start = 1;
-static const int JSON_value_first_final = 12;
+static const int JSON_value_first_final = 21;
static const int JSON_value_error = 0;
static const int JSON_value_en_main = 1;
-#line 177 "parser.rl"
+#line 210 "parser.rl"
static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -408,13 +415,13 @@ static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 412 "parser.c"
+#line 419 "parser.c"
{
cs = JSON_value_start;
}
-#line 184 "parser.rl"
+#line 217 "parser.rl"
-#line 418 "parser.c"
+#line 425 "parser.c"
{
if ( p == pe )
goto _out;
@@ -424,11 +431,13 @@ case 1:
switch( (*p) ) {
case 34: goto tr0;
case 45: goto tr2;
- case 91: goto tr3;
- case 102: goto st2;
- case 110: goto st6;
- case 116: goto st9;
- case 123: goto tr7;
+ case 73: goto st2;
+ case 78: goto st9;
+ case 91: goto tr5;
+ case 102: goto st11;
+ case 110: goto st15;
+ case 116: goto st18;
+ case 123: goto tr9;
}
if ( 48 <= (*p) && (*p) <= 57 )
goto tr2;
@@ -436,142 +445,234 @@ case 1:
st0:
goto _out0;
tr0:
-#line 136 "parser.rl"
+#line 158 "parser.rl"
{
char *np = JSON_parse_string(json, p, pe, result);
- if (np == NULL) goto _out12; else {p = (( np))-1;}
+ if (np == NULL) goto _out21; else {p = (( np))-1;}
}
- goto st12;
+ goto st21;
tr2:
-#line 141 "parser.rl"
+#line 163 "parser.rl"
{
char *np;
+ if(pe > p + 9 && !strncmp(MinusInfinity, p, 9)) {
+ if (json->allow_nan) {
+ *result = CMinusInfinity;
+ {p = (( p + 10))-1;}
+ goto _out21;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p);
+ }
+ }
np = JSON_parse_float(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
np = JSON_parse_integer(json, p, pe, result);
if (np != NULL) {p = (( np))-1;}
- goto _out12;
+ goto _out21;
}
- goto st12;
-tr3:
-#line 150 "parser.rl"
+ goto st21;
+tr5:
+#line 181 "parser.rl"
{
char *np;
json->current_nesting += 1;
np = JSON_parse_array(json, p, pe, result);
json->current_nesting -= 1;
- if (np == NULL) goto _out12; else {p = (( np))-1;}
+ if (np == NULL) goto _out21; else {p = (( np))-1;}
}
- goto st12;
-tr7:
-#line 158 "parser.rl"
+ goto st21;
+tr9:
+#line 189 "parser.rl"
{
char *np;
json->current_nesting += 1;
np = JSON_parse_object(json, p, pe, result);
json->current_nesting -= 1;
- if (np == NULL) goto _out12; else {p = (( np))-1;}
+ if (np == NULL) goto _out21; else {p = (( np))-1;}
}
- goto st12;
-tr11:
-#line 130 "parser.rl"
+ goto st21;
+tr16:
+#line 151 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CInfinity;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ }
+ }
+ goto st21;
+tr18:
+#line 144 "parser.rl"
+ {
+ if (json->allow_nan) {
+ *result = CNaN;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ }
+ }
+ goto st21;
+tr22:
+#line 138 "parser.rl"
{
*result = Qfalse;
}
- goto st12;
-tr14:
-#line 127 "parser.rl"
+ goto st21;
+tr25:
+#line 135 "parser.rl"
{
*result = Qnil;
}
- goto st12;
-tr17:
-#line 133 "parser.rl"
+ goto st21;
+tr28:
+#line 141 "parser.rl"
{
*result = Qtrue;
}
- goto st12;
-st12:
+ goto st21;
+st21:
if ( ++p == pe )
- goto _out12;
-case 12:
-#line 166 "parser.rl"
- { goto _out12; }
-#line 501 "parser.c"
+ goto _out21;
+case 21:
+#line 197 "parser.rl"
+ { goto _out21; }
+#line 539 "parser.c"
goto st0;
st2:
if ( ++p == pe )
goto _out2;
case 2:
- if ( (*p) == 97 )
+ if ( (*p) == 110 )
goto st3;
goto st0;
st3:
if ( ++p == pe )
goto _out3;
case 3:
- if ( (*p) == 108 )
+ if ( (*p) == 102 )
goto st4;
goto st0;
st4:
if ( ++p == pe )
goto _out4;
case 4:
- if ( (*p) == 115 )
+ if ( (*p) == 105 )
goto st5;
goto st0;
st5:
if ( ++p == pe )
goto _out5;
case 5:
- if ( (*p) == 101 )
- goto tr11;
+ if ( (*p) == 110 )
+ goto st6;
goto st0;
st6:
if ( ++p == pe )
goto _out6;
case 6:
- if ( (*p) == 117 )
+ if ( (*p) == 105 )
goto st7;
goto st0;
st7:
if ( ++p == pe )
goto _out7;
case 7:
- if ( (*p) == 108 )
+ if ( (*p) == 116 )
goto st8;
goto st0;
st8:
if ( ++p == pe )
goto _out8;
case 8:
- if ( (*p) == 108 )
- goto tr14;
+ if ( (*p) == 121 )
+ goto tr16;
goto st0;
st9:
if ( ++p == pe )
goto _out9;
case 9:
- if ( (*p) == 114 )
+ if ( (*p) == 97 )
goto st10;
goto st0;
st10:
if ( ++p == pe )
goto _out10;
case 10:
- if ( (*p) == 117 )
- goto st11;
+ if ( (*p) == 78 )
+ goto tr18;
goto st0;
st11:
if ( ++p == pe )
goto _out11;
case 11:
+ if ( (*p) == 97 )
+ goto st12;
+ goto st0;
+st12:
+ if ( ++p == pe )
+ goto _out12;
+case 12:
+ if ( (*p) == 108 )
+ goto st13;
+ goto st0;
+st13:
+ if ( ++p == pe )
+ goto _out13;
+case 13:
+ if ( (*p) == 115 )
+ goto st14;
+ goto st0;
+st14:
+ if ( ++p == pe )
+ goto _out14;
+case 14:
+ if ( (*p) == 101 )
+ goto tr22;
+ goto st0;
+st15:
+ if ( ++p == pe )
+ goto _out15;
+case 15:
+ if ( (*p) == 117 )
+ goto st16;
+ goto st0;
+st16:
+ if ( ++p == pe )
+ goto _out16;
+case 16:
+ if ( (*p) == 108 )
+ goto st17;
+ goto st0;
+st17:
+ if ( ++p == pe )
+ goto _out17;
+case 17:
+ if ( (*p) == 108 )
+ goto tr25;
+ goto st0;
+st18:
+ if ( ++p == pe )
+ goto _out18;
+case 18:
+ if ( (*p) == 114 )
+ goto st19;
+ goto st0;
+st19:
+ if ( ++p == pe )
+ goto _out19;
+case 19:
+ if ( (*p) == 117 )
+ goto st20;
+ goto st0;
+st20:
+ if ( ++p == pe )
+ goto _out20;
+case 20:
if ( (*p) == 101 )
- goto tr17;
+ goto tr28;
goto st0;
}
_out0: cs = 0; goto _out;
- _out12: cs = 12; goto _out;
+ _out21: cs = 21; goto _out;
_out2: cs = 2; goto _out;
_out3: cs = 3; goto _out;
_out4: cs = 4; goto _out;
@@ -582,10 +683,19 @@ case 11:
_out9: cs = 9; goto _out;
_out10: cs = 10; goto _out;
_out11: cs = 11; goto _out;
+ _out12: cs = 12; goto _out;
+ _out13: cs = 13; goto _out;
+ _out14: cs = 14; goto _out;
+ _out15: cs = 15; goto _out;
+ _out16: cs = 16; goto _out;
+ _out17: cs = 17; goto _out;
+ _out18: cs = 18; goto _out;
+ _out19: cs = 19; goto _out;
+ _out20: cs = 20; goto _out;
_out: {}
}
-#line 185 "parser.rl"
+#line 218 "parser.rl"
if (cs >= JSON_value_first_final) {
return p;
@@ -595,14 +705,14 @@ case 11:
}
-#line 599 "parser.c"
+#line 709 "parser.c"
static const int JSON_integer_start = 1;
static const int JSON_integer_first_final = 5;
static const int JSON_integer_error = 0;
static const int JSON_integer_en_main = 1;
-#line 201 "parser.rl"
+#line 234 "parser.rl"
static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -610,14 +720,14 @@ static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *res
int cs = EVIL;
-#line 614 "parser.c"
+#line 724 "parser.c"
{
cs = JSON_integer_start;
}
-#line 208 "parser.rl"
+#line 241 "parser.rl"
json->memo = p;
-#line 621 "parser.c"
+#line 731 "parser.c"
{
if ( p == pe )
goto _out;
@@ -650,14 +760,14 @@ case 3:
goto st0;
goto tr4;
tr4:
-#line 198 "parser.rl"
+#line 231 "parser.rl"
{ goto _out5; }
goto st5;
st5:
if ( ++p == pe )
goto _out5;
case 5:
-#line 661 "parser.c"
+#line 771 "parser.c"
goto st0;
st4:
if ( ++p == pe )
@@ -675,7 +785,7 @@ case 4:
_out: {}
}
-#line 210 "parser.rl"
+#line 243 "parser.rl"
if (cs >= JSON_integer_first_final) {
long len = p - json->memo;
@@ -687,14 +797,14 @@ case 4:
}
-#line 691 "parser.c"
+#line 801 "parser.c"
static const int JSON_float_start = 1;
static const int JSON_float_first_final = 10;
static const int JSON_float_error = 0;
static const int JSON_float_en_main = 1;
-#line 232 "parser.rl"
+#line 265 "parser.rl"
static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -702,14 +812,14 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
int cs = EVIL;
-#line 706 "parser.c"
+#line 816 "parser.c"
{
cs = JSON_float_start;
}
-#line 239 "parser.rl"
+#line 272 "parser.rl"
json->memo = p;
-#line 713 "parser.c"
+#line 823 "parser.c"
{
if ( p == pe )
goto _out;
@@ -766,14 +876,14 @@ case 5:
goto st0;
goto tr7;
tr7:
-#line 226 "parser.rl"
+#line 259 "parser.rl"
{ goto _out10; }
goto st10;
st10:
if ( ++p == pe )
goto _out10;
case 10:
-#line 777 "parser.c"
+#line 887 "parser.c"
goto st0;
st6:
if ( ++p == pe )
@@ -833,7 +943,7 @@ case 9:
_out: {}
}
-#line 241 "parser.rl"
+#line 274 "parser.rl"
if (cs >= JSON_float_first_final) {
long len = p - json->memo;
@@ -846,14 +956,14 @@ case 9:
-#line 850 "parser.c"
+#line 960 "parser.c"
static const int JSON_array_start = 1;
static const int JSON_array_first_final = 17;
static const int JSON_array_error = 0;
static const int JSON_array_en_main = 1;
-#line 277 "parser.rl"
+#line 310 "parser.rl"
static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -866,13 +976,13 @@ static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *resul
*result = rb_ary_new();
-#line 870 "parser.c"
+#line 980 "parser.c"
{
cs = JSON_array_start;
}
-#line 289 "parser.rl"
+#line 322 "parser.rl"
-#line 876 "parser.c"
+#line 986 "parser.c"
{
if ( p == pe )
goto _out;
@@ -894,6 +1004,8 @@ case 2:
case 34: goto tr2;
case 45: goto tr2;
case 47: goto st13;
+ case 73: goto tr2;
+ case 78: goto tr2;
case 91: goto tr2;
case 93: goto tr4;
case 102: goto tr2;
@@ -908,7 +1020,7 @@ case 2:
goto st2;
goto st0;
tr2:
-#line 258 "parser.rl"
+#line 291 "parser.rl"
{
VALUE v = Qnil;
char *np = JSON_parse_value(json, p, pe, &v);
@@ -924,7 +1036,7 @@ st3:
if ( ++p == pe )
goto _out3;
case 3:
-#line 928 "parser.c"
+#line 1040 "parser.c"
switch( (*p) ) {
case 13: goto st3;
case 32: goto st3;
@@ -945,6 +1057,8 @@ case 4:
case 34: goto tr2;
case 45: goto tr2;
case 47: goto st5;
+ case 73: goto tr2;
+ case 78: goto tr2;
case 91: goto tr2;
case 102: goto tr2;
case 110: goto tr2;
@@ -1022,14 +1136,14 @@ case 12:
goto st3;
goto st12;
tr4:
-#line 269 "parser.rl"
+#line 302 "parser.rl"
{ goto _out17; }
goto st17;
st17:
if ( ++p == pe )
goto _out17;
case 17:
-#line 1033 "parser.c"
+#line 1147 "parser.c"
goto st0;
st13:
if ( ++p == pe )
@@ -1084,7 +1198,7 @@ case 16:
_out: {}
}
-#line 290 "parser.rl"
+#line 323 "parser.rl"
if(cs >= JSON_array_first_final) {
return p + 1;
@@ -1150,14 +1264,14 @@ static VALUE json_string_unescape(char *p, char *pe)
}
-#line 1154 "parser.c"
+#line 1268 "parser.c"
static const int JSON_string_start = 1;
static const int JSON_string_first_final = 8;
static const int JSON_string_error = 0;
static const int JSON_string_en_main = 1;
-#line 368 "parser.rl"
+#line 401 "parser.rl"
static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
@@ -1166,14 +1280,14 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*result = rb_str_new("", 0);
-#line 1170 "parser.c"
+#line 1284 "parser.c"
{
cs = JSON_string_start;
}
-#line 376 "parser.rl"
+#line 409 "parser.rl"
json->memo = p;
-#line 1177 "parser.c"
+#line 1291 "parser.c"
{
if ( p == pe )
goto _out;
@@ -1197,19 +1311,19 @@ case 2:
goto st0;
goto st2;
tr2:
-#line 360 "parser.rl"
+#line 393 "parser.rl"
{
*result = json_string_unescape(json->memo + 1, p);
if (NIL_P(*result)) goto _out8; else {p = (( p + 1))-1;}
}
-#line 365 "parser.rl"
+#line 398 "parser.rl"
{ goto _out8; }
goto st8;
st8:
if ( ++p == pe )
goto _out8;
case 8:
-#line 1213 "parser.c"
+#line 1327 "parser.c"
goto st0;
st3:
if ( ++p == pe )
@@ -1284,7 +1398,7 @@ case 7:
_out: {}
}
-#line 378 "parser.rl"
+#line 411 "parser.rl"
if (cs >= JSON_string_first_final) {
return p + 1;
@@ -1295,14 +1409,14 @@ case 7:
-#line 1299 "parser.c"
+#line 1413 "parser.c"
static const int JSON_start = 1;
static const int JSON_first_final = 10;
static const int JSON_error = 0;
static const int JSON_en_main = 1;
-#line 412 "parser.rl"
+#line 445 "parser.rl"
/*
@@ -1329,7 +1443,11 @@ static const int JSON_en_main = 1;
*
* _opts_ can have the following keys:
* * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- * structures. Disable depth checking with :max_nesting => false.
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
+ * defaults to 19.
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
+ * false.
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -1345,14 +1463,15 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
rb_raise(eParserError, "A JSON text must at least contain two octets!");
}
json->max_nesting = 19;
+ json->allow_nan = 0;
if (!NIL_P(opts)) {
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
if (NIL_P(opts)) {
rb_raise(rb_eArgError, "opts needs to be like a hash");
} else {
- VALUE s_max_nesting = ID2SYM(i_max_nesting);
- if (st_lookup(RHASH(opts)->tbl, s_max_nesting, 0)) {
- VALUE max_nesting = rb_hash_aref(opts, s_max_nesting);
+ VALUE tmp = ID2SYM(i_max_nesting);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
if (RTEST(max_nesting)) {
Check_Type(max_nesting, T_FIXNUM);
json->max_nesting = FIX2INT(max_nesting);
@@ -1360,6 +1479,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 0;
}
}
+ tmp = ID2SYM(i_allow_nan);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE allow_nan = rb_hash_aref(opts, tmp);
+ if (RTEST(allow_nan)) json->allow_nan = 1;
+ }
}
}
json->current_nesting = 0;
@@ -1396,15 +1520,15 @@ static VALUE cParser_parse(VALUE self)
GET_STRUCT;
-#line 1400 "parser.c"
+#line 1524 "parser.c"
{
cs = JSON_start;
}
-#line 505 "parser.rl"
+#line 548 "parser.rl"
p = json->source;
pe = p + json->len;
-#line 1408 "parser.c"
+#line 1532 "parser.c"
{
if ( p == pe )
goto _out;
@@ -1459,7 +1583,7 @@ case 5:
goto st1;
goto st5;
tr3:
-#line 401 "parser.rl"
+#line 434 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1468,7 +1592,7 @@ tr3:
}
goto st10;
tr4:
-#line 394 "parser.rl"
+#line 427 "parser.rl"
{
char *np;
json->current_nesting = 1;
@@ -1480,7 +1604,7 @@ st10:
if ( ++p == pe )
goto _out10;
case 10:
-#line 1484 "parser.c"
+#line 1608 "parser.c"
switch( (*p) ) {
case 13: goto st10;
case 32: goto st10;
@@ -1536,7 +1660,7 @@ case 9:
_out: {}
}
-#line 508 "parser.rl"
+#line 551 "parser.rl"
if (cs >= JSON_first_final && p == pe) {
return result;
@@ -1593,9 +1717,14 @@ void Init_parser()
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+
i_json_creatable_p = rb_intern("json_creatable?");
i_json_create = rb_intern("json_create");
i_create_id = rb_intern("create_id");
i_chr = rb_intern("chr");
i_max_nesting = rb_intern("max_nesting");
+ i_allow_nan = rb_intern("allow_nan");
}
diff --git a/ext/json/ext/parser/parser.rl b/ext/json/ext/parser/parser.rl
index 9e2a5015eb..c1373c23dd 100644
--- a/ext/json/ext/parser/parser.rl
+++ b/ext/json/ext/parser/parser.rl
@@ -8,8 +8,12 @@
#define EVIL 0x666
static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
+static VALUE CNaN, CInfinity, CMinusInfinity;
-static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting;
+static ID i_json_creatable_p, i_json_create, i_create_id, i_chr, i_max_nesting,
+ i_allow_nan;
+
+#define MinusInfinity "-Infinity"
typedef struct JSON_ParserStruct {
VALUE Vsource;
@@ -19,6 +23,7 @@ typedef struct JSON_ParserStruct {
VALUE create_id;
int max_nesting;
int current_nesting;
+ int allow_nan;
} JSON_Parser;
static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result);
@@ -47,7 +52,10 @@ static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *resul
Vnull = 'null';
Vfalse = 'false';
Vtrue = 'true';
- begin_value = [nft"\-[{] | digit;
+ VNaN = 'NaN';
+ VInfinity = 'Infinity';
+ VMinusInfinity = '-Infinity';
+ begin_value = [nft"\-[{NI] | digit;
begin_object = '{';
end_object = '}';
begin_array = '[';
@@ -133,6 +141,20 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
action parse_true {
*result = Qtrue;
}
+ action parse_nan {
+ if (json->allow_nan) {
+ *result = CNaN;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 2);
+ }
+ }
+ action parse_infinity {
+ if (json->allow_nan) {
+ *result = CInfinity;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p - 8);
+ }
+ }
action parse_string {
char *np = JSON_parse_string(json, fpc, pe, result);
if (np == NULL) fbreak; else fexec np;
@@ -140,6 +162,15 @@ static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *resu
action parse_number {
char *np;
+ if(pe > fpc + 9 && !strncmp(MinusInfinity, fpc, 9)) {
+ if (json->allow_nan) {
+ *result = CMinusInfinity;
+ fexec p + 10;
+ fbreak;
+ } else {
+ rb_raise(eParserError, "unexpected token at '%s'", p);
+ }
+ }
np = JSON_parse_float(json, fpc, pe, result);
if (np != NULL) fexec np;
np = JSON_parse_integer(json, fpc, pe, result);
@@ -169,6 +200,8 @@ main := (
Vnull @parse_null |
Vfalse @parse_false |
Vtrue @parse_true |
+ VNaN @parse_nan |
+ VInfinity @parse_infinity |
begin_number >parse_number |
begin_string >parse_string |
begin_array >parse_array |
@@ -435,7 +468,11 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
*
* _opts_ can have the following keys:
* * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- * structures. Disable depth checking with :max_nesting => false.
+ * structures. Disable depth checking with :max_nesting => false|nil|0, it
+ * defaults to 19.
+ * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
+ * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
+ * false.
*/
static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
{
@@ -451,14 +488,15 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
rb_raise(eParserError, "A JSON text must at least contain two octets!");
}
json->max_nesting = 19;
+ json->allow_nan = 0;
if (!NIL_P(opts)) {
opts = rb_convert_type(opts, T_HASH, "Hash", "to_hash");
if (NIL_P(opts)) {
rb_raise(rb_eArgError, "opts needs to be like a hash");
} else {
- VALUE s_max_nesting = ID2SYM(i_max_nesting);
- if (st_lookup(RHASH(opts)->tbl, s_max_nesting, 0)) {
- VALUE max_nesting = rb_hash_aref(opts, s_max_nesting);
+ VALUE tmp = ID2SYM(i_max_nesting);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE max_nesting = rb_hash_aref(opts, tmp);
if (RTEST(max_nesting)) {
Check_Type(max_nesting, T_FIXNUM);
json->max_nesting = FIX2INT(max_nesting);
@@ -466,6 +504,11 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
json->max_nesting = 0;
}
}
+ tmp = ID2SYM(i_allow_nan);
+ if (st_lookup(RHASH(opts)->tbl, tmp, 0)) {
+ VALUE allow_nan = rb_hash_aref(opts, tmp);
+ if (RTEST(allow_nan)) json->allow_nan = 1;
+ }
}
}
json->current_nesting = 0;
@@ -561,9 +604,14 @@ void Init_parser()
rb_define_method(cParser, "parse", cParser_parse, 0);
rb_define_method(cParser, "source", cParser_source, 0);
+ CNaN = rb_const_get(mJSON, rb_intern("NaN"));
+ CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
+ CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
+
i_json_creatable_p = rb_intern("json_creatable?");
i_json_create = rb_intern("json_create");
i_create_id = rb_intern("create_id");
i_chr = rb_intern("chr");
i_max_nesting = rb_intern("max_nesting");
+ i_allow_nan = rb_intern("allow_nan");
}