mirror of
https://github.com/DaveGamble/cJSON.git
synced 2025-09-15 12:58:50 +08:00
Compare commits
4 Commits
be2c083d01
...
da5d093022
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da5d093022 | ||
|
|
c859b25da0 | ||
|
|
5c89f9b7ca | ||
|
|
755622d9df |
12
CHANGELOG.md
12
CHANGELOG.md
@ -1,3 +1,15 @@
|
||||
1.7.19 (Sep 9, 2025)
|
||||
======
|
||||
Fixes:
|
||||
------
|
||||
* Fix indentation (should use spaces), see #814
|
||||
* Fix spelling errors found by CodeSpell, see #841
|
||||
* Check for NULL in cJSON_DetachItemViaPointer, fixes #882, see #886
|
||||
* Fix #881, check overlap before calling strcpy in cJSON_SetValuestring, see #885
|
||||
* Fix #880 Max recursion depth for cJSON_Duplicate to prevent stack exhaustion, see #888
|
||||
* Allocate memory for the temporary buffer when paring numbers, see #939
|
||||
* fix the incorrect check in decode_array_index_from_pointer, see #957
|
||||
|
||||
1.7.18 (May 13, 2024)
|
||||
======
|
||||
Fixes:
|
||||
|
||||
@ -2,7 +2,7 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
project(cJSON
|
||||
VERSION 1.7.18
|
||||
VERSION 1.7.19
|
||||
LANGUAGES C)
|
||||
|
||||
cmake_policy(SET CMP0054 NEW) # set CMP0054 policy
|
||||
|
||||
@ -24,6 +24,7 @@ Contributors:
|
||||
* [Debora Grosse](https://github.com/DeboraG)
|
||||
* [dieyushi](https://github.com/dieyushi)
|
||||
* [Dōngwén Huáng (黄东文)](https://github.com/DongwenHuang)
|
||||
* [Dominik](https://github.com/DL6ER)
|
||||
* [Donough Liu](https://github.com/ldm0)
|
||||
* [Erez Oxman](https://github.com/erez-o)
|
||||
* Eswar Yaganti
|
||||
@ -80,6 +81,8 @@ Contributors:
|
||||
* [Stephan Gatzka](https://github.com/gatzka)
|
||||
* [Tony Langhammer](https://github.com/BigBrainAFK)
|
||||
* [Vemake](https://github.com/vemakereporter)
|
||||
* [vwvw](https://github.com/vwvw)
|
||||
* [warmsocks](https://github.com/warmsocks)
|
||||
* [Wei Tan](https://github.com/tan-wei)
|
||||
* [Weston Schmidt](https://github.com/schmidtw)
|
||||
* [xiaomianhehe](https://github.com/xiaomianhehe)
|
||||
|
||||
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ CJSON_TEST_SRC = cJSON.c test.c
|
||||
|
||||
LDLIBS = -lm
|
||||
|
||||
LIBVERSION = 1.7.18
|
||||
LIBVERSION = 1.7.19
|
||||
CJSON_SOVERSION = 1
|
||||
UTILS_SOVERSION = 1
|
||||
|
||||
|
||||
63
cJSON.c
63
cJSON.c
@ -117,7 +117,7 @@ CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
|
||||
}
|
||||
|
||||
/* 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 != 18)
|
||||
#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19)
|
||||
#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
|
||||
#endif
|
||||
|
||||
@ -185,27 +185,43 @@ static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
|
||||
|
||||
static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
|
||||
|
||||
static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
|
||||
static char* cJSON_strndup(const char* string, const size_t length, const internal_hooks * const hooks)
|
||||
{
|
||||
size_t length = 0;
|
||||
unsigned char *copy = NULL;
|
||||
char *copy = NULL;
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
string = "";
|
||||
}
|
||||
|
||||
if (string == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = strlen((const char*)string) + sizeof("");
|
||||
copy = (unsigned char*)hooks->allocate(length);
|
||||
/* allocate an extra byte for the null terminator */
|
||||
copy = (char *) hooks->allocate(length + 1);
|
||||
if (copy == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
memcpy(copy, string, length);
|
||||
copy[length] = '\0';
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
static char* cJSON_strdup(const char *string, const internal_hooks * const hooks)
|
||||
{
|
||||
if (string == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cJSON_strndup(string, strlen(string), hooks);
|
||||
}
|
||||
|
||||
|
||||
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
|
||||
{
|
||||
if (hooks == NULL)
|
||||
@ -456,7 +472,7 @@ CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
|
||||
strcpy(object->valuestring, valuestring);
|
||||
return object->valuestring;
|
||||
}
|
||||
copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
|
||||
copy = cJSON_strndup(valuestring, v1_len, &global_hooks);
|
||||
if (copy == NULL)
|
||||
{
|
||||
return NULL;
|
||||
@ -2081,7 +2097,7 @@ static cJSON_bool add_item_to_object(cJSON * const object, const char * const st
|
||||
}
|
||||
else
|
||||
{
|
||||
new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
|
||||
new_key = cJSON_strdup(string, hooks);
|
||||
if (new_key == NULL)
|
||||
{
|
||||
return false;
|
||||
@ -2421,7 +2437,7 @@ static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSO
|
||||
{
|
||||
cJSON_free(replacement->string);
|
||||
}
|
||||
replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
|
||||
replacement->string = cJSON_strdup(string, &global_hooks);
|
||||
if (replacement->string == NULL)
|
||||
{
|
||||
return false;
|
||||
@ -2514,19 +2530,28 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
|
||||
{
|
||||
if (string == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cJSON_CreateStringWithLength(string, strlen(string));
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringWithLength(const char *string, const size_t length)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item(&global_hooks);
|
||||
if(item)
|
||||
{
|
||||
item->type = cJSON_String;
|
||||
item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
|
||||
item->valuestring = cJSON_strndup(string, length, &global_hooks);
|
||||
if(!item->valuestring)
|
||||
{
|
||||
cJSON_Delete(item);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -2564,12 +2589,22 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
|
||||
{
|
||||
if (raw == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cJSON_CreateRawWithLength(raw, strlen(raw));
|
||||
}
|
||||
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRawWithLength(const char *raw, const size_t length)
|
||||
{
|
||||
cJSON *item = cJSON_New_Item(&global_hooks);
|
||||
if(item)
|
||||
{
|
||||
item->type = cJSON_Raw;
|
||||
item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
|
||||
item->valuestring = cJSON_strndup(raw, length, &global_hooks);
|
||||
if(!item->valuestring)
|
||||
{
|
||||
cJSON_Delete(item);
|
||||
@ -2795,7 +2830,7 @@ cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
|
||||
newitem->valuedouble = item->valuedouble;
|
||||
if (item->valuestring)
|
||||
{
|
||||
newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
|
||||
newitem->valuestring = cJSON_strdup(item->valuestring, &global_hooks);
|
||||
if (!newitem->valuestring)
|
||||
{
|
||||
goto fail;
|
||||
@ -2803,7 +2838,7 @@ cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
|
||||
}
|
||||
if (item->string)
|
||||
{
|
||||
newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
|
||||
newitem->string = (item->type&cJSON_StringIsConst) ? item->string : cJSON_strdup(item->string, &global_hooks);
|
||||
if (!newitem->string)
|
||||
{
|
||||
goto fail;
|
||||
|
||||
4
cJSON.h
4
cJSON.h
@ -81,7 +81,7 @@ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJ
|
||||
/* project version */
|
||||
#define CJSON_VERSION_MAJOR 1
|
||||
#define CJSON_VERSION_MINOR 7
|
||||
#define CJSON_VERSION_PATCH 18
|
||||
#define CJSON_VERSION_PATCH 19
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
@ -204,8 +204,10 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateStringWithLength(const char *string, size_t length);
|
||||
/* raw json */
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateRawWithLength(const char *raw, size_t length);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
|
||||
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
|
||||
|
||||
|
||||
@ -426,7 +426,9 @@ static void cjson_functions_should_not_crash_with_null_pointers(void)
|
||||
TEST_ASSERT_FALSE(cJSON_IsObject(NULL));
|
||||
TEST_ASSERT_FALSE(cJSON_IsRaw(NULL));
|
||||
TEST_ASSERT_NULL(cJSON_CreateString(NULL));
|
||||
TEST_ASSERT_NULL(cJSON_CreateStringWithLength(NULL, 10));
|
||||
TEST_ASSERT_NULL(cJSON_CreateRaw(NULL));
|
||||
TEST_ASSERT_NULL(cJSON_CreateRawWithLength(NULL, 10));
|
||||
TEST_ASSERT_NULL(cJSON_CreateIntArray(NULL, 10));
|
||||
TEST_ASSERT_NULL(cJSON_CreateFloatArray(NULL, 10));
|
||||
TEST_ASSERT_NULL(cJSON_CreateDoubleArray(NULL, 10));
|
||||
@ -572,6 +574,32 @@ static void cjson_get_number_value_should_get_a_number(void)
|
||||
cJSON_Delete(string);
|
||||
}
|
||||
|
||||
static void cjson_create_string_with_length_should_create_a_string(void)
|
||||
{
|
||||
cJSON *string = cJSON_CreateStringWithLength("testtest", 4);
|
||||
cJSON *stringNull = cJSON_CreateStringWithLength(NULL, 0);
|
||||
TEST_ASSERT_EQUAL_INT(cJSON_String, string->type);
|
||||
TEST_ASSERT_TRUE(strcmp(string->valuestring, "test") == 0);
|
||||
TEST_ASSERT_NOT_NULL(stringNull);
|
||||
TEST_ASSERT_EQUAL_INT(cJSON_String, stringNull->type);
|
||||
TEST_ASSERT_TRUE(strcmp(stringNull->valuestring, "") == 0);
|
||||
cJSON_Delete(string);
|
||||
cJSON_Delete(stringNull);
|
||||
}
|
||||
|
||||
static void cjson_create_raw_with_length_should_create_a_string(void)
|
||||
{
|
||||
cJSON *raw = cJSON_CreateRawWithLength("testtest", 4);
|
||||
cJSON *rawNull = cJSON_CreateRawWithLength(NULL, 0);
|
||||
TEST_ASSERT_EQUAL_INT(cJSON_Raw, raw->type);
|
||||
TEST_ASSERT_TRUE(strcmp(raw->valuestring, "test") == 0);
|
||||
TEST_ASSERT_NOT_NULL(rawNull);
|
||||
TEST_ASSERT_EQUAL_INT(cJSON_Raw, rawNull->type);
|
||||
TEST_ASSERT_TRUE(strcmp(rawNull->valuestring, "") == 0);
|
||||
cJSON_Delete(raw);
|
||||
cJSON_Delete(rawNull);
|
||||
}
|
||||
|
||||
static void cjson_create_string_reference_should_create_a_string_reference(void)
|
||||
{
|
||||
const char *string = "I am a string!";
|
||||
@ -640,7 +668,7 @@ static void cjson_add_item_to_object_should_not_use_after_free_when_string_is_al
|
||||
{
|
||||
cJSON *object = cJSON_CreateObject();
|
||||
cJSON *number = cJSON_CreateNumber(42);
|
||||
char *name = (char *)cJSON_strdup((const unsigned char *)"number", &global_hooks);
|
||||
char *name = cJSON_strdup("number", &global_hooks);
|
||||
|
||||
TEST_ASSERT_NOT_NULL(object);
|
||||
TEST_ASSERT_NOT_NULL(number);
|
||||
@ -823,6 +851,8 @@ int CJSON_CDECL main(void)
|
||||
RUN_TEST(skip_utf8_bom_should_not_skip_bom_if_not_at_beginning);
|
||||
RUN_TEST(cjson_get_string_value_should_get_a_string);
|
||||
RUN_TEST(cjson_get_number_value_should_get_a_number);
|
||||
RUN_TEST(cjson_create_string_with_length_should_create_a_string);
|
||||
RUN_TEST(cjson_create_raw_with_length_should_create_a_string);
|
||||
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_array_reference_should_create_an_array_reference);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user