Skip to content

Commit

Permalink
adds 2 new public functions:
Browse files Browse the repository at this point in the history
 - cJSON_CreateRawWithLength: create a cJSON_Raw from a length limited input string
 - cJSON_CreateStringWithLength: create a cJSON_String from a length limited input string
  • Loading branch information
ste-lam committed Aug 31, 2024
1 parent 078c4e6 commit 83779b2
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 21 deletions.
71 changes: 51 additions & 20 deletions cJSON.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,27 +185,38 @@ 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 (string == NULL)
if ((string == NULL) && (length > 0))
{
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)
Expand Down Expand Up @@ -429,7 +440,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;
Expand Down Expand Up @@ -1461,6 +1472,7 @@ static cJSON_bool print_value(const cJSON * const item, printbuffer * const outp
}
}


/* Build an array from input text. */
static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
{
Expand Down Expand Up @@ -2054,7 +2066,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;
Expand Down Expand Up @@ -2394,7 +2406,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;
Expand Down Expand Up @@ -2486,23 +2498,32 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
CJSON_PUBLIC(cJSON *) cJSON_CreateStringWithLength(const char *string, const size_t length)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
if (item)
{
item->type = cJSON_String;
item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
if(!item->valuestring)
item->valuestring = cJSON_strndup(string, length, &global_hooks);
if (!item->valuestring)
{
cJSON_Delete(item);
return NULL;
}
}

return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
{
if (string == NULL)
{
return NULL;
}

return cJSON_CreateStringWithLength(string, strlen(string));
}

CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
{
cJSON *item = cJSON_New_Item(&global_hooks);
Expand Down Expand Up @@ -2536,14 +2557,14 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
CJSON_PUBLIC(cJSON *) cJSON_CreateRawWithLength(const char *raw, const size_t length)
{
cJSON *item = cJSON_New_Item(&global_hooks);
if(item)
if (item)
{
item->type = cJSON_Raw;
item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
if(!item->valuestring)
item->valuestring = cJSON_strndup(raw, length, &global_hooks);
if (!item->valuestring)
{
cJSON_Delete(item);
return NULL;
Expand All @@ -2553,6 +2574,16 @@ CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
return item;
}

CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
{
if (raw == NULL)
{
return NULL;
}

return cJSON_CreateRawWithLength(raw, strlen(raw));
}

CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
{
cJSON *item = cJSON_New_Item(&global_hooks);
Expand Down Expand Up @@ -2761,15 +2792,15 @@ CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, 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;
}
}
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;
Expand Down
2 changes: 2 additions & 0 deletions cJSON.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,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);

Expand Down
32 changes: 31 additions & 1 deletion tests/misc_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,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));
Expand Down Expand Up @@ -555,6 +557,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!";
Expand Down Expand Up @@ -623,7 +651,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);
Expand Down Expand Up @@ -789,6 +817,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);
Expand Down

0 comments on commit 83779b2

Please sign in to comment.