Origin: backport, https://github.com/DaveGamble/cJSON/commit/60ff122ef5862d04b39b150541459e7f5e35add8
From: Peter Alfred Lee <peterlee@apache.com>
Bug: https://github.com/DaveGamble/cJSON/issues/803
Bug: https://github.com/DaveGamble/cJSON/issues/802
Bug-Debian: https://bugs.debian.org/1059287
Acked-by: Maytham Alsudany <maytha8thedev@gmail.com>
Subject: [PATCH] add NULL checkings (#809)
 * add NULL checks in cJSON_SetValuestring
 Fixes #803(CVE-2023-50472)
 .
 * add NULL check in cJSON_InsertItemInArray
 Fixes #802(CVE-2023-50471)
 .
 * add tests for NULL checks
 add tests for NULL checks in cJSON_InsertItemInArray and cJSON_SetValuestring

--- a/cJSON.c
+++ b/cJSON.c
@@ -401,7 +401,12 @@
 {
     char *copy = NULL;
     /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
-    if (!(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+    if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+    {
+        return NULL;
+    }
+    /* return NULL if the object is corrupted */
+    if (object->valuestring == NULL)
     {
         return NULL;
     }
@@ -2260,7 +2265,7 @@
 {
     cJSON *after_inserted = NULL;
 
-    if (which < 0)
+    if (which < 0 || newitem == NULL)
     {
         return false;
     }
@@ -2271,6 +2276,11 @@
         return add_item_to_array(array, newitem);
     }
 
+    if (after_inserted != array->child && newitem->prev == NULL) {
+        /* return false if after_inserted is a corrupted array item */
+        return false;
+    }
+
     newitem->next = after_inserted;
     newitem->prev = after_inserted->prev;
     after_inserted->prev = newitem;
--- a/tests/misc_tests.c
+++ b/tests/misc_tests.c
@@ -353,6 +353,19 @@
 {
     char buffer[10];
     cJSON *item = cJSON_CreateString("item");
+    cJSON *array = cJSON_CreateArray();
+    cJSON *item1 = cJSON_CreateString("item1");
+    cJSON *item2 = cJSON_CreateString("corrupted array item3");
+    cJSON *corruptedString = cJSON_CreateString("corrupted");
+    struct cJSON *originalPrev;
+
+    add_item_to_array(array, item1);
+    add_item_to_array(array, item2);
+
+    originalPrev = item2->prev;
+    item2->prev = NULL;
+    free(corruptedString->valuestring);
+    corruptedString->valuestring = NULL;
 
     cJSON_InitHooks(NULL);
     TEST_ASSERT_NULL(cJSON_Parse(NULL));
@@ -412,6 +425,8 @@
     cJSON_DeleteItemFromObject(item, NULL);
     cJSON_DeleteItemFromObjectCaseSensitive(NULL, "item");
     cJSON_DeleteItemFromObjectCaseSensitive(item, NULL);
+    TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 0, NULL));
+    TEST_ASSERT_FALSE(cJSON_InsertItemInArray(array, 1, item));
     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(NULL, 0, item));
     TEST_ASSERT_FALSE(cJSON_InsertItemInArray(item, 0, NULL));
     TEST_ASSERT_FALSE(cJSON_ReplaceItemViaPointer(NULL, item, item));
@@ -428,10 +443,16 @@
     TEST_ASSERT_NULL(cJSON_Duplicate(NULL, true));
     TEST_ASSERT_FALSE(cJSON_Compare(item, NULL, false));
     TEST_ASSERT_FALSE(cJSON_Compare(NULL, item, false));
+    TEST_ASSERT_NULL(cJSON_SetValuestring(NULL, "test"));
+    TEST_ASSERT_NULL(cJSON_SetValuestring(corruptedString, "test"));
     cJSON_Minify(NULL);
     /* skipped because it is only used via a macro that checks for NULL */
     /* cJSON_SetNumberHelper(NULL, 0); */
 
+    /* restore corrupted item2 to delete it */
+    item2->prev = originalPrev;
+    cJSON_Delete(corruptedString);
+    cJSON_Delete(array);
     cJSON_Delete(item);
 }
 
