diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2015-03-03 22:41:31 -0500 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2015-03-03 22:41:31 -0500 |
commit | 68d856f618fac279f7ff3e7439c90f3ecaee57ad (patch) | |
tree | 0d800d5373b62b63d60afea6e3de8e0cb8989861 | |
parent | 7e3a6c6b9d5e54032aa7e5ef593f898a7ca9bb50 (diff) | |
parent | 99d8fc975e059a5e1749d4dc6c07a02e9a629921 (diff) |
Tightening the number parsing algorithm
-rw-r--r-- | json_tokener.c | 37 | ||||
-rw-r--r-- | tests/test_parse.c | 20 | ||||
-rw-r--r-- | tests/test_parse.expected | 7 |
3 files changed, 62 insertions, 2 deletions
diff --git a/json_tokener.c b/json_tokener.c index fed6ad9..d9e9e24 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -668,10 +668,45 @@ struct json_object* json_tokener_parse_ex(struct json_tokener *tok, /* Advance until we change state */ const char *case_start = str; int case_len=0; + int is_exponent=0; + int negativesign_next_possible_location=1; while(c && strchr(json_number_chars, c)) { ++case_len; - if(c == '.' || c == 'e' || c == 'E') + + /* non-digit characters checks */ + /* note: since the main loop condition to get here was + an input starting with 0-9 or '-', we are + protected from input starting with '.' or + e/E. */ + if (c == '.') { + if (tok->is_double != 0) { + /* '.' can only be found once, and out of the exponent part. + Thus, if the input is already flagged as double, it + is invalid. */ + tok->err = json_tokener_error_parse_number; + goto out; + } tok->is_double = 1; + } + if (c == 'e' || c == 'E') { + if (is_exponent != 0) { + /* only one exponent possible */ + tok->err = json_tokener_error_parse_number; + goto out; + } + is_exponent = 1; + tok->is_double = 1; + /* the exponent part can begin with a negative sign */ + negativesign_next_possible_location = case_len + 1; + } + if (c == '-' && case_len != negativesign_next_possible_location) { + /* If the negative sign is not where expected (ie + start of input or start of exponent part), the + input is invalid. */ + tok->err = json_tokener_error_parse_number; + goto out; + } + if (!ADVANCE_CHAR(str, tok) || !PEEK_CHAR(c, tok)) { printbuf_memappend_fast(tok->pb, case_start, case_len); goto out; diff --git a/tests/test_parse.c b/tests/test_parse.c index 8808d0f..bc5389b 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -91,6 +91,23 @@ static void test_basic_parse() printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); json_object_put(new_obj); + new_obj = json_tokener_parse("12.3.4"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + /* was returning (int)2015 before patch, should return null */ + new_obj = json_tokener_parse("2015-01-15"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{\"FoO\" : -12.3E512}"); + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + + new_obj = json_tokener_parse("{\"FoO\" : -12.3E51.2}"); /* non-sensical, returns null */ + printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); + json_object_put(new_obj); + new_obj = json_tokener_parse("[\"\\n\"]"); printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj)); json_object_put(new_obj); @@ -195,6 +212,9 @@ struct incremental_step { { "1", 1, 1, json_tokener_continue, 0 }, { "2", 2, 1, json_tokener_success, 0 }, + /* Some bad formatting. Check we get the correct error status */ + { "2015-01-15", 10, 4, json_tokener_error_parse_number, 1 }, + /* Strings have a well defined end point, so we can stop at the quote */ { "\"blue\"", -1, -1, json_tokener_success, 0 }, diff --git a/tests/test_parse.expected b/tests/test_parse.expected index d49cbbb..6606260 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -14,6 +14,10 @@ new_obj.to_string()=-Infinity new_obj.to_string()=true new_obj.to_string()=12 new_obj.to_string()=12.3 +new_obj.to_string()=null +new_obj.to_string()=null +new_obj.to_string()={ "FoO": -12.3E512 } +new_obj.to_string()=null new_obj.to_string()=[ "\n" ] new_obj.to_string()=[ "\nabc\n" ] new_obj.to_string()=[ null ] @@ -48,6 +52,7 @@ json_tokener_parse_ex(tok, {"x": 123 }"X", 14) ... OK: got object of type [obje json_tokener_parse_ex(tok, "Y" , 3) ... OK: got object of type [string]: "Y" json_tokener_parse_ex(tok, 1 , 1) ... OK: got correct error: continue json_tokener_parse_ex(tok, 2 , 2) ... OK: got object of type [int]: 12 +json_tokener_parse_ex(tok, 2015-01-15 , 10) ... OK: got correct error: number expected json_tokener_parse_ex(tok, "blue" , 6) ... OK: got object of type [string]: "blue" json_tokener_parse_ex(tok, "\"" , 4) ... OK: got object of type [string]: "\"" json_tokener_parse_ex(tok, "\\" , 4) ... OK: got object of type [string]: "\\" @@ -61,5 +66,5 @@ json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got object of type [array] json_tokener_parse_ex(tok, [1,2,,3,] , 9) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, [1,2,3,] , 8) ... OK: got correct error: unexpected character json_tokener_parse_ex(tok, {"a":1,} , 8) ... OK: got correct error: unexpected character -End Incremental Tests OK=29 ERROR=0 +End Incremental Tests OK=30 ERROR=0 ================================== |