wallet2: avoid std::out_of_range on a truncated tx set blob
What changed, and why it matters
This commit fixes a minor crash bug in Monero's wallet code. When the wallet tried to read a transaction data blob that contained only the file-type 'magic' header and nothing else, it would throw an uncaught out-of-range exception instead of cleanly reporting 'bad data.' The patch makes the wallet check that at least one byte follows the magic before reading it, turning the crash into a normal error return.
Apply the patch. It is a low-risk, defensive fix. Consider also auditing other parse_*_from_str helpers for similar missing length checks after magic stripping.
Security signals we found
Denial-of-service vector: unhandled std::out_of_range exception on malformed input
Input-validation gap: magic prefix checked without ensuring minimum remaining length
Exception-safety fix in transaction deserialization paths
Evidence from the diff
wallet2::parse_unsigned_tx_from_str() and wallet2::parse_tx_from_str() strip the magic prefix, then read a version byte via s[1] / s.substr(1). The existing check only verified the magic prefix with strncmp(…, magiclen), where magiclen is strlen(PREFIX)-1. A blob exactly equal to the magic (or shorter) leaves s with size <= magiclen, so the subsequent version-byte access can throw std::out_of_range. The patch adds a size guard (s.size() < magiclen + 1) so the function returns false early with a logged ‘Bad magic’ message.
Changed components
src/wallet/wallet2.cppwallet2::parse_unsigned_tx_from_strwallet2::parse_tx_from_strInspect captured patch +2 / −2
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 3bd03e6..208969c 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -7743,7 +7743,7 @@ bool wallet2::parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsi
{
std::string s = unsigned_tx_st;
const size_t magiclen = strlen(UNSIGNED_TX_PREFIX) - 1;
- if (strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen))
+ if (s.size() < magiclen + 1 || strncmp(s.c_str(), UNSIGNED_TX_PREFIX, magiclen))
{
LOG_PRINT_L0("Bad magic from unsigned tx");
return false;
@@ -8021,7 +8021,7 @@ bool wallet2::parse_tx_from_str(const std::string &signed_tx_st, std::vector<too
signed_tx_set signed_txs;
const size_t magiclen = strlen(SIGNED_TX_PREFIX) - 1;
- if (strncmp(s.c_str(), SIGNED_TX_PREFIX, magiclen))
+ if (s.size() < magiclen + 1 || strncmp(s.c_str(), SIGNED_TX_PREFIX, magiclen))
{
LOG_PRINT_L0("Bad magic from signed transaction");
return false;
Why this scored 28/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.