CVE-2019-1010239: Improper Check for Unusual or Exceptional Conditions (CWE-754)
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 does not check or incorrectly checks for unusual or exceptional conditions that are not expected to occur frequently during day to day operation of the product.
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);