Make parse_cbor_internal's top a copy so it survives pop_back()

top aliased container_stack.back(), and was still read (top.is_object)
right after container_stack.pop_back() destroyed the element it aliased.
Nothing currently reorders those two lines, but the comment claiming the
reference's lifetime was already fine only accounted for reallocation
from a push, not this. A trivially-copyable container_frame makes top a
copy instead, so reads of it stay valid regardless of what happens to the
stack; the one place that mutates the live entry now does so through
container_stack.back() directly rather than through top.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-10 18:40:07 +02:00
parent 4297d2aeaf
commit d05ac29f9b
2 changed files with 12 additions and 12 deletions
@@ -1424,9 +1424,10 @@ class binary_reader
{
if (!container_stack.empty())
{
// the reference is not held across parse_cbor_value() below,
// which can push onto the stack and reallocate it
container_frame& top = container_stack.back();
// a copy, not a reference: it must stay valid across the
// pop_back() below, which destroys the container_stack element
// it would otherwise alias
container_frame top = container_stack.back();
bool at_end = false;
if (top.remaining != npos)
@@ -1437,7 +1438,7 @@ class binary_reader
if (!at_end)
{
// claim the element about to be read
--top.remaining;
--container_stack.back().remaining;
if (top.is_object)
{
get();
@@ -1456,9 +1457,8 @@ class binary_reader
if (at_end)
{
const bool is_object = top.is_object;
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;
}
+6 -6
View File
@@ -12248,9 +12248,10 @@ class binary_reader
{
if (!container_stack.empty())
{
// the reference is not held across parse_cbor_value() below,
// which can push onto the stack and reallocate it
container_frame& top = container_stack.back();
// a copy, not a reference: it must stay valid across the
// pop_back() below, which destroys the container_stack element
// it would otherwise alias
container_frame top = container_stack.back();
bool at_end = false;
if (top.remaining != npos)
@@ -12261,7 +12262,7 @@ class binary_reader
if (!at_end)
{
// claim the element about to be read
--top.remaining;
--container_stack.back().remaining;
if (top.is_object)
{
get();
@@ -12280,9 +12281,8 @@ class binary_reader
if (at_end)
{
const bool is_object = top.is_object;
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;
}