From c377802477bf0f38ed192e346bc6dfaef12e70a0 Mon Sep 17 00:00:00 2001 From: Vladislav Vysokikh Date: Wed, 1 Jul 2026 11:28:59 +0100 Subject: [PATCH] fix: reject zero CheckID in CheckCancel and CheckCash --- src/libxrpl/tx/transactors/check/CheckCancel.cpp | 5 +++++ src/libxrpl/tx/transactors/check/CheckCash.cpp | 4 ++++ src/test/app/Check_test.cpp | 14 ++++++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/libxrpl/tx/transactors/check/CheckCancel.cpp b/src/libxrpl/tx/transactors/check/CheckCancel.cpp index d966772191..0c13f9334e 100644 --- a/src/libxrpl/tx/transactors/check/CheckCancel.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCancel.cpp @@ -1,10 +1,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -19,6 +21,9 @@ namespace xrpl { NotTEC CheckCancel::preflight(PreflightContext const& ctx) { + if (ctx.rules.enabled(fixCleanup3_3_0) && ctx.tx[sfCheckID] == beast::kZero) + return temMALFORMED; + return tesSUCCESS; } diff --git a/src/libxrpl/tx/transactors/check/CheckCash.cpp b/src/libxrpl/tx/transactors/check/CheckCash.cpp index 80ef742f52..a48d6078fb 100644 --- a/src/libxrpl/tx/transactors/check/CheckCash.cpp +++ b/src/libxrpl/tx/transactors/check/CheckCash.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -49,6 +50,9 @@ CheckCash::checkExtraFeatures(xrpl::PreflightContext const& ctx) NotTEC CheckCash::preflight(PreflightContext const& ctx) { + if (ctx.rules.enabled(fixCleanup3_3_0) && ctx.tx[sfCheckID] == beast::kZero) + return temMALFORMED; + // Exactly one of Amount or DeliverMin must be present. auto const optAmount = ctx.tx[~sfAmount]; auto const optDeliverMin = ctx.tx[~sfDeliverMin]; diff --git a/src/test/app/Check_test.cpp b/src/test/app/Check_test.cpp index 3ad1e3fa4e..69ccb28051 100644 --- a/src/test/app/Check_test.cpp +++ b/src/test/app/Check_test.cpp @@ -1257,6 +1257,12 @@ class Check_test : public beast::unit_test::Suite env.close(); } + // Zero CheckID is malformed once fixCleanup3_3_0 is active; before + // that it simply misses the ledger lookup. + env(check::cash(bob, uint256{}, usd(20)), + Ter(features[fixCleanup3_3_0] ? TER{temMALFORMED} : TER{tecNO_ENTRY})); + env.close(); + // alice creates her checks ahead of time. uint256 const chkIdU{getCheckIndex(alice, env.seq(alice))}; env(check::create(alice, bob, usd(20))); @@ -1704,6 +1710,12 @@ class Check_test : public beast::unit_test::Suite // Non-existent check. env(check::cancel(bob, getCheckIndex(alice, env.seq(alice))), Ter(tecNO_ENTRY)); env.close(); + + // Zero CheckID is malformed once fixCleanup3_3_0 is active; before + // that it simply misses the ledger lookup. + env(check::cancel(bob, uint256{}), + Ter(features[fixCleanup3_3_0] ? TER{temMALFORMED} : TER{tecNO_ENTRY})); + env.close(); } void @@ -2498,6 +2510,8 @@ public: using namespace test::jtx; auto const sa = testableAmendments(); testWithFeats(sa); + testCancelInvalid(sa - fixCleanup3_3_0); + testCashInvalid(sa - fixCleanup3_3_0); testTrustLineCreation(sa); } };