Give operator>> a strong exception-safety guarantee

operator>> parsed directly into its basic_json& target, so a parse
error left the target holding whatever was parsed before the error
instead of its previous value. With JSON_DIAGNOSTICS=1, that partial
value also violated the class invariant, because the parent pointers
of an array or object's elements are only set when the container is
closed, which a failed parse never reaches; copying such a value then
aborted in assert_invariant().

Fix it the way basic_json::parse() already handles this: parse into a
temporary and move it into the target only once parsing succeeds, so
the target is left unchanged if an exception is thrown.

Fixes #5652.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-29 23:39:07 +02:00
parent 633de8e44b
commit 357a72e6e2
4 changed files with 31 additions and 2 deletions
+4 -1
View File
@@ -5050,7 +5050,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
friend std::istream& operator>>(std::istream& i, basic_json& j)
{
parser(detail::input_adapter(i)).parse(false, j);
// parse into a temporary so that j is left unchanged if parsing fails
basic_json result;
parser(detail::input_adapter(i)).parse(false, result);
j = std::move(result);
return i;
}
#endif // JSON_NO_IO