diff --git a/json_util.c b/json_util.c index 2b5f858..5d9cada 100644 --- a/json_util.c +++ b/json_util.c @@ -263,7 +263,13 @@ int json_parse_uint64(const char *buf, uint64_t *retval) uint64_t val; errno = 0; - while (*buf == ' ') + /* strtoull() skips leading whitespace and then quietly negates a + * leading '-', wrapping the result into a huge value. We only skipped + * spaces here, so a '-' behind a tab/newline/etc slipped past the check + * below. Skip the same whitespace set strtoull() does so the rejection + * actually holds. */ + while (*buf == ' ' || *buf == '\t' || *buf == '\n' || *buf == '\v' || *buf == '\f' || + *buf == '\r') buf++; if (*buf == '-') return 1; /* error: uint cannot be negative */ diff --git a/tests/test_parse_int64.c b/tests/test_parse_int64.c index 5710b08..47a404f 100644 --- a/tests/test_parse_int64.c +++ b/tests/test_parse_int64.c @@ -145,6 +145,11 @@ int main(int argc, char **argv) strcpy(buf, "-9223372036854775808"); checkit_uint(buf); + // A negative value hidden behind non-space whitespace must still be + // rejected; strtoull() skips this whitespace and would wrap the '-'. + strcpy(buf, "\t-1"); + checkit_uint(buf); + strcpy(buf, " 1"); checkit_uint(buf); diff --git a/tests/test_parse_int64.expected b/tests/test_parse_int64.expected index 6dca94b..c6128ce 100644 --- a/tests/test_parse_int64.expected +++ b/tests/test_parse_int64.expected @@ -41,6 +41,7 @@ buf=1 parseit=0, value=1 buf=2147483647 parseit=0, value=2147483647 buf=-1 parseit=1, value=666 buf=-9223372036854775808 parseit=1, value=666 +buf= -1 parseit=1, value=666 buf= 1 parseit=0, value=1 buf=00001234 parseit=0, value=1234 buf=0001234x parseit=0, value=1234