fix: Add zero NFT Offer ID check for NFTokenCancelOffer (#7391)

This commit is contained in:
yinyiqian1
2026-06-03 15:30:20 -04:00
committed by GitHub
parent 023bdaeeed
commit e5cf1a0985
2 changed files with 28 additions and 2 deletions

View File

@@ -4,6 +4,7 @@
#include <xrpl/basics/base_uint.h>
#include <xrpl/ledger/View.h>
#include <xrpl/ledger/helpers/NFTokenHelpers.h>
#include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/Indexes.h>
#include <xrpl/protocol/LedgerFormats.h>
#include <xrpl/protocol/Protocol.h>
@@ -21,8 +22,14 @@ namespace xrpl {
NotTEC
NFTokenCancelOffer::preflight(PreflightContext const& ctx)
{
if (auto const& ids = ctx.tx[sfNFTokenOffers];
ids.empty() || (ids.size() > kMaxTokenOfferCancelCount))
auto const& offerIds = ctx.tx[sfNFTokenOffers];
if (offerIds.empty() || (offerIds.size() > kMaxTokenOfferCancelCount))
return temMALFORMED;
// Zero offer IDs cannot be passed as ledger entry keys.
if (ctx.rules.enabled(fixCleanup3_2_0) &&
std::ranges::any_of(offerIds, [](uint256 const& id) { return id.isZero(); }))
return temMALFORMED;
// In order to prevent unnecessarily overlarge transactions, we

View File

@@ -892,6 +892,25 @@ class NFTokenBaseUtil_test : public beast::unit_test::Suite
BEAST_EXPECT(ownerCount(env, buyer) == 1);
}
// Only test this with fixCleanup3_2_0 enabled. Without the fix,
// an assert-enabled build can crash when Ledger::read() receives
// a zero-key offer ID.
if (features[fixCleanup3_2_0])
{
// Zero is not a valid offer ID.
env(token::cancelOffer(buyer, {uint256{}}), Ter(temMALFORMED));
env.close();
BEAST_EXPECT(ownerCount(env, buyer) == 1);
// List of offer IDs containing zero is invalid.
// craftedIndex is not a valid offer index but it is not zero.
auto const craftedIndex = keylet::nftoffer(gw, env.seq(gw)).key;
env(token::cancelOffer(buyer, {buyerOfferIndex, uint256{}, craftedIndex}),
Ter(temMALFORMED));
env.close();
BEAST_EXPECT(ownerCount(env, buyer) == 1);
}
// List of tokens to delete is too long.
{
std::vector<uint256> const offers(kMaxTokenOfferCancelCount + 1, buyerOfferIndex);