Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add empty vector check before xdr_get in HerderPersistenceImpl::getQuorumSet#5230

Draft
Copilot wants to merge 1 commit into
master from
copilot/fix-undefined-behavior-on-empty-vector-check
Draft

Add empty vector check before xdr_get in HerderPersistenceImpl::getQuorumSet #5230
Copilot wants to merge 1 commit into
master from
copilot/fix-undefined-behavior-on-empty-vector-check

Conversation

Copilot AI commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Summary

HerderPersistenceImpl::getQuorumSet decodes a base64 quorum set blob from the database into a std::vector<uint8_t> and then constructs xdr::xdr_get using &qSetBytes.front() / &qSetBytes.back() + 1 without checking whether the decoded vector is empty. If a corrupted database row contains an empty string, evaluating front() and back() on an empty vector is undefined behavior in C++.

This adds an empty-vector guard that throws a descriptive std::runtime_error before the UB can occur, matching the identical pattern already established in LedgerHeaderUtils::decodeFromData (line 111-114 of LedgerHeaderUtils.cpp).

Details

The only unguarded site using the &vec.front() / &vec.back() + 1 pattern was in HerderPersistenceImpl.cpp:369. Other database read paths either:

  • Already had an empty check (LedgerHeaderUtils.cpp)
  • Used xdr::xdr_from_opaque() which internally uses .data() / .data() + .size() and is safe for empty vectors

Testing

Database corruptions should not happen in practice, so this is a defensive guard. The change is a simple 5-line conditional that throws before any pointer dereference, consistent with existing error handling in the codebase.

...orumSet
Add a guard to check if the decoded quorum set bytes vector is empty
before constructing xdr_get with &vec.front()/&vec.back()+1. Without
this check, calling front()/back() on an empty vector is undefined
behavior in C++. If a corrupted database row contains an empty blob,
the code now throws a descriptive runtime_error instead of proceeding
with UB. This matches the existing pattern in LedgerHeaderUtils.cpp.
Agent-Logs-Url: https://github.com/stellar/stellar-core/sessions/5f91013f-7cd3-40f0-9039-c541ad3e93b2
Co-authored-by: marta-lokhova <9428003+marta-lokhova@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@marta-lokhova marta-lokhova Awaiting requested review from marta-lokhova

Copilot code review Copilot Awaiting requested review from Copilot Copilot will automatically review once the pull request is marked ready for review

At least 1 approving review is required to merge this pull request.

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

AltStyle によって変換されたページ (->オリジナル) /