diff --git a/src/value.c b/src/value.c index 547eb5d..ba9908e 100644 --- a/src/value.c +++ b/src/value.c @@ -10,12 +10,20 @@ #include #include #include +#include #include "jansson.h" #include "hashtable.h" #include "jansson_private.h" #include "utf.h" +/* Work around nonstandard isnan() and isinf() implementations */ +#ifndef isnan +static JSON_INLINE int isnan(double x) { return x != x; } +#endif +#ifndef isinf +static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); } +#endif static JSON_INLINE void json_init(json_t *json, json_type type) { @@ -731,7 +739,12 @@ static json_t *json_integer_copy(json_t *integer) json_t *json_real(double value) { - json_real_t *real = jsonp_malloc(sizeof(json_real_t)); + json_real_t *real; + + if(isnan(value) || isinf(value)) + return NULL; + + real = jsonp_malloc(sizeof(json_real_t)); if(!real) return NULL; json_init(&real->json, JSON_REAL); @@ -750,7 +763,7 @@ double json_real_value(const json_t *json) int json_real_set(json_t *json, double value) { - if(!json_is_real(json)) + if(!json_is_real(json) || isnan(value) || isinf(value)) return -1; json_to_real(json)->value = value; diff --git a/test/suites/api/test_number.c b/test/suites/api/test_number.c index c6fab6d..c256598 100644 --- a/test/suites/api/test_number.c +++ b/test/suites/api/test_number.c @@ -5,6 +5,7 @@ * it under the terms of the MIT license. See LICENSE for details. */ +#include #include #include "util.h" @@ -39,4 +40,34 @@ static void run_tests() json_decref(integer); json_decref(real); + +#ifdef NAN + real = json_real(NAN); + if(real != NULL) + fail("could construct a real from NaN"); + + real = json_real(1.0); + if(json_real_set(real, NAN) != -1) + fail("could set a real to NaN"); + + if(json_real_value(real) != 1.0) + fail("real value changed unexpectedly"); + + json_decref(real); +#endif + +#ifdef INFINITY + real = json_real(INFINITY); + if(real != NULL) + fail("could construct a real from Inf"); + + real = json_real(1.0); + if(json_real_set(real, INFINITY) != -1) + fail("could set a real to Inf"); + + if(json_real_value(real) != 1.0) + fail("real value changed unexpectedly"); + + json_decref(real); +#endif }