Merge pull request #957 from dngr2/fix/strict-number-grammar

Check the whole RFC 8259 number grammar in strict mode
This commit is contained in:
Eric Hawicz
2026-08-16 21:37:39 -04:00
committed by GitHub
3 changed files with 89 additions and 6 deletions
+57 -5
View File
@@ -1045,15 +1045,67 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char *
} }
if (tok->flags & JSON_TOKENER_STRICT) if (tok->flags & JSON_TOKENER_STRICT)
{ {
/* RFC 8259 forbids leading zeros in the integer part: /* Check the accumulated text against the RFC 8259 grammar:
* a '0' may only be followed by '.', 'e'/'E' or the end *
* of the number, so "01", "00" and "-0123" are invalid * number = [ minus ] int [ frac ] [ exp ]
* while "0", "-0" and "0.5" remain valid. * 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; const char *num = tok->pb->buf;
if (*num == '-') if (*num == '-')
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; tok->err = json_tokener_error_parse_number;
goto out; goto out;
+18
View File
@@ -375,6 +375,24 @@ struct incremental_step
/* ... but a lone zero, "-0" and a zero before the fraction stay valid. */ /* ... but a lone zero, "-0" and a zero before the fraction stay valid. */
{"[-0]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT}, {"[-0]", -1, -1, json_tokener_success, 1, JSON_TOKENER_STRICT},
{"[0.5]", -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", 5, 4, json_tokener_success, 1, 0},
{"[0e+0]", -1, -1, json_tokener_success, 1, 0}, {"[0e+0]", -1, -1, json_tokener_success, 1, 0},
+14 -1
View File
@@ -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, [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] , 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, [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 , 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+0] , 6) ... OK: got object of type [array]: [ 0e+0 ]
json_tokener_parse_ex(tok, 0e , 2) ... OK: got correct error: continue 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 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
================================== ==================================