Empty array reference token is accepted as index 0 in JSON Pointer evaluation
Summary
decode_array_index_from_pointer() appears to accept an empty reference token as a valid array index and decodes it as 0.
This seems inconsistent with RFC 6901 JSON Pointer array evaluation. When the currently referenced value is an array, the reference token should be either:
- a valid unsigned base-10 array index without leading zeroes, or
- exactly
"-" for the special position after the last array element.
An empty string is not a valid array index, but cJSON currently treats it as index 0.
Relevant code
In cJSON_Utils.c:
static cJSON_bool decode_array_index_from_pointer(const unsigned char * const pointer, size_t * const index)
{
size_t parsed_index = 0;
size_t position = 0;
if ((pointer[0] == '0') && ((pointer[1] != '\0') && (pointer[1] != '/')))
{
/* leading zeroes are not permitted */
return 0;
}
for (position = 0; (pointer[position] >= '0') && (pointer[position] <= '9'); position++)
{
parsed_index = (10 * parsed_index) + (size_t)(pointer[position] - '0');
}
if ((pointer[position] != '\0') && (pointer[position] != '/'))
{
return 0;
}
*index = parsed_index;
return 1;
}
Observable impact
Because get_item_from_pointer() calls decode_array_index_from_pointer() when the current value is an array, invalid pointers can resolve to the first array element.
Examples:
cJSONUtils_GetPointer(array, "/") returns array[0], but it should fail.
- JSON Patch
remove with path "/" on an array removes the first element, although the path is invalid for an array.
- JSON Patch
replace with path "/" on an array replaces the first element.
- JSON Patch
copy or move with from: "/" on an array reads or detaches the first element.
- Nested paths such as
"/0/" can incorrectly resolve an empty token inside a nested array as index 0.
For JSON Patch, RFC 6902 requires operation paths and from locations to be JSON Pointer values. If the target location is invalid or does not exist, the operation should fail instead of silently acting on index 0.
References:
Expected behavior
decode_array_index_from_pointer() should reject an empty token when resolving an array index.
For example:
if (pointer[0] == '\0' || pointer[0] == '/')
{
return 0;
}
Actual behavior
The empty token is accepted and interpreted as index 0, so invalid JSON Pointers targeting arrays can resolve to, modify, remove, copy, or move the first array element.
Empty array reference token is accepted as index 0 in JSON Pointer evaluation
Summary
decode_array_index_from_pointer()appears to accept an empty reference token as a valid array index and decodes it as0.This seems inconsistent with RFC 6901 JSON Pointer array evaluation. When the currently referenced value is an array, the reference token should be either:
"-"for the special position after the last array element.An empty string is not a valid array index, but cJSON currently treats it as index
0.Relevant code
In
cJSON_Utils.c:Observable impact
Because
get_item_from_pointer()callsdecode_array_index_from_pointer()when the current value is an array, invalid pointers can resolve to the first array element.Examples:
cJSONUtils_GetPointer(array, "/")returnsarray[0], but it should fail.removewith path"/"on an array removes the first element, although the path is invalid for an array.replacewith path"/"on an array replaces the first element.copyormovewithfrom: "/"on an array reads or detaches the first element."/0/"can incorrectly resolve an empty token inside a nested array as index0.For JSON Patch, RFC 6902 requires operation paths and
fromlocations to be JSON Pointer values. If the target location is invalid or does not exist, the operation should fail instead of silently acting on index0.References:
Expected behavior
decode_array_index_from_pointer()should reject an empty token when resolving an array index.For example:
Actual behavior
The empty token is accepted and interpreted as index
0, so invalid JSON Pointers targeting arrays can resolve to, modify, remove, copy, or move the first array element.