Make the UBJSON/BJData advance loop's top a copy, not a reference

Same issue as the CBOR reader: top aliased container_stack.back() and
was read (top.is_object) right after container_stack.pop_back() ended
its lifetime. A copy stays valid regardless of what happens to the
stack; the one place that mutates the live entry (--top.remaining) now
goes through container_stack.back() directly.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-10 18:43:41 +02:00
parent 0e99cf2482
commit d46c80b983
2 changed files with 12 additions and 12 deletions
@@ -2205,17 +2205,18 @@ class binary_reader
} }
// advance to the next element, closing the containers that ended. // advance to the next element, closing the containers that ended.
// The reference is not held across get_ubjson_value() above, which // top is a copy, not a reference: it must stay valid across the
// can push onto the stack and reallocate it. // pop_back() below, which destroys the container_stack element it
// would otherwise alias.
for (;;) for (;;)
{ {
container_frame& top = container_stack.back(); container_frame top = container_stack.back();
if (top.remaining != npos) if (top.remaining != npos)
{ {
if (top.remaining != 0) if (top.remaining != 0)
{ {
--top.remaining; --container_stack.back().remaining;
if (top.is_object) if (top.is_object)
{ {
key.clear(); key.clear();
@@ -2254,9 +2255,8 @@ class binary_reader
break; break;
} }
const bool is_object = top.is_object;
container_stack.pop_back(); container_stack.pop_back();
if (JSON_HEDLEY_UNLIKELY(is_object ? !sax->end_object() : !sax->end_array())) if (JSON_HEDLEY_UNLIKELY(top.is_object ? !sax->end_object() : !sax->end_array()))
{ {
return false; return false;
} }
+6 -6
View File
@@ -13029,17 +13029,18 @@ class binary_reader
} }
// advance to the next element, closing the containers that ended. // advance to the next element, closing the containers that ended.
// The reference is not held across get_ubjson_value() above, which // top is a copy, not a reference: it must stay valid across the
// can push onto the stack and reallocate it. // pop_back() below, which destroys the container_stack element it
// would otherwise alias.
for (;;) for (;;)
{ {
container_frame& top = container_stack.back(); container_frame top = container_stack.back();
if (top.remaining != npos) if (top.remaining != npos)
{ {
if (top.remaining != 0) if (top.remaining != 0)
{ {
--top.remaining; --container_stack.back().remaining;
if (top.is_object) if (top.is_object)
{ {
key.clear(); key.clear();
@@ -13078,9 +13079,8 @@ class binary_reader
break; break;
} }
const bool is_object = top.is_object;
container_stack.pop_back(); container_stack.pop_back();
if (JSON_HEDLEY_UNLIKELY(is_object ? !sax->end_object() : !sax->end_array())) if (JSON_HEDLEY_UNLIKELY(top.is_object ? !sax->end_object() : !sax->end_array()))
{ {
return false; return false;
} }