diff --git a/json_tokener.c b/json_tokener.c index b723f13..cfa01ab 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -1045,15 +1045,67 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * } if (tok->flags & JSON_TOKENER_STRICT) { - /* RFC 8259 forbids leading zeros in the integer part: - * a '0' may only be followed by '.', 'e'/'E' or the end - * of the number, so "01", "00" and "-0123" are invalid - * while "0", "-0" and "0.5" remain valid. + /* Check the accumulated text against the RFC 8259 grammar: + * + * number = [ minus ] int [ frac ] [ exp ] + * int = zero / ( digit1-9 *DIGIT ) + * frac = decimal-point 1*DIGIT + * exp = e [ minus / plus ] 1*DIGIT + * + * so the integer part is mandatory and may not carry a + * leading zero, and both the fraction and the exponent + * need at least one digit of their own. That rejects + * "01", ".5", "-.123", "1.", "2.e3" and "1e", while + * "0", "-0", "0.5" and "2e3" stay valid. */ const char *num = tok->pb->buf; if (*num == '-') num++; - if (num[0] == '0' && num[1] >= '0' && num[1] <= '9') + if (*num == '0') + { + num++; + if (*num >= '0' && *num <= '9') + { + tok->err = json_tokener_error_parse_number; + goto out; + } + } + else if (*num >= '1' && *num <= '9') + { + while (*num >= '0' && *num <= '9') + num++; + } + else + { + /* no integer part at all, e.g. ".5" or "-.123" */ + tok->err = json_tokener_error_parse_number; + goto out; + } + if (*num == '.') + { + num++; + if (!(*num >= '0' && *num <= '9')) + { + tok->err = json_tokener_error_parse_number; + goto out; + } + while (*num >= '0' && *num <= '9') + num++; + } + if (*num == 'e' || *num == 'E') + { + num++; + if (*num == '+' || *num == '-') + num++; + if (!(*num >= '0' && *num <= '9')) + { + tok->err = json_tokener_error_parse_number; + goto out; + } + while (*num >= '0' && *num <= '9') + num++; + } + if (*num != '\0') { tok->err = json_tokener_error_parse_number; goto out; diff --git a/tests/test_parse.c b/tests/test_parse.c index 897863a..220ce5e 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -375,6 +375,24 @@ struct incremental_step /* ... but a lone zero, "-0" and a zero before the fraction stay valid. */ {"[-0]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, {"[0.5]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, + /* RFC 8259 wants a digit either side of the decimal point and after the + * exponent marker, so a bare "1." or "2.e3" is not a number ... */ + {"[1.]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[-2.]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[2.e3]", -1, 5, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[2.e+3]", -1, 6, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[0.e1]", -1, 5, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[1e]", -1, 3, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + {"[1e+]", -1, 4, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + /* ... and the integer part is mandatory, so "-.123" is not a number either + * (a bare ".5" never reaches the number state at all). */ + {"[-.123]", -1, 6, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + /* The well-formed spellings of the same values stay valid. */ + {"[1.0]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, + {"[2e3]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, + {"[2E-3]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, + {"[0.123]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, + {"[-0.123]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, {"0e+0", 5, 4, json_tokener_success, 1, 0}, {"[0e+0]", -1, -1, json_tokener_success, 1, 0}, diff --git a/tests/test_parse.expected b/tests/test_parse.expected index acf0594..b409a36 100644 --- a/tests/test_parse.expected +++ b/tests/test_parse.expected @@ -163,6 +163,19 @@ json_tokener_parse_ex(tok, [-0123] , 7) ... OK: got correct error: number json_tokener_parse_ex(tok, [01.5] , 6) ... OK: got correct error: number expected json_tokener_parse_ex(tok, [-0] , 4) ... OK: got object of type [array]: [ 0 ] json_tokener_parse_ex(tok, [0.5] , 5) ... OK: got object of type [array]: [ 0.5 ] +json_tokener_parse_ex(tok, [1.] , 4) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [-2.] , 5) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [2.e3] , 6) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [2.e+3] , 7) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [0.e1] , 6) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [1e] , 4) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [1e+] , 5) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [-.123] , 7) ... OK: got correct error: number expected +json_tokener_parse_ex(tok, [1.0] , 5) ... OK: got object of type [array]: [ 1.0 ] +json_tokener_parse_ex(tok, [2e3] , 5) ... OK: got object of type [array]: [ 2e3 ] +json_tokener_parse_ex(tok, [2E-3] , 6) ... OK: got object of type [array]: [ 2E-3 ] +json_tokener_parse_ex(tok, [0.123] , 7) ... OK: got object of type [array]: [ 0.123 ] +json_tokener_parse_ex(tok, [-0.123] , 8) ... OK: got object of type [array]: [ -0.123 ] json_tokener_parse_ex(tok, 0e+0 , 5) ... OK: got object of type [double]: 0e+0 json_tokener_parse_ex(tok, [0e+0] , 6) ... OK: got object of type [array]: [ 0e+0 ] json_tokener_parse_ex(tok, 0e , 2) ... OK: got correct error: continue @@ -375,5 +388,5 @@ json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence json_tokener_parse_ex(tok, {"":1} , 7) ... OK: got correct error: invalid string sequence -End Incremental Tests OK=279 ERROR=0 +End Incremental Tests OK=292 ERROR=0 ==================================