fix(tx_extra): enforce equal vector lengths in tx_extra_master_node_register#197
Open
raw391 wants to merge 1 commit into
Open
fix(tx_extra): enforce equal vector lengths in tx_extra_master_node_register#197raw391 wants to merge 1 commit into
raw391 wants to merge 1 commit into
Conversation
…egister tx_extra_master_node_register carries three parallel vectors (m_public_spend_keys, m_public_view_keys, m_portions) that are intended to be index-aligned. The serializer reads each as an independent vector with no cross-field invariant, so a malformed field with desynchronized lengths deserializes successfully and exposes consumers to out-of-bounds reads. Two consumers index by one vector size and read another: master_node_list.cpp:305-309 (block-include path) and core_rpc_server.cpp:711-720 (mempool-staged + RPC tx_extra=true). Enforces the equal-length invariant in the deserializer, matching the tx_extra_padding pattern at tx_extra.h:195-210. Adds defensive guards at both consumers so the call sites stay safe if the invariant drifts in a future change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tx_extra_master_node_registeratsrc/cryptonote_basic/tx_extra.h:317-334carries three parallel vectors (m_public_spend_keys,m_public_view_keys,m_portions) that are intended to be index-aligned. The serializer reads each as an independent vector with no cross-field invariant, so a malformed field with desynchronized lengths deserializes successfully and exposes consumers to out-of-bounds reads.Two consumers index by one vectors size and read another. The block-include path at
master_node_list.cpp:305-309(reg_tx_extract_fields):validate_contributor_args(line 333) catches the size mismatch only after the loop runs.The RPC path at
core_rpc_server.cpp:711-720(extra_extractor::operator()(tx_extra_master_node_register&)) is reachable from any otherwise valid relayable transaction that carries a malformedtx_extra_master_node_registerfield.tx_pool::add_txaccepts arbitrarytx.extracontent on standard transfer transactions, so the tx sits in mempool until a caller queriesget_transactionsorget_transaction_poolwithtx_extra=true. The visitor then reads past the end of one of the key vectors; outcome depends on heap layout.Patch enforces the equal-length invariant at deserialization (matching the
tx_extra_paddingpattern attx_extra.h:195-210), and adds size-equality guards at both consumers so the call sites stay safe if the invariant ever drifts.struct tx_extra_master_node_register { ... BEGIN_SERIALIZE() FIELD(m_public_spend_keys) FIELD(m_public_view_keys) FIELD(m_portions_for_operator) FIELD(m_portions) FIELD(m_expiration_timestamp) FIELD(m_master_node_signature) + if (Archive::is_deserializer) + { + if (m_public_spend_keys.size() != m_public_view_keys.size()) + throw std::invalid_argument{"tx_extra_master_node_register: spend/view key count mismatch"}; + if (m_public_spend_keys.size() != m_portions.size()) + throw std::invalid_argument{"tx_extra_master_node_register: spend/portions count mismatch"}; + } END_SERIALIZE() };