From a2d20e58b956bcf97dc7540b6ca45f83eef287c1 Mon Sep 17 00:00:00 2001 From: Joe C Date: Tue, 22 Oct 2024 17:27:37 +0400 Subject: [PATCH] SVM: add check for check results length mismatch (#3259) --- svm/src/transaction_processor.rs | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index 49aa9e1381b543..7b54dfbf878297 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -249,6 +249,16 @@ impl TransactionBatchProcessor { environment: &TransactionProcessingEnvironment, config: &TransactionProcessingConfig, ) -> LoadAndExecuteSanitizedTransactionsOutput { + // If `check_results` does not have the same length as `sanitized_txs`, + // transactions could be truncated as a result of `.iter().zip()` in + // many of the below methods. + // See . + debug_assert_eq!( + sanitized_txs.len(), + check_results.len(), + "Length of check_results does not match length of sanitized_txs" + ); + // Initialize metrics. let mut error_metrics = TransactionErrorMetrics::default(); let mut execute_timings = ExecuteTimings::default(); @@ -1038,6 +1048,7 @@ mod tests { transaction::{SanitizedTransaction, Transaction, TransactionError}, transaction_context::TransactionContext, }, + test_case::test_case, }; fn new_unchecked_sanitized_message(message: Message) -> SanitizedMessage { @@ -1112,6 +1123,51 @@ mod tests { } } + #[test_case(1; "Check results too small")] + #[test_case(3; "Check results too large")] + #[should_panic(expected = "Length of check_results does not match length of sanitized_txs")] + fn test_check_results_txs_length_mismatch(check_results_len: usize) { + let sanitized_message = new_unchecked_sanitized_message(Message { + account_keys: vec![Pubkey::new_from_array([0; 32])], + header: MessageHeader::default(), + instructions: vec![CompiledInstruction { + program_id_index: 0, + accounts: vec![], + data: vec![], + }], + recent_blockhash: Hash::default(), + }); + + // Transactions, length 2. + let sanitized_txs = vec![ + SanitizedTransaction::new_for_tests( + sanitized_message, + vec![Signature::new_unique()], + false, + ); + 2 + ]; + + let check_results = vec![ + TransactionCheckResult::Ok(CheckedTransactionDetails { + nonce: None, + lamports_per_signature: 0 + }); + check_results_len + ]; + + let batch_processor = TransactionBatchProcessor::::default(); + let callback = MockBankCallback::default(); + + batch_processor.load_and_execute_sanitized_transactions( + &callback, + &sanitized_txs, + check_results, + &TransactionProcessingEnvironment::default(), + &TransactionProcessingConfig::default(), + ); + } + #[test] fn test_inner_instructions_list_from_instruction_trace() { let instruction_trace = [1, 2, 1, 1, 2, 3, 2];