Skip to content

Catch the exception actually thrown when a bucket fails to deserialise - #8371

Merged
Max (maxtropets) merged 4 commits into
microsoft:mainfrom
achamayou:achamayou-fix-bucketed-index-deserialise-catch
Sep 14, 2026
Merged

Max (maxtropets) merged 4 commits into
microsoft:mainfrom
achamayou:achamayou-fix-bucketed-index-deserialise-catch

Conversation

@achamayou

@achamayou Amaury Chamayou (achamayou) commented Sep 14, 2026

Copy link
Copy Markdown
Member

SeqnosByKey_Bucketed_Untyped::Impl::deserialise catches std::logic_error to treat an unparseable bucket as corrupt, but serialized::read throws serialized::InsufficientSpaceException, which derives directly from std::exception. The catch missed this exception.

A loaded bucket that did not contain a well-formed serialisation therefore escaped get_write_txs_in_range as an exception, which the frontend reports as HTTP 500 InternalError. Since the bucket stayed in the LRU in its Loaded state, every later query touching that range threw again until it was evicted, and the strategy never re-indexed.

This catches InsufficientSpaceException instead, so malformed bucket contents are reported as corrupt and the index is rebuilt, as intended. ContiguousSet::insert can still throw allocation or capacity exceptions, including std::bad_alloc and std::length_error (which derives from std::logic_error). These are left to propagate rather than being misclassified as corruption; rebuilding the index would not address the underlying resource or capacity problem.

In practice this path is only reachable with content that has passed AES-GCM authentication and the key-prefix check in EnclaveLFSAccess, so it is defensive rather than attacker-controlled. Noticed while reviewing #7955.

The other catch (const std::logic_error&) around serialized::* calls, in raft.h via LedgerEnclave::get_entry/skip_entry, is fine: get_entry_size bounds-checks with its own std::logic_error before any serialized::peek/skip.

SeqnosByKey_Bucketed_Untyped::Impl::deserialise catches std::logic_error
to treat an unparseable bucket as corrupt, but serialized::read throws
InsufficientSpaceException, which derives directly from std::exception.
The catch was dead, so a loaded bucket which did not contain a
well-formed serialisation escaped as an exception from
get_write_txs_in_range, reaching the calling endpoint handler. The
bucket remained in the LRU in its loaded state, so every later query
touching that range threw again, and the strategy never re-indexed.

Catch InsufficientSpaceException instead, which is the only exception
that block can throw, so that such a bucket is reported as corrupt and
the index is rebuilt.

In practice this path is only reachable with content that has passed
AES-GCM authentication, so it is defensive rather than attacker
controlled.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 14, 2026 07:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The fix is covered by regression tests and no unresolved issues were identified.

Pull request overview

Fixes malformed LFS bucket handling by catching serialized::InsufficientSpaceException and triggering re-indexing instead of propagating errors.

Changes:

  • Catch the correct deserialization exception.
  • Add malformed-bucket and recovery regression tests.
File summaries
File Description
src/indexing/test/lfs.cpp Adds malformed-bucket and re-indexing recovery tests.
src/indexing/strategies/seqnos_by_key_bucketed.cpp Handles malformed bucket deserialization as corruption.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@maxtropets
Max (maxtropets) enabled auto-merge (squash) September 14, 2026 08:32
@maxtropets
Max (maxtropets) merged commit b08a5c6 into microsoft:main Sep 14, 2026
15 of 23 checks passed
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.

3 participants