mirror of
https://github.com/nlohmann/json.git
synced 2026-10-03 13:10:33 +00:00
Assert that write_bson_document() consumes every calc_bson_sizes() entry
calc_bson_sizes() and write_bson_document() are a hand-synchronized pair of passes over the same object/array tree, introduced by #5553: the size pass appends to nested_sizes in visiting order, and the write pass consumes the table by position with nested_sizes[next_size++]. Nothing checked that the write pass consumed the whole table. If a future change touched only one of the two passes - for example to skip or reject an entry - every later size prefix in the document would be silently wrong. Add JSON_ASSERT(next_size == nested_sizes.size()) where write_bson_document() returns, so such a future drift between the two passes is caught immediately (JSON_ASSERT expands to nothing in release builds using assert(), and the fuzzers/tests already build with it enabled). The two passes agree today, so this changes nothing observable; it only guards against the risk described in #5710 item 5. Extracting a shared stepper for the two passes (the second half of the proposed change) is left for a follow-up: it only saves ~30 lines and the issue asks for it only if the result reads clearly, which needs more room to get right than a mechanical cleanup pass allows. #5710 item 5 Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -1358,6 +1358,14 @@ class binary_writer
|
||||
oa.write_character(to_char_type(0x00));
|
||||
if (parents.empty())
|
||||
{
|
||||
// calc_bson_sizes() and write_bson_document() are two
|
||||
// hand-synchronized passes over the same structure, linked
|
||||
// only by nested_sizes' visiting order; this checks that the
|
||||
// write pass consumed exactly the sizes the size pass
|
||||
// produced, so a future change that desyncs them (skips or
|
||||
// rejects an entry in only one pass) is caught immediately
|
||||
// instead of silently writing wrong length prefixes.
|
||||
JSON_ASSERT(next_size == nested_sizes.size());
|
||||
return;
|
||||
}
|
||||
current = std::move(parents.back());
|
||||
|
||||
@@ -21651,6 +21651,14 @@ class binary_writer
|
||||
oa.write_character(to_char_type(0x00));
|
||||
if (parents.empty())
|
||||
{
|
||||
// calc_bson_sizes() and write_bson_document() are two
|
||||
// hand-synchronized passes over the same structure, linked
|
||||
// only by nested_sizes' visiting order; this checks that the
|
||||
// write pass consumed exactly the sizes the size pass
|
||||
// produced, so a future change that desyncs them (skips or
|
||||
// rejects an entry in only one pass) is caught immediately
|
||||
// instead of silently writing wrong length prefixes.
|
||||
JSON_ASSERT(next_size == nested_sizes.size());
|
||||
return;
|
||||
}
|
||||
current = std::move(parents.back());
|
||||
|
||||
Reference in New Issue
Block a user