]> granicus.if.org Git - json-c/commitdiff
Explicitly check for integer overflow/underflow when parsing integers with JSON_TOKEN...
authorEric Haszlakiewicz <erh+git@nimenees.com>
Sun, 30 Oct 2022 19:29:15 +0000 (19:29 +0000)
committerEric Haszlakiewicz <erh+git@nimenees.com>
Sun, 30 Oct 2022 19:39:30 +0000 (19:39 +0000)
ChangeLog
json_tokener.c
tests/test_parse.c

index d04edbe125c0cff4dfa9791b363361cbc5239655..5108a9e946cbfa4ce0986013dd0d816b14754b2c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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)
index 0c09b66e8dd6dbd1c635012d72da6c3124c07edd..753d4f22c9b49be7f3f9772c42d4d81201627ac6 100644 (file)
@@ -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))
                                        {
index 4a8e3d74e8bf29edbea13de0286d1670d83d6424..92d822a7da59d9cf4983afb1645dc26b53aacd32 100644 (file)
@@ -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... */