mirror of
https://github.com/nlohmann/json.git
synced 2026-10-27 08:18:55 +00:00
Fix self-aliasing in json_pointer::operator/= and patch_inplace
json_pointer::operator/=(const json_pointer&) passed iterators into its own token vector to insert() when a pointer was appended to itself (p /= p), which is undefined behavior; libstdc++ produced "/a/b//" for "/a/b". The pointer now appends a copy in that case. basic_json::patch_inplace iterated the patch while changing *this, so j.patch_inplace(j) read freed memory. It now applies a copy of the patch when the patch is the value itself. A patch stored inside the value remains undefined behavior and is documented as such; copying the patch unconditionally would double the time of a large patch. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
7 files changed
+188
-2
No files matched your search
@@ -62,6 +62,16 @@ Unlike [`patch`](patch.md), `patch_inplace` applies the operation "in place" and
|
||||
That makes it faster for large documents by avoiding the copy. However, the JSON value might be corrupted if the
|
||||
function throws an exception.
|
||||
|
||||
The JSON patch may be the JSON value itself (`#!cpp j.patch_inplace(j)`): the operations are then read from a copy of
|
||||
the patch made before the first operation is applied, so the result is the same as that of
|
||||
`#!cpp j = j.patch(j)`, and the exception safety is the same as above.
|
||||
|
||||
!!! danger "Undefined behavior"
|
||||
|
||||
The JSON patch must not be a value stored inside the JSON value (e.g., `#!cpp j.patch_inplace(j["patch"])`), as the
|
||||
operations may change or destroy it while it is read. Pass a copy (`#!cpp j.patch_inplace(json(j["patch"]))`) or use
|
||||
[`patch`](patch.md) instead.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example "Example: apply a JSON patch in place"
|
||||
@@ -113,3 +123,4 @@ function throws an exception.
|
||||
- Throws [`parse_error.109`](../../home/exceptions.md#jsonexceptionparse_error109) instead of
|
||||
[`out_of_range.404`](../../home/exceptions.md#jsonexceptionout_of_range404) for a one-character array index that is
|
||||
not a digit (e.g., `/x`) in version 3.13.0, as it already did for longer ones.
|
||||
- Applying a JSON value as patch to itself no longer results in undefined behavior in version 3.13.0.
|
||||
@@ -18,7 +18,8 @@ json_pointer& operator/=(std::size_t array_idx)
|
||||
## Parameters
|
||||
|
||||
`ptr` (in)
|
||||
: JSON pointer to append
|
||||
: JSON pointer to append; may be the JSON pointer itself (`#!cpp p /= p`), which then appends a copy of its
|
||||
reference tokens
|
||||
|
||||
`token` (in)
|
||||
: reference token to append
|
||||
@@ -68,6 +69,7 @@ json_pointer& operator/=(std::size_t array_idx)
|
||||
|
||||
## Version history
|
||||
|
||||
1. Added in version 3.6.0.
|
||||
1. Added in version 3.6.0. Appending a JSON pointer to itself no longer results in undefined behavior in version
|
||||
3.13.0.
|
||||
2. Added in version 3.6.0. Changed type of `token` to `string_t` in version 3.11.0.
|
||||
3. Added in version 3.6.0.
|
||||
Reference in new issue
Block a user