diff --git a/json_patch.c b/json_patch.c index 0930816..d909d87 100644 --- a/json_patch.c +++ b/json_patch.c @@ -233,19 +233,12 @@ static int json_object_array_move_cb(struct json_object *parent, const char *key struct json_object *value, void *priv) { int rc; - struct json_pointer_get_result *from = priv; - size_t len = json_object_array_length(parent); /** - * If it's the same array parent, it means that we removed - * and element from it, so the length is temporarily reduced - * by 1, which means that if we try to move an element to - * the last position, we need to check the current length + 1 + * When moving within the same array, the element has already been + * removed, and idx refers to the shorter array (RFC 6902 section 4.4) */ - if (parent == from->parent) - len++; - - if (idx > len) + if (idx > json_object_array_length(parent)) { // Note: will propagate back out through json_pointer_set_with_cb() errno = EINVAL; diff --git a/tests/json_patch_tests.json b/tests/json_patch_tests.json index 5b9a41d..5a7f403 100644 --- a/tests/json_patch_tests.json +++ b/tests/json_patch_tests.json @@ -136,6 +136,16 @@ "doc": ["foo", "sil"], "patch": [{"op":"add", "path": "/3", "value": "bar"}], "error": "index is greater than number of items in array" }, + + { "comment": "Move within an array to the old array length is out of bounds", + "doc": {"foo": [1, 2, 3]}, + "patch": [{"op": "move", "from": "/foo/0", "path": "/foo/3"}], + "error": "/foo/3 is past the end of the array once /foo/0 is removed" }, + + { "comment": "Move within an array to its last index", + "doc": {"foo": [1, 2, 3]}, + "patch": [{"op": "move", "from": "/foo/0", "path": "/foo/2"}], + "expected": {"foo": [2, 3, 1]} }, { "comment": "test integer against equal double", "doc": {"n": 1}, diff --git a/tests/test_json_patch.expected b/tests/test_json_patch.expected index c4fe5f4..7191257 100644 --- a/tests/test_json_patch.expected +++ b/tests/test_json_patch.expected @@ -54,6 +54,9 @@ Testing '(null)', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/0", Testing 'push item to array via last index + 1', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/2", "value": "bar" } ]' : OK Testing 'add item to array at index > length should fail', doc '[ "foo", "sil" ]' patch '[ { "op": "add", "path": "\/3", "value": "bar" } ]' : OK => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field +Testing 'Move within an array to the old array length is out of bounds', doc '{ "foo": [ 1, 2, 3 ] }' patch '[ { "op": "move", "from": "\/foo\/0", "path": "\/foo\/3" } ]' : OK + => json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Failed to set value at path referenced by 'path' field +Testing 'Move within an array to its last index', doc '{ "foo": [ 1, 2, 3 ] }' patch '[ { "op": "move", "from": "\/foo\/0", "path": "\/foo\/2" } ]' : OK Testing 'test integer against equal double', doc '{ "n": 1 }' patch '[ { "op": "test", "path": "\/n", "value": 1.0 } ]' : OK Testing 'test double against equal integer', doc '{ "n": 1.0 }' patch '[ { "op": "test", "path": "\/n", "value": 1 } ]' : OK Testing 'test numeric equality inside arrays and objects', doc '{ "a": [ 1, { "n": -2.0 } ], "b": null }' patch '[ { "op": "test", "path": "", "value": { "b": null, "a": [ 1.0, { "n": -2 } ] } } ]' : OK