Sponsored Content
Skip to content

fix: Remaining clang-tidy unchecked optionals - #6979

Merged
bthomee merged 5 commits into
XRPLF:developfrom
godexsoft:fix/clang-tidy-optional
Apr 23, 2026
Merged

fix: Remaining clang-tidy unchecked optionals#6979
bthomee merged 5 commits into
XRPLF:developfrom
godexsoft:fix/clang-tidy-optional

Conversation

@godexsoft

Copy link
Copy Markdown
Contributor

High Level Overview of Change

This PR fixes remaining issues from bugprone-unchecked-optional-access.

API Impact

No impact.

@godexsoft godexsoft self-assigned this Apr 20, 2026
@godexsoft godexsoft added the DraftRunCI Normally CI does not run on draft PRs. This opts in. label Apr 20, 2026
@codecov

codecov Bot commented Apr 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.67925% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.9%. Comparing base (7c7c189) to head (2ccdb28).
⚠️ Report is 8 commits behind head on develop.

Files with missing lines Patch % Lines
include/xrpl/protocol/PublicKey.h 0.0% 3 Missing ⚠️
src/libxrpl/tx/paths/OfferStream.cpp 50.0% 1 Missing ⚠️
src/xrpld/consensus/LedgerTrie.h 0.0% 1 Missing ⚠️
src/xrpld/rpc/detail/PathRequest.cpp 50.0% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #6979     +/-   ##
=========================================
- Coverage     82.5%   81.9%   -0.7%     
=========================================
  Files         1010    1010             
  Lines        79246   76395   -2851     
  Branches      7529    7529             
=========================================
- Hits         65389   62532   -2857     
- Misses       13857   13863      +6     
Files with missing lines Coverage Δ
include/xrpl/tx/ApplyContext.h 100.0% <100.0%> (ø)
include/xrpl/tx/paths/OfferStream.h 100.0% <100.0%> (ø)
include/xrpl/tx/paths/detail/StrandFlow.h 93.2% <ø> (ø)
src/libxrpl/net/HTTPClient.cpp 70.9% <100.0%> (-2.3%) ⬇️
src/libxrpl/server/Manifest.cpp 85.7% <100.0%> (-1.1%) ⬇️
src/libxrpl/shamap/SHAMapInnerNode.cpp 96.5% <100.0%> (-0.3%) ⬇️
src/libxrpl/tx/ApplyContext.cpp 100.0% <100.0%> (ø)
src/libxrpl/tx/invariants/AMMInvariant.cpp 95.1% <ø> (-0.1%) ⬇️
src/libxrpl/tx/paths/BookStep.cpp 95.9% <100.0%> (-0.1%) ⬇️
src/libxrpl/tx/paths/DirectStep.cpp 83.9% <ø> (-0.7%) ⬇️
... and 20 more

... and 413 files with indirect coverage changes

Impacted file tree graph

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@godexsoft
godexsoft force-pushed the fix/clang-tidy-optional branch from 9185926 to b8fe16f Compare April 20, 2026 17:28
Fix level

More clang-tidy fixes

Fix more from ci

Autofixes on linux

Fix format

Bring back original shell

Fix remaining clang-tidy

More
@godexsoft
godexsoft force-pushed the fix/clang-tidy-optional branch from 16005c0 to 3303daf Compare April 21, 2026 15:07
@godexsoft
godexsoft marked this pull request as ready for review April 21, 2026 16:03
@godexsoft godexsoft removed the DraftRunCI Normally CI does not run on draft PRs. This opts in. label Apr 21, 2026
@bthomee
bthomee requested a review from Copilot April 21, 2026 16:05

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.

Pull request overview

This PR enables the bugprone-unchecked-optional-access clang-tidy check and updates the codebase to address the remaining findings, primarily by adding targeted NOLINT annotations and a few small runtime guards where needed.

Changes:

  • Enable bugprone-unchecked-optional-access in .clang-tidy.
  • Add NOLINT suppressions around optional dereferences that are currently treated as invariants/assert-protected.
  • Add a small number of functional fixes to avoid unchecked dereferences (e.g., extra null/optional checks).

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/xrpld/rpc/detail/RPCLedgerHelpers.cpp Adds NOLINTBEGIN/END around refHash dereferences in ledger acquisition flow.
src/xrpld/rpc/detail/PathRequest.cpp Adds NOLINT annotations around raSrcAccount/raDstAccount dereferences after isValid().
src/xrpld/perflog/detail/PerfLogImp.cpp Removes an unused include.
src/xrpld/overlay/detail/PeerImp.cpp Adds NOLINT around assert-guarded optional dereferences.
src/xrpld/overlay/detail/OverlayImpl.cpp Adds NOLINTBEGIN/END around manifest optional access guarded by assert.
src/xrpld/consensus/LedgerTrie.h Adds NOLINT for optional access guarded by asserts/invariants.
src/xrpld/consensus/Consensus.h Adds NOLINT for result_ dereferences and minor formatting/operator-token changes.
src/xrpld/app/misc/detail/ValidatorSite.cpp Adds NOLINT for optional port dereference (documented as defaulted earlier).
src/xrpld/app/misc/detail/ValidatorList.cpp Adds NOLINT around optional publisher key/max sequence accesses.
src/xrpld/app/misc/detail/TxQ.cpp Avoids dereferencing an empty optional fee level (changes fallback behavior).
src/xrpld/app/misc/TxQ.h Adds NOLINT comments for pfResult invariants.
src/xrpld/app/main/Application.cpp Adds NOLINT comments for invariant/assert-protected member dereferences.
src/xrpld/app/ledger/LedgerHistory.cpp Adds NOLINT around consensus.value() access (documented invariant).
src/test/protocol/Hooks_test.cpp Wraps optional deref with NOLINTBEGIN/END.
src/test/jtx/mpt.h Adds NOLINT for optional issuance ID dereference after test assertion.
src/test/jtx/impl/TestHelpers.cpp Adds missing null check (po.object) and adds NOLINT on optional path element deref.
src/test/jtx/TrustedPublisherServer.h Adds NOLINT around optional dereferences in test server helper.
src/test/core/Config_test.cpp Adds protocol include (and keeps it via IWYU pragma).
src/test/app/GRPCServerTLS_test.cpp Adds NOLINT around optional port dereferences after has_value() checks.
src/test/app/AccountTxPaging_test.cpp Removes unused include.
src/test/app/AMMMPT_test.cpp Adds NOLINTBEGIN/END around optional AMM dereferences in tests.
src/libxrpl/tx/transactors/payment/DepositPreauth.cpp Adds NOLINT on conditional optional dereference.
src/libxrpl/tx/transactors/dex/AMMVote.cpp Adds NOLINTBEGIN/END around optional dereference guarded by loop/invariant.
src/libxrpl/tx/transactors/dex/AMMBid.cpp Adds NOLINTBEGIN/END around assert-guarded optional dereference.
src/libxrpl/tx/paths/OfferStream.cpp Adds a guard to avoid using ownerFunds_ when not set.
src/libxrpl/tx/paths/MPTEndpointStep.cpp Adds NOLINT around cache optional dereferences under documented invariants/asserts.
src/libxrpl/tx/paths/Flow.cpp Adds NOLINT for sandbox optional deref on success path.
src/libxrpl/tx/paths/DirectStep.cpp Adds NOLINT around cache optional dereferences under documented invariants/asserts.
src/libxrpl/tx/paths/BookStep.cpp Adds NOLINT around quality optional dereference and cache invariants.
src/libxrpl/tx/invariants/AMMInvariant.cpp Adds NOLINTBEGIN/END around invariant-protected optionals.
src/libxrpl/tx/ApplyContext.cpp Adds NOLINT around view optional dereferences.
src/libxrpl/shamap/SHAMapInnerNode.cpp Adds NOLINT around optional child-index accesses guarded by asserts/flags.
src/libxrpl/server/Manifest.cpp Adds NOLINT around signingKey optional dereferences under documented invariants.
src/libxrpl/net/HTTPClient.cpp Adds NOLINT around global optional SSL context access.
include/xrpl/tx/paths/detail/StrandFlow.h Adds NOLINTBEGIN/END around cachedIn/cachedOut optional accesses.
include/xrpl/tx/paths/OfferStream.h Adds NOLINT for ownerFunds_ dereference (documented invariant).
include/xrpl/tx/ApplyContext.h Adds NOLINT for view optional dereferences.
include/xrpl/protocol/PublicKey.h Fixes unchecked optional use by validating strUnHex result before deref.
.github/scripts/levelization/results/ordering.txt Updates test layering to include xrpl.protocol.
.clang-tidy Enables bugprone-unchecked-optional-access.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 440 to +461
auto const refIndex = getCandidateLedger(ledgerIndex);
auto refHash = hashOfSeq(*ledger, refIndex, j);
XRPL_ASSERT(refHash, "xrpl::RPC::getOrAcquireLedger : nonzero ledger hash");

// NOLINTBEGIN(bugprone-unchecked-optional-access) assert above
ledger = ledgerMaster.getLedgerByHash(*refHash);
if (!ledger)
{
// We don't have the ledger we need to figure out which
// ledger they want. Try to get it.

if (auto il = context.app.getInboundLedgers().acquire(
*refHash, refIndex, InboundLedger::Reason::GENERIC))
{
Json::Value jvResult = RPC::make_error(
rpcLGR_NOT_FOUND, "acquiring ledger containing requested index");
jvResult[jss::acquiring] = getJson(LedgerFill(*il, &context));
return Unexpected(jvResult);
}

if (auto il = context.app.getInboundLedgers().find(*refHash))
// NOLINTEND(bugprone-unchecked-optional-access)

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

refHash is an std::optional from hashOfSeq(). The only guard here is XRPL_ASSERT(refHash, ...), which compiles out under NDEBUG, so *refHash can be dereferenced when empty in release builds (UB/crash). Please replace the assert+NOLINT with a real runtime check/early-return error path (similar to the neededHash handling above) before using *refHash in getLedgerByHash() / acquire() / find().

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We have an XRPL_ASSERT that suggests it should never be nullptr. however clang-tidy does not understand it. so for now we nolint this

Comment on lines 275 to 281
if (!sumNlast.first)
return {sumNlast.first, FeeLevel64{sumNlast.second}};
auto const totalFeeLevel =
mulDiv(multiplier, sumNlast.second - sumNcurrent.second, target * target);

return {totalFeeLevel.has_value(), *totalFeeLevel};
return {totalFeeLevel.has_value(), totalFeeLevel.value_or(FeeLevel64{})};
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

When mulDiv(...) overflows it returns std::nullopt. Returning FeeLevel64{} (0) in that case is likely incorrect/misleading (and differs from nearby patterns that saturate to muldiv_max / std::numeric_limits<...>::max() on overflow). Consider returning a saturated maximum fee level for the second element when totalFeeLevel is empty, while keeping the boolean flag to indicate overflow.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think nolint is actually correct here. value_or changed behaviour so let's not do that.

Comment on lines 323 to +336
std::optional<STPathElement> const& srcElement,
std::optional<AccountID> const& srcIssuer,
std::optional<uint256> const& domain)
{
return find_paths(
env, src, dst, saDstAmount, saSendMax, srcElement->getPathAsset(), srcIssuer, domain);
env,
src,
dst,
saDstAmount,
saSendMax,
srcElement->getPathAsset(), // NOLINT(bugprone-unchecked-optional-access) callers always
// pass non-null srcElement
srcIssuer,
domain);

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

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

find_paths_by_element takes srcElement as std::optional<STPathElement> with a default of std::nullopt, but unconditionally dereferences it (srcElement->...). This makes the API foot-gun-y and can crash if callers ever use the default. Please either (1) make srcElement a required parameter (non-optional, no default) or (2) add an explicit if (!srcElement) ... handling/assert before dereferencing.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't think we can change it because optional is used to provide default values for surrounding params. It was intentional and i think that it is expected that it wont be nullopt. I added an XRPL_ASSERT to make it obvious

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Tbf it is only called from one test as far as i can see. Let's come back to this when we handle nolints across the codebase.

@godexsoft godexsoft added the Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required. label Apr 21, 2026
@bthomee
bthomee requested a review from kuznetsss April 21, 2026 22:32

// NOLINTBEGIN(bugprone-unchecked-optional-access) cachedIn/Out set after strand is stepped
// above
auto const strandIn = *strand.front()->cachedIn();

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.

Maybe add assert for NOLINT places?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's probably a good idea but i was thinking we will deal with nolints in a separate PR entirely. I'd like to get as many checks working first so we prevent more bad code being added, then work on the things we did not figure out while enabling checks

@godexsoft
godexsoft requested a review from kuznetsss April 22, 2026 12:08
@XRPLF XRPLF deleted a comment from github-actions Bot Apr 22, 2026
Comment thread src/xrpld/app/misc/detail/TxQ.cpp Outdated
Comment on lines 879 to 880
// NOLINTBEGIN(bugprone-unchecked-optional-access) acctTxCount > 0 implies txIter is set
if (acctTxCount == 1 && txIter->first->second.consequences().isBlocker() &&

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should the if-statement here be changed from acctTxCount == 1 to acctTxCount > 0`, or should the comment be changed to reflect the if-condition?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I guess the comment should change as the code stayed the same as it was

Comment thread src/xrpld/consensus/Consensus.h Outdated

if ((ahead == 0u) || (laggards == 0u) || (totalValidators == 0u) || !adaptor_.validator() ||
!adaptor_.haveValidated() || result_->roundTime.read() > parms.ledgerMAX_CONSENSUS)
if ((ahead == 0u) or (laggards == 0u) or (totalValidators == 0u) or not adaptor_.validator() or

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is or and not used here instead of || and !?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's because it reads a bit more like English this way - my personal preference. I can roll it back but we do the same in Clio when it makes sense

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd like consistency. I don't mind || or or for instance, but as long as the chosen one is used everywhere. Right now this just looks like Python mixed in with C++, so let's roll it back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I disagree, imo it's ok to have this particular inconsistency when it makes it read better. I guess this case is not really a good candidate so i have no issue rolling it back here.

Copilot AI review requested due to automatic review settings April 23, 2026 12:03

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.

Pull request overview

Copilot reviewed 40 out of 40 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/xrpld/app/misc/detail/ValidatorList.cpp
Comment thread src/test/jtx/impl/TestHelpers.cpp
Comment thread src/xrpld/consensus/Consensus.h Outdated
@bthomee
bthomee added this pull request to the merge queue Apr 23, 2026
Merged via the queue into XRPLF:develop with commit 19da258 Apr 23, 2026
3 checks passed
marek-foss-neti pushed a commit to marek-foss-neti/rippled that referenced this pull request May 5, 2026
@mvadari mvadari added this to the 3.2.0 milestone May 20, 2026
beartec-jpg pushed a commit to beartec-jpg/FalconLedger that referenced this pull request Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready to merge *PR author* thinks it's ready to merge. Has passed code review. Perf sign-off may still be required.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants