diff --git a/cJSON_Utils.c b/cJSON_Utils.c index 8b38eb253..6403eb200 100644 --- a/cJSON_Utils.c +++ b/cJSON_Utils.c @@ -276,6 +276,12 @@ static cJSON_bool decode_array_index_from_pointer(const unsigned char * const po size_t parsed_index = 0; size_t position = 0; + if ((pointer[0] == '\0') || (pointer[0] == '/')) + { + /* an empty reference token is not a valid array index */ + return 0; + } + if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/'))) { /* leading zeroes are not permitted */ diff --git a/tests/json-patch-tests/cjson-utils-tests.json b/tests/json-patch-tests/cjson-utils-tests.json index 28a5e3073..279f30529 100644 --- a/tests/json-patch-tests/cjson-utils-tests.json +++ b/tests/json-patch-tests/cjson-utils-tests.json @@ -87,5 +87,17 @@ "doc": {"foo": {"bar": 1}}, "patch": [{"op": "add", "path": "/foo/bar/baz", "value": "5"}], "error": "attempting to add to subfield of non-object" - } + }, + { + "comment": "16, an empty reference token is not a valid array index", + "doc": [ "first", "second", "third" ], + "patch": [{ "op": "remove", "path": "/" }], + "error": "an empty reference token is not a valid array index" + }, + { + "comment": "17, an empty reference token is not a valid array index", + "doc": [ "first", "second", "third" ], + "patch": [{ "op": "replace", "path": "/", "value": "x" }], + "error": "an empty reference token is not a valid array index" + } ] diff --git a/tests/old_utils_tests.c b/tests/old_utils_tests.c index 690dbb583..c19236e67 100644 --- a/tests/old_utils_tests.c +++ b/tests/old_utils_tests.c @@ -85,6 +85,28 @@ static void json_pointer_tests(void) cJSON_Delete(root); } +static void json_pointer_should_reject_empty_array_index(void) +{ + /* An empty reference token is not a valid array index (RFC 6901), so it + * must not be silently accepted as index 0. */ + cJSON *array = cJSON_Parse("[\"first\", \"second\", \"third\"]"); + cJSON *nested = cJSON_Parse("[[1, 2], [3, 4]]"); + + TEST_ASSERT_NOT_NULL(array); + TEST_ASSERT_NOT_NULL(nested); + + /* valid array indices still resolve */ + TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(array, "/0"), cJSON_GetArrayItem(array, 0)); + TEST_ASSERT_EQUAL_PTR(cJSONUtils_GetPointer(nested, "/0/1"), cJSON_GetArrayItem(cJSON_GetArrayItem(nested, 0), 1)); + + /* an empty array reference token must be rejected, not resolved to index 0 */ + TEST_ASSERT_NULL(cJSONUtils_GetPointer(array, "/")); + TEST_ASSERT_NULL(cJSONUtils_GetPointer(nested, "/0/")); + + cJSON_Delete(array); + cJSON_Delete(nested); +} + static void misc_tests(void) { /* Misc tests */ @@ -216,6 +238,7 @@ int main(void) UNITY_BEGIN(); RUN_TEST(json_pointer_tests); + RUN_TEST(json_pointer_should_reject_empty_array_index); RUN_TEST(misc_tests); RUN_TEST(sort_tests); RUN_TEST(merge_tests);