CVE-2019-1010239: NULL Pointer Dereference (CWE-476)
value: DaveGamble/cJSON cJSON 1.7.8 is affected by: Improper Check for Unusual or Exceptional Conditions. The impact is: Null dereference, so attack can cause denial of service. The component is: cJSON_GetObjectItemCaseSensitive() function. The attack vector is: crafted json file. The fixed version is: 1.7.9 and later.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 7.5
Published: 2019-07-19T17:15Z
Repository: https://github.com/DaveGamble/cJSON
Language: C
Files changed: cJSON.c, tests/misc_tests.c
Commit date: 2018-12-16 11:06:40 +0100
Commit message: Fix crash of cJSON_GetObjectItemCaseSensitive when calling it on arrays

Diff: diff --git a/cJSON.c b/cJSON.c
index 1733811..c9c5b61 100644
--- a/cJSON.c
+++ b/cJSON.c
@@ -1779,11 +1779,11 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
     }
 
     current_element = object->child;
     if (case_sensitive)
     {
-        while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
+        while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
         {
             current_element = current_element->next;
         }
     }
     else
@@ -1792,10 +1792,14 @@ static cJSON *get_object_item(const cJSON * const object, const char * const nam
         {
             current_element = current_element->next;
         }
     }
 
+    if ((current_element == NULL) || (current_element->string == NULL)) {
+        return NULL;
+    }
+
     return current_element;
 }
 
 CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
 {
diff --git a/tests/misc_tests.c b/tests/misc_tests.c
index f42772a..1635fa3 100644
--- a/tests/misc_tests.c
+++ b/tests/misc_tests.c
@@ -125,10 +125,32 @@ static void cjson_get_object_item_case_sensitive_should_get_object_items(void)
     TEST_ASSERT_NULL_MESSAGE(found, "Should not find something that isn't there.");
 
     cJSON_Delete(item);
 }
 
+static void cjson_get_object_item_should_not_crash_with_array(void) {
+    cJSON *array = NULL;
+    cJSON *found = NULL;
+    array = cJSON_Parse("[1]");
+
+    found = cJSON_GetObjectItem(array, "name");
+    TEST_ASSERT_NULL(found);
+
+    cJSON_Delete(array);
+}
+
+static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
+    cJSON *array = NULL;
+    cJSON *found = NULL;
+    array = cJSON_Parse("[1]");
+
+    found = cJSON_GetObjectItemCaseSensitive(array, "name");
+    TEST_ASSERT_NULL(found);
+
+    cJSON_Delete(array);
+}
+
 static void typecheck_functions_should_check_type(void)
 {
     cJSON invalid[1];
     cJSON item[1];
     invalid->type = cJSON_Invalid;
@@ -533,10 +555,12 @@ int CJSON_CDECL main(void)
 
     RUN_TEST(cjson_array_foreach_should_loop_over_arrays);
     RUN_TEST(cjson_array_foreach_should_not_dereference_null_pointer);
     RUN_TEST(cjson_get_object_item_should_get_object_items);
     RUN_TEST(cjson_get_object_item_case_sensitive_should_get_object_items);
+    RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
+    RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);
     RUN_TEST(typecheck_functions_should_check_type);
     RUN_TEST(cjson_should_not_parse_to_deeply_nested_jsons);
     RUN_TEST(cjson_set_number_value_should_set_numbers);
     RUN_TEST(cjson_detach_item_via_pointer_should_detach_items);
     RUN_TEST(cjson_replace_item_via_pointer_should_replace_items);

Vulnerable code:         while ((current_element != NULL) && (strcmp(name, current_element->string) != 0))
Fixed code:         while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
    if ((current_element == NULL) || (current_element->string == NULL)) {
        return NULL;
    }

static void cjson_get_object_item_should_not_crash_with_array(void) {
    cJSON *array = NULL;
    cJSON *found = NULL;
    array = cJSON_Parse("[1]");

    found = cJSON_GetObjectItem(array, "name");
    TEST_ASSERT_NULL(found);

    cJSON_Delete(array);
}

static void cjson_get_object_item_case_sensitive_should_not_crash_with_array(void) {
    cJSON *array = NULL;
    cJSON *found = NULL;
    array = cJSON_Parse("[1]");

    found = cJSON_GetObjectItemCaseSensitive(array, "name");
    TEST_ASSERT_NULL(found);

    cJSON_Delete(array);
}

    RUN_TEST(cjson_get_object_item_should_not_crash_with_array);
    RUN_TEST(cjson_get_object_item_case_sensitive_should_not_crash_with_array);