Skip to content

Reject unrepresentable deserialised trees - #82

Closed
Amaury Chamayou (achamayou) wants to merge 2 commits into
achamayou-tree-deserialise-ownershipfrom
achamayou-tree-size-validation
Closed

Reject unrepresentable deserialised trees#82
Amaury Chamayou (achamayou) wants to merge 2 commits into
achamayou-tree-deserialise-ownershipfrom
achamayou-tree-size-validation

Conversation

@achamayou

@achamayou Amaury Chamayou (achamayou) commented Aug 24, 2026

Copy link
Copy Markdown
Member

Summary

  • reject serialised trees whose flushed count is non-zero while their retained-leaf count is zero
  • add a focused malformed-input regression that supplies the flushed-subtree hash and verifies the dedicated error

Rationale

The normal serializer cannot produce this count combination. flush_to(index) removes leaves strictly before the flush boundary and retains the boundary leaf, so every non-empty serialised tree has at least one retained leaf hash. Accepting {retained leaves: 0, flushed leaves: > 0} constructs a flushed-only state that is outside the tree representation's invariants.

The deserializer now reports this case as serialised tree has no retained leaves before attempting reconstruction.

Arithmetic limits

The lower stack layer in #78 now owns the size/count validation that this PR originally carried:

  • for L logical leaves, 2 * L - 1 must fit in size_t, so the maximum representable leaf count is SIZE_MAX / 2 + 1
  • the retained and flushed counts are checked with subtraction rather than overflowing addition
  • full-subtree sizes avoid shifting by the size_t bit width
  • the hash preflight includes retained hashes plus one flushed-subtree hash per set bit in the flushed count

This PR deliberately does not duplicate those checks. Its remaining delta is only the orthogonal representability rule that a non-empty flushed prefix must have a retained boundary leaf.

Malformed-input cases

  • retained 0, flushed 0: valid empty tree
  • retained > 0, flushed 0: valid subject to the lower layer's size and byte-count checks
  • retained > 0, flushed > 0: valid subject to the same checks
  • retained 0, flushed > 0: rejected because no valid serializer output has a flushed-only tree

Tests

TreeT rejects invalid serialised leaf data now builds a complete {retained: 0, flushed: 1} payload, including its required flushed-subtree hash, and checks for the dedicated std::runtime_error message.

Validated with the focused unit_tests CTest target in a Debug build.

Stacked immediately above #80 in native stack #85.

Own partially reconstructed nodes until the complete tree has been built, then transfer the final root and leaf metadata. Add a malformed flushed-tree regression that exercises cleanup after partial reconstruction.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@achamayou
Amaury Chamayou (achamayou) force-pushed the achamayou-tree-deserialise-ownership branch from 2a49f78 to 5778593 Compare August 24, 2026 20:31
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@achamayou
Amaury Chamayou (achamayou) force-pushed the achamayou-tree-deserialise-ownership branch 2 times, most recently from 4a25c5b to e3801e3 Compare August 25, 2026 12:54
@achamayou

Copy link
Copy Markdown
Member Author

Folded the remaining no-retained-leaves validation and regression test into #78, then rebuilt the native stack without this layer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant