Disallow NaN or Inf real values
authorPetri Lehtinen <petri@digip.org>
Thu, 13 Sep 2012 18:30:19 +0000 (21:30 +0300)
committerPetri Lehtinen <petri@digip.org>
Thu, 13 Sep 2012 18:30:19 +0000 (21:30 +0300)
src/value.c
test/suites/api/test_number.c

index 547eb5d..ba9908e 100644 (file)
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
+#include <math.h>
 
 #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;
index c6fab6d..c256598 100644 (file)
@@ -5,6 +5,7 @@
  * it under the terms of the MIT license. See LICENSE for details.
  */
 
+#include <math.h>
 #include <jansson.h>
 #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
 }