Explorar o código

cJSON_Compare: Fix comparison of objects

It did consider two arrays equal if one is a subset of te other one,
which is incorrect.

See #180
Max Bruckner %!s(int64=8) %!d(string=hai) anos
pai
achega
03ba72faec
Modificáronse 2 ficheiros con 27 adicións e 1 borrados
  1. 18 1
      cJSON.c
  2. 9 0
      tests/compare_tests.c

+ 18 - 1
cJSON.c

@@ -2605,10 +2605,11 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
         case cJSON_Object:
         {
             cJSON *a_element = NULL;
+            cJSON *b_element = NULL;
             cJSON_ArrayForEach(a_element, a)
             {
                 /* TODO This has O(n^2) runtime, which is horrible! */
-                cJSON *b_element = get_object_item(b, a_element->string, case_sensitive);
+                b_element = get_object_item(b, a_element->string, case_sensitive);
                 if (b_element == NULL)
                 {
                     return false;
@@ -2620,6 +2621,22 @@ CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * cons
                 }
             }
 
+            /* doing this twice, once on a and b to prevent true comparison if a subset of b
+             * TODO: Do this the proper way, this is just a fix for now */
+            cJSON_ArrayForEach(b_element, b)
+            {
+                a_element = get_object_item(a, b_element->string, case_sensitive);
+                if (a_element == NULL)
+                {
+                    return false;
+                }
+
+                if (!cJSON_Compare(b_element, a_element, case_sensitive))
+                {
+                    return false;
+                }
+            }
+
             return true;
         }
 

+ 9 - 0
tests/compare_tests.c

@@ -175,6 +175,15 @@ static void cjson_compare_should_compare_objects(void)
                 "{\"Flse\": false, \"true\": true, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
                 "{\"true\": true, \"false\": false, \"null\": null, \"number\": 42, \"string\": \"string\", \"array\": [], \"object\": {}}",
                 false));
+    /* test objects that are a subset of each other */
+    TEST_ASSERT_FALSE(compare_from_string(
+                "{\"one\": 1, \"two\": 2}",
+                "{\"one\": 1, \"two\": 2, \"three\": 3}",
+                true))
+    TEST_ASSERT_FALSE(compare_from_string(
+                "{\"one\": 1, \"two\": 2}",
+                "{\"one\": 1, \"two\": 2, \"three\": 3}",
+                false))
 }
 
 int main(void)