mirror of
https://github.com/json-c/json-c.git
synced 2026-11-09 23:40:14 +08:00
json_patch: treat an empty "from" as a parent of any "path"
Since the token-boundary check for the parent/child test (1b504e2), an
empty "from" (the root) only counts as a prefix of "path" when "path"
starts with '/'. With an invalid "path" like "a", a move from "" went
on to remove the root: __json_patch_apply_remove() dropped a reference
to the document, the following set failed on the bad path, and the
error path dropped the last reference, so *base was freed while the
caller still owned it (use-after-free / double free in
json_object_put()).
The root is a parent of every other location, so an empty "from" now
always takes the parent/child branch: a no-op for "path": "" and
EINVAL otherwise. This also restores the invariant the comment below
relies on, that json_pointer can't find the root here.
Added move and copy cases to json_patch_tests.json and regenerated
test_json_patch.expected.
This commit is contained in:
1 parent
ea3756e561
commit
cdd8db0530
3 files changed
+15
-1
No files matched your search
@@ -480,6 +480,16 @@
|
||||
"patch": [{"op": "copy", "from": "/aa", "path": "/aab"}],
|
||||
"expected": {"aa": 1, "aab": 1} },
|
||||
|
||||
{ "comment": "Moving the root to a path without a leading '/' must fail, not free the document",
|
||||
"doc": {"a": null},
|
||||
"patch": [{"op": "move", "from": "", "path": "a"}],
|
||||
"error": "the root is a parent of every other location" },
|
||||
|
||||
{ "comment": "Copying the root to a path without a leading '/' must fail",
|
||||
"doc": {"a": null},
|
||||
"patch": [{"op": "copy", "from": "", "path": "a"}],
|
||||
"error": "the root is a parent of every other location" },
|
||||
|
||||
{ "comment": "Remove members whose names need escaping",
|
||||
"doc": {"a/b": 1, "m~n": 2, "c": 3},
|
||||
"patch": [{"op": "remove", "path": "/a~1b"},
|
||||
|
||||
@@ -131,6 +131,10 @@ Testing '(null)', doc '{ "foo": [ "bar", "baz" ], "": 0, "a\/b": 1, "c%d": 2, "e
|
||||
Testing 'Move to same location has no effect', doc '{ "foo": 1 }' patch '[ { "op": "move", "from": "\/foo", "path": "\/foo" } ]' : OK
|
||||
Testing 'Move between sibling keys sharing a name prefix is not a parent/child move', doc '{ "aa": 1, "aab": 2 }' patch '[ { "op": "move", "from": "\/aa", "path": "\/aab" } ]' : OK
|
||||
Testing 'Copy between sibling keys sharing a name prefix is not a parent/child move', doc '{ "aa": 1, "aab": 2 }' patch '[ { "op": "copy", "from": "\/aa", "path": "\/aab" } ]' : OK
|
||||
Testing 'Moving the root to a path without a leading '/' must fail, not free the document', doc '{ "a": null }' patch '[ { "op": "move", "from": "", "path": "a" } ]' : OK
|
||||
=> json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid attempt to move parent under a child
|
||||
Testing 'Copying the root to a path without a leading '/' must fail', doc '{ "a": null }' patch '[ { "op": "copy", "from": "", "path": "a" } ]' : OK
|
||||
=> json_patch_apply failed as expected: ERRNO=EINVAL at patch idx 0: Invalid attempt to move parent under a child
|
||||
Testing 'Remove members whose names need escaping', doc '{ "a\/b": 1, "m~n": 2, "c": 3 }' patch '[ { "op": "remove", "path": "\/a~1b" }, { "op": "remove", "path": "\/m~0n" } ]' : OK
|
||||
Testing 'Move from a member whose name needs escaping', doc '{ "a\/b": 1 }' patch '[ { "op": "move", "from": "\/a~1b", "path": "\/c" } ]' : OK
|
||||
Testing '(null)', doc '{ "foo": 1, "baz": [ { "qux": "hello" } ] }' patch '[ { "op": "move", "from": "\/foo", "path": "\/bar" } ]' : OK
|
||||
|
||||
Reference in new issue
Block a user