Compare commits

...

12 Commits

Author SHA1 Message Date
Max Bruckner
afd5d186b7 Release version 1.5.9 2017-09-08 13:54:24 +02:00
Max Bruckner
7456637793 CONTRIBUTORS.md: Add Robin Mallinson 2017-09-08 13:52:15 +02:00
Max Bruckner
d92754cd30 Add valgrind suppressions for ARMv7 2017-09-08 13:25:14 +02:00
Max Bruckner
e4980b65b9 Merge pull request #200 from rmallins/cJSON_ParseWithOpts_fix_ErrorPtr_behaviour
Fix error pointer behaviour of cJSON_ParseWithOpts()
2017-09-08 12:05:19 +02:00
rmallins
629c354390 Rewrite test for cJSON_ParseWithOpts() to expect non-null error
pointer in error case and change code to match new expectations.
2017-09-08 01:22:10 +01:00
rmallins
1b2236a9a6 Improve existing tests showing behaviour of Parse and ParseWithOpts functions. 2017-09-08 01:20:52 +01:00
Max Bruckner
1925d1bbe5 Release version 1.5.8 2017-08-21 11:06:10 +02:00
Max Bruckner
76b705576f Makefile: Fix 'make test'
make test tried to execute the test for cJSON_Utils, which has been
ported to CUnity tests.
2017-08-21 10:58:49 +02:00
Max Bruckner
88d66c5da9 Release version 1.5.7 2017-07-12 23:13:14 +02:00
Max Bruckner
954d61e5e7 Fix #189, ensure returns an invalid pointer
If realloc returns NULL, ensure didn't abort but returned
printbuffer.offset instead. If an attacker can control
printbuffer.offset and also make realloc fail at just the right moment,
this would make cJSON potentially write at an arbitrary memory address.
2017-07-12 23:02:31 +02:00
Max Bruckner
ecdff7837c Merge pull request #185 from jwilk-forks/spelling
Fix typos in json.dict
2017-07-08 20:16:33 +02:00
Jakub Wilk
a3c2eba991 Fix typos in json.dict 2017-07-08 09:39:06 +02:00
12 changed files with 95 additions and 21 deletions

View File

@@ -1,3 +1,18 @@
1.5.9
=====
* Set the global error pointer even if `return_parse_end` is passed to `cJSON_ParseWithOpts`. See #200, thanks @rmallins
1.5.8
=====
* Fix `make test` in the Makefile, thanks @YanhaoMo for reporting this (#195)
1.5.7
=====
Fixes:
------
* Fix a bug where realloc failing would return a pointer to an invalid memory address. This is a security issue as it could potentially be used by an attacker to write to arbitrary memory addresses. (see #189), fixed in (954d61e5e7cb9dc6c480fc28ac1cdceca07dd5bd), big thanks @timothyjohncarney for reporting this issue
* Fix a spelling mistake in the AFL fuzzer dictionary (#185), thanks @jwilk
1.5.6
=====
Fixes:

View File

@@ -7,7 +7,7 @@ project(cJSON C)
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 5)
set(PROJECT_VERSION_PATCH 6)
set(PROJECT_VERSION_PATCH 9)
set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")

View File

@@ -15,6 +15,7 @@ Contributors
* Ian Mobley
* Irwan Djadjadi
* [IvanVoid](https://github.com/npi3pak)
* [Jakub Wilk](https://github.com/jwilk)
* [Jiri Zouhar](https://github.com/loigu)
* [Jonathan Fether](https://github.com/jfether)
* [Julián Vásquez](https://github.com/juvasquezg)
@@ -29,6 +30,7 @@ Contributors
* [Pawel Winogrodzki](https://github.com/PawelWMS)
* [prefetchnta](https://github.com/prefetchnta)
* [Rafael Leal Dias](https://github.com/rafaeldias)
* [Robin Mallinson](https://github.com/rmallins)
* [Rod Vagg](https://github.com/rvagg)
* [Roland Meertens](https://github.com/rmeertens)
* [Romain Porte](https://github.com/MicroJoe)

View File

@@ -8,7 +8,7 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm
LIBVERSION = 1.5.6
LIBVERSION = 1.5.9
CJSON_SOVERSION = 1
UTILS_SOVERSION = 1
@@ -66,11 +66,10 @@ shared: $(CJSON_SHARED) $(UTILS_SHARED)
static: $(CJSON_STATIC) $(UTILS_STATIC)
tests: $(CJSON_TEST) $(UTILS_TEST)
tests: $(CJSON_TEST)
test: tests
./$(CJSON_TEST)
./$(UTILS_TEST)
.c.o:
$(CC) -c $(R_CFLAGS) $<
@@ -150,4 +149,4 @@ clean:
$(RM) $(CJSON_OBJ) $(UTILS_OBJ) #delete object files
$(RM) $(CJSON_SHARED) $(CJSON_SHARED_VERSION) $(CJSON_SHARED_SO) $(CJSON_STATIC) #delete cJSON
$(RM) $(UTILS_SHARED) $(UTILS_SHARED_VERSION) $(UTILS_SHARED_SO) $(UTILS_STATIC) #delete cJSON_Utils
$(RM) $(CJSON_TEST) $(UTILS_TEST) #delete tests
$(RM) $(CJSON_TEST) #delete test

16
cJSON.c
View File

@@ -58,7 +58,7 @@ CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
}
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 6)
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 5) || (CJSON_VERSION_PATCH != 9)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif
@@ -377,6 +377,14 @@ static unsigned char* ensure(printbuffer * const p, size_t needed)
{
/* reallocate with realloc if available */
newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
if (newbuffer == NULL)
{
p->hooks.deallocate(p->buffer);
p->length = 0;
p->buffer = NULL;
return NULL;
}
}
else
{
@@ -998,10 +1006,8 @@ fail:
{
*return_parse_end = (const char*)local_error.json + local_error.position;
}
else
{
global_error = local_error;
}
global_error = local_error;
}
return NULL;

View File

@@ -31,7 +31,7 @@ extern "C"
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 5
#define CJSON_VERSION_PATCH 6
#define CJSON_VERSION_PATCH 9
#include <stddef.h>
@@ -139,7 +139,7 @@ CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error. If not, then cJSON_GetErrorPtr() does the job. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */

View File

@@ -25,8 +25,8 @@ escape_sequence_r="\\r"
escape_sequence_t="\\t"
escape_sequence_quote="\\\""
escape_sequence_backslash="\\\\"
escapce_sequence_slash="\\/"
escpae_sequence_utf16_base="\\u"
escape_sequence_slash="\\/"
escape_sequence_utf16_base="\\u"
escape_sequence_utf16="\\u12ab"
number_integer="1"

View File

@@ -58,7 +58,7 @@ if(ENABLE_CJSON_TEST)
message(WARNING "Valgrind couldn't be found.")
unset(MEMORYCHECK_COMMAND)
else()
set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1)
set(MEMORYCHECK_COMMAND_OPTIONS --trace-children=yes --leak-check=full --error-exitcode=1 --suppressions=${CMAKE_CURRENT_SOURCE_DIR}/../valgrind.supp)
endif()
endif()

View File

@@ -410,6 +410,22 @@ static void cjson_functions_shouldnt_crash_with_null_pointers(void)
cJSON_Delete(item);
}
static void *failing_realloc(void *pointer, size_t size)
{
(void)size;
(void)pointer;
return NULL;
}
static void ensure_should_fail_on_failed_realloc(void)
{
printbuffer buffer = {NULL, 10, 0, 0, false, false, {&malloc, &free, &failing_realloc}};
buffer.buffer = (unsigned char*)malloc(100);
TEST_ASSERT_NOT_NULL(buffer.buffer);
TEST_ASSERT_NULL_MESSAGE(ensure(&buffer, 200), "Ensure didn't fail with failing realloc.");
}
int main(void)
{
UNITY_BEGIN();
@@ -425,6 +441,6 @@ int main(void)
RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);
RUN_TEST(cjson_replace_item_in_object_should_preserve_name);
RUN_TEST(cjson_functions_shouldnt_crash_with_null_pointers);
RUN_TEST(ensure_should_fail_on_failed_realloc);
return UNITY_END();
}

View File

@@ -142,7 +142,7 @@ static void file_test6_should_not_be_parsed(void)
tree = cJSON_Parse(test6);
TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse what is not JSON.");
TEST_ASSERT_EQUAL_STRING_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect.");
TEST_ASSERT_EQUAL_PTR_MESSAGE(test6, cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (test6 != NULL)
{
@@ -179,6 +179,22 @@ static void file_test11_should_be_parsed_and_printed(void)
do_test("test11");
}
static void test12_should_not_be_parsed(void)
{
const char *test12 = "{ \"name\": ";
cJSON *tree = NULL;
tree = cJSON_Parse(test12);
TEST_ASSERT_NULL_MESSAGE(tree, "Should fail to parse incomplete JSON.");
TEST_ASSERT_EQUAL_PTR_MESSAGE(test12 + strlen(test12), cJSON_GetErrorPtr(), "Error pointer is incorrect.");
if (tree != NULL)
{
cJSON_Delete(tree);
}
}
int main(void)
{
UNITY_BEGIN();
@@ -193,5 +209,6 @@ int main(void)
RUN_TEST(file_test9_should_be_parsed_and_printed);
RUN_TEST(file_test10_should_be_parsed_and_printed);
RUN_TEST(file_test11_should_be_parsed_and_printed);
RUN_TEST(test12_should_not_be_parsed);
return UNITY_END();
}

View File

@@ -40,11 +40,23 @@ static void parse_with_opts_should_handle_empty_strings(void)
{
const char empty_string[] = "";
const char *error_pointer = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, NULL, false));
error_pointer = cJSON_GetErrorPtr();
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string);
TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
TEST_ASSERT_NULL(cJSON_ParseWithOpts(empty_string, &error_pointer, false));
TEST_ASSERT_EQUAL_INT(0, error_pointer - empty_string);
TEST_ASSERT_EQUAL_PTR(empty_string, error_pointer);
TEST_ASSERT_EQUAL_PTR(empty_string, cJSON_GetErrorPtr());
}
static void parse_with_opts_should_handle_incomplete_json(void)
{
const char json[] = "{ \"name\": ";
const char *parse_end = NULL;
TEST_ASSERT_NULL(cJSON_ParseWithOpts(json, &parse_end, false));
TEST_ASSERT_EQUAL_PTR(json + strlen(json), parse_end);
TEST_ASSERT_EQUAL_PTR(json + strlen(json), cJSON_GetErrorPtr());
}
static void parse_with_opts_should_require_null_if_requested(void)
@@ -65,7 +77,7 @@ static void parse_with_opts_should_return_parse_end(void)
cJSON *item = cJSON_ParseWithOpts(json, &parse_end, false);
TEST_ASSERT_NOT_NULL(item);
TEST_ASSERT_EQUAL_INT(2, parse_end - json);
TEST_ASSERT_EQUAL_PTR(json + 2, parse_end);
cJSON_Delete(item);
}
@@ -75,6 +87,7 @@ int main(void)
RUN_TEST(parse_with_opts_should_handle_null);
RUN_TEST(parse_with_opts_should_handle_empty_strings);
RUN_TEST(parse_with_opts_should_handle_incomplete_json);
RUN_TEST(parse_with_opts_should_require_null_if_requested);
RUN_TEST(parse_with_opts_should_return_parse_end);

6
valgrind.supp Normal file
View File

@@ -0,0 +1,6 @@
{
suppress_ld_on_armv7
Memcheck:Cond
...
obj:*/ld-*.so
}