From cb893bf197cfc040ed22150d0497d6d46ac650e6 Mon Sep 17 00:00:00 2001 From: selsta Date: Tue, 22 Sep 2026 20:47:53 +0200 Subject: [PATCH] cryptonote_protocol: tighten pruned transaction blob validation (cherry picked from commit 71e3be0e48d0939dfd2500f703b69234967d254a) --- src/cryptonote_basic/cryptonote_format_utils.cpp | 3 ++- src/cryptonote_basic/cryptonote_format_utils.h | 2 +- src/cryptonote_protocol/cryptonote_protocol_handler.inl | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index ba61748a2..d4a13e581 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -253,11 +253,12 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx) + bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx, const bool require_eof) { binary_archive ba{epee::strspan(tx_blob)}; bool r = tx.serialize_base(ba); CHECK_AND_ASSERT_MES(r, false, "Failed to parse transaction from blob"); + CHECK_AND_ASSERT_MES(::serialization::check_stream_state(ba, !require_eof), false, "Unexpected trailing data after transaction base"); CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data"); tx.invalidate_hashes(); return true; diff --git a/src/cryptonote_basic/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h index 296f45abc..f0f25575f 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.h +++ b/src/cryptonote_basic/cryptonote_format_utils.h @@ -56,7 +56,7 @@ namespace cryptonote bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash); bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx, crypto::hash& tx_hash); bool parse_and_validate_tx_from_blob(const blobdata_ref& tx_blob, transaction& tx); - bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx); + bool parse_and_validate_tx_base_from_blob(const blobdata_ref& tx_blob, transaction& tx, const bool require_eof = false); bool is_v1_tx(const blobdata_ref& tx_blob); bool is_v1_tx(const blobdata& tx_blob); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index e0bd59e00..0e0d53704 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -115,7 +115,7 @@ namespace cryptonote bool parse_success = false; if (is_pruned) { - if ((parse_success = cryptonote::parse_and_validate_tx_base_from_blob(tx_entry.blob, tx))) + if ((parse_success = cryptonote::parse_and_validate_tx_base_from_blob(tx_entry.blob, tx, /*require_eof=*/true))) parse_success = cryptonote::get_pruned_transaction_hash(tx, tx_entry.prunable_hash, tx_hash); } else