From 8943c733455f12c82c8c82bd9f1c848ae8e91b09 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Thu, 2 Apr 2020 16:02:24 +0800 Subject: [PATCH 1/2] comparing double value with DBL_EPSILON --- Makefile | 2 +- cJSON.c | 14 ++++++++++++-- cJSON.h | 5 ----- cJSON_Utils.c | 5 ++++- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 08fcc22..0e58d5c 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ else endif PIC_FLAGS = -fPIC -R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion -Wfloat-equal $(CFLAGS) +R_CFLAGS = $(PIC_FLAGS) -pedantic -Wall -Werror -Wstrict-prototypes -Wwrite-strings -Wshadow -Winit-self -Wcast-align -Wformat=2 -Wmissing-prototypes -Wstrict-overflow=2 -Wcast-qual -Wc++-compat -Wundef -Wswitch-default -Wconversion $(CFLAGS) uname := $(shell sh -c 'uname -s 2>/dev/null || echo false') diff --git a/cJSON.c b/cJSON.c index b0e744e..9fc4ffb 100644 --- a/cJSON.c +++ b/cJSON.c @@ -43,6 +43,7 @@ #include #include #include +#include #ifdef ENABLE_LOCALES #include @@ -68,6 +69,14 @@ #endif #define false ((cJSON_bool)0) +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + typedef struct { const unsigned char *json; size_t position; @@ -483,7 +492,8 @@ static void update_offset(printbuffer * const buffer) /* securely comparison of floating-point variables */ static cJSON_bool compare_double(double a, double b) { - return (fabs(a - b) <= CJSON_DOUBLE_PRECISION); + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); } /* Render the number nicely from the given item into a string. */ @@ -503,7 +513,7 @@ static cJSON_bool print_number(const cJSON * const item, printbuffer * const out } /* This checks for NaN and Infinity */ - if ((d * 0) != 0) + if (isnan(d) || isinf(d)) { length = sprintf((char*)number_buffer, "null"); } diff --git a/cJSON.h b/cJSON.h index 2c53562..753b1ad 100644 --- a/cJSON.h +++ b/cJSON.h @@ -137,11 +137,6 @@ typedef int cJSON_bool; #define CJSON_NESTING_LIMIT 1000 #endif -/* Precision of double variables comparison */ -#ifndef CJSON_DOUBLE_PRECISION -#define CJSON_DOUBLE_PRECISION .0000000000000001 -#endif - /* returns the version of cJSON as a string */ CJSON_PUBLIC(const char*) cJSON_Version(void); diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 3a535b1..c750f7f 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #if defined(_MSC_VER) #pragma warning (pop) @@ -109,7 +111,8 @@ static int compare_strings(const unsigned char *string1, const unsigned char *st /* securely comparison of floating-point variables */ static cJSON_bool compare_double(double a, double b) { - return (fabs(a - b) <= CJSON_DOUBLE_PRECISION); + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); } From 4e114c1f3132e1a4db46ab8e8c6aa33ecde3def8 Mon Sep 17 00:00:00 2001 From: Alanscut Date: Thu, 2 Apr 2020 16:24:10 +0800 Subject: [PATCH 2/2] update testcase, fixes #433 --- tests/compare_tests.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/compare_tests.c b/tests/compare_tests.c index 307d0e8..797c774 100644 --- a/tests/compare_tests.c +++ b/tests/compare_tests.c @@ -64,6 +64,9 @@ static void cjson_compare_should_compare_numbers(void) TEST_ASSERT_TRUE(compare_from_string("1", "1", false)); TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", true)); TEST_ASSERT_TRUE(compare_from_string("0.0001", "0.0001", false)); + TEST_ASSERT_TRUE(compare_from_string("1E100", "10E99", false)); + + TEST_ASSERT_FALSE(compare_from_string("0.5E-100", "0.5E-101", false)); TEST_ASSERT_FALSE(compare_from_string("1", "2", true)); TEST_ASSERT_FALSE(compare_from_string("1", "2", false));