Using jsonp_strtod instead of casting to double to catch double overflow

This commit is contained in:
Jason Choy 2013-06-11 15:09:08 +01:00
parent c3e9725f02
commit 120a90a155
3 changed files with 23 additions and 5 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}