Browse Source

Explicitly check for integer overflow/underflow when parsing integers with JSON_TOKENER_STRICT.

tags/json-c-0.17-20230812
Eric Haszlakiewicz 2 years ago
parent
commit
d6f46ae104
3 changed files with 46 additions and 0 deletions
  1. +3
    -0
      ChangeLog
  2. +11
    -0
      json_tokener.c
  3. +32
    -0
      tests/test_parse.c

+ 3
- 0
ChangeLog View File

@@ -16,6 +16,9 @@ Significant changes and bug fixes
closing curly or square braces on same line for empty objects or arrays. closing curly or square braces on same line for empty objects or arrays.
* Disable locale handling when targeting a uClibc system due to problems * Disable locale handling when targeting a uClibc system due to problems
with its duplocale() function. 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) 0.16 (up to commit 66dcdf5, 2022-04-13)


+ 11
- 0
json_tokener.c View File

@@ -17,6 +17,7 @@


#include "math_compat.h" #include "math_compat.h"
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <stddef.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] == '-' && if (!tok->is_double && tok->pb->buf[0] == '-' &&
json_parse_int64(tok->pb->buf, &num64) == 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); current = json_object_new_int64(num64);
if (current == NULL) if (current == NULL)
goto out; 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] != '-' && else if (!tok->is_double && tok->pb->buf[0] != '-' &&
json_parse_uint64(tok->pb->buf, &numuint64) == 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' && if (numuint64 && tok->pb->buf[0] == '0' &&
(tok->flags & JSON_TOKENER_STRICT)) (tok->flags & JSON_TOKENER_STRICT))
{ {


+ 32
- 0
tests/test_parse.c View File

@@ -438,6 +438,38 @@ struct incremental_step
{"1234", 5, 0, json_tokener_success, 0, 0}, {"1234", 5, 0, json_tokener_success, 0, 0},
{"1234", 5, 4, json_tokener_success, 1, 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... */ /* offset=1 because "n" is the start of "null". hmm... */
{"noodle", 7, 1, json_tokener_error_parse_null, 1, 0}, {"noodle", 7, 1, json_tokener_error_parse_null, 1, 0},
/* offset=2 because "na" is the start of "nan". hmm... */ /* offset=2 because "na" is the start of "nan". hmm... */


Loading…
Cancel
Save