summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchl <dev+github@bugness.org>2015-02-05 01:34:10 +0100
committerchl <dev+github@bugness.org>2015-02-05 01:50:37 +0100
commit99d8fc975e059a5e1749d4dc6c07a02e9a629921 (patch)
tree08da479bde67a5222b9dd5e5ba62e21ff46450ce
parentec4879ac5b502ae81f6b73450b960ede11ad2560 (diff)
Tightening the number parsing algorithm
Some badly formated "numbers" could get partly parsed, resulting in truncated results instead of raising an error. Examples : '1.2.3' -> (double)1.2 '2015-01-15' -> (int)2015 This patch is not perfect (ex: input can still end with a 'E', which is forbidden by json.org doc) but should avoid non-sensically formated input. Tests added.
-rw-r--r--json_tokener.c37
-rw-r--r--tests/test_parse.c20
-rw-r--r--tests/test_parse.expected7
3 files changed, 62 insertions, 2 deletions
diff --git a/json_tokener.c b/json_tokener.c
index 60e81f2..7cd8794 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
==================================