diff --git a/doc/apiref.rst b/doc/apiref.rst index 036bb69..d92fb3b 100644 --- a/doc/apiref.rst +++ b/doc/apiref.rst @@ -954,7 +954,9 @@ macros can be ORed together to obtain *flags*. JSON defines only one number type. Jansson distinguishes between ints and reals. For more information see :ref:`real-vs-integer`. With this flag enabled the decoder interprets all numbers as real - values. + values. Integers that do not have an exact double representation + will silently result in a loss of precision. Integers that cause + a double overflow will cause an error. .. versionadded:: 2.5 diff --git a/src/load.c b/src/load.c index 235c1e2..b671892 100644 --- a/src/load.c +++ b/src/load.c @@ -775,6 +775,7 @@ error: static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) { json_t *json; + double value; switch(lex->token) { case TOKEN_STRING: { @@ -784,7 +785,11 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) case TOKEN_INTEGER: { if (flags & JSON_DECODE_INT_AS_REAL) { - json = json_real(lex->value.integer); + if(jsonp_strtod(&lex->saved_text, &value)) { + error_set(error, lex, "real number overflow"); + return NULL; + } + json = json_real(value); } else { json = json_integer(lex->value.integer); } diff --git a/test/suites/api/test_load.c b/test/suites/api/test_load.c index 72667cb..6eddb34 100644 --- a/test/suites/api/test_load.c +++ b/test/suites/api/test_load.c @@ -87,14 +87,25 @@ static void decode_any() json_decref(json); } -static void decode_no_int() +static void decode_int_as_real() { json_t *json; json_error_t error; + // This number cannot be represented exactly by a double + const char *imprecise = "9007199254740993"; + json_int_t expected = 9007199254740992ll; + json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error); if (!json || !json_is_real(json) || json_real_value(json) != 42.0) - fail("json_load decode no int failed - int"); + fail("json_load decode int as real failed - int"); + json_decref(json); + + // Tests that large numbers are handled correctly + json = json_loads(imprecise, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, + &error); + if (!json || !json_is_real(json) || expected != json_real_value(json)) + fail("json_load decode int as real failed - expected imprecision"); json_decref(json); } @@ -143,7 +154,7 @@ static void run_tests() reject_duplicates(); disable_eof_check(); decode_any(); - decode_no_int(); + decode_int_as_real(); load_wrong_args(); position(); }