diff --git a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp index 1d352d3edc..24eb54e632 100644 --- a/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp +++ b/src/libxrpl/tx/transactors/Sponsor/SponsorshipTransfer.cpp @@ -20,11 +20,21 @@ #include #include +#include #include #include namespace xrpl { +static std::optional +applyCountDelta(std::uint32_t current, std::int64_t delta) +{ + std::int64_t const next = static_cast(current) + delta; + if (next < 0 || next > std::numeric_limits::max()) + return std::nullopt; + return static_cast(next); +} + std::uint32_t SponsorshipTransfer::getFlagsMask(PreflightContext const& ctx) { @@ -363,12 +373,12 @@ SponsorshipTransfer::preclaim(PreclaimContext const& ctx) return tesSUCCESS; } -TER +static TER reduceReserveCount( ApplyView& view, AccountID const& account, AccountID const& sponsor, - int32_t delta) + int64_t delta) { if (delta == 0) return tesSUCCESS; @@ -380,16 +390,15 @@ reduceReserveCount( if (!sponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - auto const reserveCount = sponsorSle->getFieldU32(sfReserveCount); - int32_t const afterReserveCount = reserveCount + delta; - - if (afterReserveCount < 0) + auto const afterReserveCount = applyCountDelta(sponsorSle->getFieldU32(sfReserveCount), delta); + if (!afterReserveCount) { // already checked in preclaim() + UNREACHABLE("xrpl::reduceReserveCount : invalid reserve count"); return tefINTERNAL; // LCOV_EXCL_LINE } - sponsorSle->at(sfReserveCount) = static_cast(afterReserveCount); + sponsorSle->at(sfReserveCount) = *afterReserveCount; view.update(sponsorSle); return tesSUCCESS; } @@ -407,16 +416,17 @@ SponsorshipTransfer::doApply() if (!sponseeSle) return tefINTERNAL; // LCOV_EXCL_LINE - auto const setSponsorFieldU32 = [](auto const& sle, auto const& field, auto const& delta) { - int32_t const newValue = static_cast(sle->getFieldU32(field)) + delta; - - if (newValue < 0) + auto const setSponsorFieldU32 = + [] [[nodiscard]] (auto const& sle, auto const& field, auto const& delta) -> TER { + auto const newValue = applyCountDelta(sle->getFieldU32(field), delta); + if (!newValue) { UNREACHABLE("xrpl::SponsorshipTransfer::doApply : Invalid sponsor field value"); - return; + return tecINTERNAL; // LCOV_EXCL_LINE } - sle->at(field) = static_cast(newValue); + sle->at(field) = *newValue; + return tesSUCCESS; }; if (isObjectSponsor) @@ -436,7 +446,7 @@ SponsorshipTransfer::doApply() if (!ownerSle) return tefINTERNAL; // LCOV_EXCL_LINE - auto const ownerCountDelta = getLedgerEntryOwnerCount(objSle); + std::int64_t const ownerCountDelta = getLedgerEntryOwnerCount(objSle); auto const& sponsorField = getLedgerEntrySponsorField(objSle, *ownerAccountID); @@ -446,14 +456,20 @@ SponsorshipTransfer::doApply() XRPL_ASSERT(!!newSponsorAccountID, "New sponsor is required when creating sponsorship"); // update owner's sponsored count - setSponsorFieldU32(ownerSle, sfSponsoredOwnerCount, ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(ownerSle, sfSponsoredOwnerCount, ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(ownerSle); // increment new sponsor's sponsoring count auto const newSponsorSle = view().peek(keylet::account(newSponsorAccountID)); if (!newSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(newSponsorSle); // set new sponsor to object @@ -483,14 +499,20 @@ SponsorshipTransfer::doApply() auto const oldSponsorSle = view().peek(keylet::account(oldSponsorAccountID)); if (!oldSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(oldSponsorSle, sfSponsoringOwnerCount, -ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(oldSponsorSle, sfSponsoringOwnerCount, -ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(oldSponsorSle); // increment new sponsor's sponsoring count auto const newSponsorSle = view().peek(keylet::account(newSponsorAccountID)); if (!newSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(newSponsorSle, sfSponsoringOwnerCount, ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(newSponsorSle); // set new sponsor to object @@ -516,11 +538,17 @@ SponsorshipTransfer::doApply() return tefINTERNAL; // LCOV_EXCL_LINE // decrement sponsored count - setSponsorFieldU32(sponseeSle, sfSponsoredOwnerCount, -ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(sponseeSle, sfSponsoredOwnerCount, -ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(sponseeSle); // decrement old sponsoring count - setSponsorFieldU32(oldSponsorSle, sfSponsoringOwnerCount, -ownerCountDelta); + if (auto const ter = + setSponsorFieldU32(oldSponsorSle, sfSponsoringOwnerCount, -ownerCountDelta); + !isTesSuccess(ter)) + return ter; view().update(oldSponsorSle); // remove sponsor from object @@ -538,7 +566,9 @@ SponsorshipTransfer::doApply() auto const newSponsorSle = view().peek(keylet::account(newSponsorAccountID)); if (!newSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(newSponsorSle, sfSponsoringAccountCount, 1); + if (auto const ter = setSponsorFieldU32(newSponsorSle, sfSponsoringAccountCount, 1); + !isTesSuccess(ter)) + return ter; view().update(newSponsorSle); // set new sponsor to account @@ -553,7 +583,9 @@ SponsorshipTransfer::doApply() auto const newSponsorSle = view().peek(keylet::account(newSponsorAccountID)); if (!newSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(newSponsorSle, sfSponsoringAccountCount, 1); + if (auto const ter = setSponsorFieldU32(newSponsorSle, sfSponsoringAccountCount, 1); + !isTesSuccess(ter)) + return ter; view().update(newSponsorSle); // decrement old sponsoring count @@ -561,7 +593,9 @@ SponsorshipTransfer::doApply() auto const oldSponsorSle = view().peek(keylet::account(oldSponsor)); if (!oldSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(oldSponsorSle, sfSponsoringAccountCount, -1); + if (auto const ter = setSponsorFieldU32(oldSponsorSle, sfSponsoringAccountCount, -1); + !isTesSuccess(ter)) + return ter; view().update(oldSponsorSle); // set new sponsor to account @@ -579,7 +613,9 @@ SponsorshipTransfer::doApply() auto const oldSponsorSle = view().peek(keylet::account(oldSponsorAccountID)); if (!oldSponsorSle) return tefINTERNAL; // LCOV_EXCL_LINE - setSponsorFieldU32(oldSponsorSle, sfSponsoringAccountCount, -1); + if (auto const ter = setSponsorFieldU32(oldSponsorSle, sfSponsoringAccountCount, -1); + !isTesSuccess(ter)) + return ter; view().update(oldSponsorSle); } }