diff options
author | Eric Haszlakiewicz <erh+git@nimenees.com> | 2022-10-30 19:29:15 +0000 |
---|---|---|
committer | Eric Haszlakiewicz <erh+git@nimenees.com> | 2022-10-30 19:39:30 +0000 |
commit | d6f46ae104871360f84695737864870c97adfd14 (patch) | |
tree | f51954e029b1d7621351a872d7a9d0fc4d9c9bcb | |
parent | c50bf9df9cb7dacd682104d844029938522f0bda (diff) | |
download | json-c-d6f46ae104871360f84695737864870c97adfd14.tar.gz |
Explicitly check for integer overflow/underflow when parsing integers with JSON_TOKENER_STRICT.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | json_tokener.c | 11 | ||||
-rw-r--r-- | tests/test_parse.c | 32 |
3 files changed, 46 insertions, 0 deletions
@@ -16,6 +16,9 @@ Significant changes and bug fixes closing curly or square braces on same line for empty objects or arrays. * Disable locale handling when targeting a uClibc system due to problems with its duplocale() function. +* When parsing with JSON_TOKENER_STRICT set, integer overflow/underflow + now result in a json_tokener_error_parse_number. Without that flag + values are capped at INT64_MIN/UINT64_MAX. 0.16 (up to commit 66dcdf5, 2022-04-13) diff --git a/json_tokener.c b/json_tokener.c index 0c09b66..753d4f2 100644 --- a/json_tokener.c +++ b/json_tokener.c @@ -17,6 +17,7 @@ #include "math_compat.h" #include <assert.h> +#include <errno.h> #include <limits.h> #include <math.h> #include <stddef.h> @@ -991,6 +992,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * if (!tok->is_double && tok->pb->buf[0] == '-' && json_parse_int64(tok->pb->buf, &num64) == 0) { + if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_number; + goto out; + } current = json_object_new_int64(num64); if (current == NULL) goto out; @@ -998,6 +1004,11 @@ struct json_object *json_tokener_parse_ex(struct json_tokener *tok, const char * else if (!tok->is_double && tok->pb->buf[0] != '-' && json_parse_uint64(tok->pb->buf, &numuint64) == 0) { + if (errno == ERANGE && (tok->flags & JSON_TOKENER_STRICT)) + { + tok->err = json_tokener_error_parse_number; + goto out; + } if (numuint64 && tok->pb->buf[0] == '0' && (tok->flags & JSON_TOKENER_STRICT)) { diff --git a/tests/test_parse.c b/tests/test_parse.c index 4a8e3d7..92d822a 100644 --- a/tests/test_parse.c +++ b/tests/test_parse.c @@ -438,6 +438,38 @@ struct incremental_step {"1234", 5, 0, json_tokener_success, 0, 0}, {"1234", 5, 4, json_tokener_success, 1, 0}, + /* INT64_MAX */ + {"[9223372036854775807]", 22, 21, json_tokener_success, 1, 0}, + /* INT64_MAX+1 => parsed as uint64 */ + {"[9223372036854775808]", 22, 21, json_tokener_success, 1, 0}, + + /* INT64_MIN */ + {"[-9223372036854775808]", 23, 22, json_tokener_success, 1, 0}, + + /* INT64_MIN-1 => success, but value ends up capped */ + {"[-9223372036854775809]", 23, 22, json_tokener_success, 1, 0}, + + /* INT64_MIN-1 => failure due to underflow detected */ + {"[-9223372036854775809]", 23, 21, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + + /* UINT64_MAX */ + {"[18446744073709551615]", 23, 22, json_tokener_success, 1, 0}, + + /* UINT64_MAX+1 => success, but value ends up capped */ + {"[18446744073709551616]", 23, 22, json_tokener_success, 1, 0}, + + /* UINT64_MAX+1 => failure due to overflow detected */ + {"[18446744073709551616]", 23, 21, json_tokener_error_parse_number, 1, JSON_TOKENER_STRICT}, + + /* XXX this seems like a bug, should fail with _error_parse_number instead */ + {"18446744073709551616", 21, 20, json_tokener_error_parse_eof, 1, JSON_TOKENER_STRICT}, + + /* Exceeding integer limits as double parse OK */ + {"[9223372036854775808.0]", 24, 23, json_tokener_success, 1, 0}, + {"[-9223372036854775809.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT}, + {"[18446744073709551615.0]", 25, 24, json_tokener_success, 1, 0}, + {"[18446744073709551616.0]", 25, 24, json_tokener_success, 1, JSON_TOKENER_STRICT}, + /* offset=1 because "n" is the start of "null". hmm... */ {"noodle", 7, 1, json_tokener_error_parse_null, 1, 0}, /* offset=2 because "na" is the start of "nan". hmm... */ |