Merge pull request #249 from DaveGamble/fix-add-item

Release 1.7.4
This commit is contained in:
Max Bruckner 2018-03-02 20:04:29 +01:00 committed by GitHub
commit 6f264b5d0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 52 additions and 21 deletions

View File

@ -1,4 +1,10 @@
1.7.2 1.7.4
=====
Fixes:
------
* Fix potential use after free if the `string` parameter to `cJSON_AddItemToObject` is an alias of the `string` property of the object that is added (#248). Thanks @hhallen for reporting.
1.7.3
===== =====
Fixes: Fixes:
------ ------

View File

@ -7,7 +7,7 @@ include(GNUInstallDirs)
set(PROJECT_VERSION_MAJOR 1) set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 7) set(PROJECT_VERSION_MINOR 7)
set(PROJECT_VERSION_PATCH 3) set(PROJECT_VERSION_PATCH 4)
set(CJSON_VERSION_SO 1) set(CJSON_VERSION_SO 1)
set(CJSON_UTILS_VERSION_SO 1) set(CJSON_UTILS_VERSION_SO 1)
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")

View File

@ -8,7 +8,7 @@ CJSON_TEST_SRC = cJSON.c test.c
LDLIBS = -lm LDLIBS = -lm
LIBVERSION = 1.7.3 LIBVERSION = 1.7.4
CJSON_SOVERSION = 1 CJSON_SOVERSION = 1
UTILS_SOVERSION = 1 UTILS_SOVERSION = 1

39
cJSON.c
View File

@ -82,7 +82,7 @@ CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
} }
/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ /* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 3) #if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 4)
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same. #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
#endif #endif
@ -1895,32 +1895,37 @@ static void* cast_away_const(const void* string)
static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
{ {
char *new_key = NULL;
int new_type = cJSON_Invalid;
if ((object == NULL) || (string == NULL) || (item == NULL)) if ((object == NULL) || (string == NULL) || (item == NULL))
{ {
return false; return false;
} }
if (constant_key)
{
new_key = (char*)cast_away_const(string);
new_type = item->type | cJSON_StringIsConst;
}
else
{
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (new_key == NULL)
{
return false;
}
new_type = item->type & ~cJSON_StringIsConst;
}
if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
{ {
hooks->deallocate(item->string); hooks->deallocate(item->string);
} }
if (constant_key) item->string = new_key;
{ item->type = new_type;
item->string = (char*)cast_away_const(string);
item->type |= cJSON_StringIsConst;
}
else
{
char *key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
if (key == NULL)
{
return false;
}
item->string = key;
item->type &= ~cJSON_StringIsConst;
}
return add_item_to_array(object, item); return add_item_to_array(object, item);
} }

View File

@ -31,7 +31,7 @@ extern "C"
/* project version */ /* project version */
#define CJSON_VERSION_MAJOR 1 #define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7 #define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 3 #define CJSON_VERSION_PATCH 4
#include <stddef.h> #include <stddef.h>

View File

@ -508,6 +508,25 @@ static void cjson_create_array_reference_should_create_an_array_reference(void)
cJSON_Delete(number_reference); cJSON_Delete(number_reference);
} }
static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased(void)
{
cJSON *object = cJSON_CreateObject();
cJSON *number = cJSON_CreateNumber(42);
char *name = (char*)cJSON_strdup((const unsigned char*)"number", &global_hooks);
TEST_ASSERT_NOT_NULL(object);
TEST_ASSERT_NOT_NULL(number);
TEST_ASSERT_NOT_NULL(name);
number->string = name;
/* The following should not have a use after free
* that would show up in valgrind or with AddressSanitizer */
cJSON_AddItemToObject(object, number->string, number);
cJSON_Delete(object);
}
int main(void) int main(void)
{ {
UNITY_BEGIN(); UNITY_BEGIN();
@ -530,6 +549,7 @@ int main(void)
RUN_TEST(cjson_create_string_reference_should_create_a_string_reference); RUN_TEST(cjson_create_string_reference_should_create_a_string_reference);
RUN_TEST(cjson_create_object_reference_should_create_an_object_reference); RUN_TEST(cjson_create_object_reference_should_create_an_object_reference);
RUN_TEST(cjson_create_array_reference_should_create_an_array_reference); RUN_TEST(cjson_create_array_reference_should_create_an_array_reference);
RUN_TEST(cjson_add_item_to_object_should_not_use_after_free_when_string_is_aliased);
return UNITY_END(); return UNITY_END();
} }