json_pointer: move array out-of-bounds check outside of is_valid_index()
The out-of-bounds check is useful when trying to index/obtain a value from
an array.
However, when we set a value to a specific JSON pointer, we can allow
values that are outside the length of the current array.
The RFC6901 doc isn't clear on that aspect, and doing so is a bit more
in-line with how json_object_array_{put,insert}_idx() functions behave.
This changes the behavior of json_pointer_set{f}() because now a value can
be set anywhere in the array.
Also, added a test-case for this behavior change.
Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com>
This commit is contained in:
committed by
Eric Hawicz
parent
5a46a3b76d
commit
1c38dea651
@@ -42,7 +42,7 @@ static void string_replace_all_occurrences_with_char(char *s, const char *occur,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_valid_index(struct json_object *jo, const char *path, size_t *idx)
|
static int is_valid_index(const char *path, size_t *idx)
|
||||||
{
|
{
|
||||||
size_t i, len = strlen(path);
|
size_t i, len = strlen(path);
|
||||||
/* this code-path optimizes a bit, for when we reference the 0-9 index range
|
/* this code-path optimizes a bit, for when we reference the 0-9 index range
|
||||||
@@ -53,7 +53,7 @@ static int is_valid_index(struct json_object *jo, const char *path, size_t *idx)
|
|||||||
if (is_plain_digit(path[0]))
|
if (is_plain_digit(path[0]))
|
||||||
{
|
{
|
||||||
*idx = (path[0] - '0');
|
*idx = (path[0] - '0');
|
||||||
goto check_oob;
|
return 1;
|
||||||
}
|
}
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -77,13 +77,6 @@ static int is_valid_index(struct json_object *jo, const char *path, size_t *idx)
|
|||||||
// We know it's all digits, so the only error case here is overflow,
|
// We know it's all digits, so the only error case here is overflow,
|
||||||
// but ULLONG_MAX will be longer than any array length so that's ok.
|
// but ULLONG_MAX will be longer than any array length so that's ok.
|
||||||
*idx = strtoull(path, NULL, 10);
|
*idx = strtoull(path, NULL, 10);
|
||||||
check_oob:
|
|
||||||
len = json_object_array_length(jo);
|
|
||||||
if (*idx >= len)
|
|
||||||
{
|
|
||||||
errno = ENOENT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -93,8 +86,14 @@ static int json_pointer_get_single_path(struct json_object *obj, char *path,
|
|||||||
{
|
{
|
||||||
if (json_object_is_type(obj, json_type_array))
|
if (json_object_is_type(obj, json_type_array))
|
||||||
{
|
{
|
||||||
if (!is_valid_index(obj, path, idx))
|
if (!is_valid_index(path, idx))
|
||||||
return -1;
|
return -1;
|
||||||
|
if (*idx >= json_object_array_length(obj))
|
||||||
|
{
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
obj = json_object_array_get_idx(obj, *idx);
|
obj = json_object_array_get_idx(obj, *idx);
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
@@ -129,7 +128,7 @@ static int json_pointer_set_single_path(struct json_object *parent, const char *
|
|||||||
/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
|
/* RFC (Chapter 4) states that '-' may be used to add new elements to an array */
|
||||||
if (path[0] == '-' && path[1] == '\0')
|
if (path[0] == '-' && path[1] == '\0')
|
||||||
return json_object_array_add(parent, value);
|
return json_object_array_add(parent, value);
|
||||||
if (!is_valid_index(parent, path, &idx))
|
if (!is_valid_index(path, &idx))
|
||||||
return -1;
|
return -1;
|
||||||
return json_object_array_put_idx(parent, idx, value);
|
return json_object_array_put_idx(parent, idx, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -269,6 +269,22 @@ static void test_example_set(void)
|
|||||||
printf("%s\n", json_object_get_string(jo1));
|
printf("%s\n", json_object_get_string(jo1));
|
||||||
|
|
||||||
json_object_put(jo1);
|
json_object_put(jo1);
|
||||||
|
|
||||||
|
jo1 = json_tokener_parse("[0, 1, 2, 3]");
|
||||||
|
jo2 = json_tokener_parse("[0, 1, 2, 3, null, null, null, 7]");
|
||||||
|
|
||||||
|
assert(0 == json_pointer_set(&jo1, "/7", json_object_new_int(7)));
|
||||||
|
assert(1 == json_object_equal(jo1, jo2));
|
||||||
|
|
||||||
|
json_object_put(jo1);
|
||||||
|
|
||||||
|
jo1 = json_tokener_parse("[0, 1, 2, 3]");
|
||||||
|
|
||||||
|
assert(0 == json_pointer_setf(&jo1, json_object_new_int(7), "/%u", 7));
|
||||||
|
assert(1 == json_object_equal(jo1, jo2));
|
||||||
|
|
||||||
|
json_object_put(jo1);
|
||||||
|
json_object_put(jo2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_wrong_inputs_set(void)
|
static void test_wrong_inputs_set(void)
|
||||||
|
|||||||
Reference in New Issue
Block a user