json_patch: reject a move past the end of the same array

json_object_array_move_cb() added one to the array length when "from"
and "path" are in the same array, so that the old length counted as a
valid target index. A move is a remove followed by an add (RFC 6902
section 4.4), and the add's index must not be greater than the number
of elements left after the remove. With the extra slot,
json_object_array_insert_idx() was called one past the end and padded
the array with a null:

    doc:   {"foo": [1, 2, 3]}
    patch: [{"op": "move", "from": "/foo/0", "path": "/foo/3"}]

returned 0 with {"foo": [2, 3, null, 1]}. It now fails with EINVAL,
like an add to /foo/3 on a two-element array. Moving to /foo/2 or
/foo/- still puts the element last.
This commit is contained in:
Wleeaf authored and Eric Hawicz committed 2026-11-09 08:22:21 -05:00
1 parent 46f0355925
commit 0389cc85ce
3 files changed
+16 -10

No files matched your search

+3
View File
@@ -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