Fix unaligned read of short_vec pubkey_size in sigverify (#6388)

automerge
This commit is contained in:
Ryo Onodera 2019-10-17 03:09:17 +09:00 committed by Grimes
parent a258e1e0b3
commit f4c5da3c72
1 changed files with 45 additions and 4 deletions

View File

@ -84,13 +84,14 @@ fn batch_size(batches: &[Packets]) -> usize {
pub fn get_packet_offsets(packet: &Packet, current_offset: u32) -> (u32, u32, u32, u32) {
let (sig_len, sig_size) = decode_len(&packet.data);
let msg_start_offset = sig_size + sig_len * size_of::<Signature>();
let msg_header_size = serialized_size(&MessageHeader::default()).unwrap() as usize;
let (_pubkey_len, pubkey_size) = decode_len(&packet.data[msg_start_offset..]);
let (_pubkey_len, pubkey_size) =
decode_len(&packet.data[(msg_start_offset + msg_header_size)..]);
let sig_start = current_offset as usize + sig_size;
let msg_start = current_offset as usize + msg_start_offset;
let pubkey_start =
msg_start + serialized_size(&MessageHeader::default()).unwrap() as usize + pubkey_size;
let pubkey_start = msg_start + msg_header_size + pubkey_size;
(
sig_len as u32,
@ -288,8 +289,12 @@ mod tests {
use crate::recycler::Recycler;
use crate::sigverify;
use crate::test_tx::{test_multisig_tx, test_tx};
use bincode::{deserialize, serialize};
use bincode::{deserialize, serialize, serialized_size};
use solana_sdk::hash::Hash;
use solana_sdk::message::{Message, MessageHeader};
use solana_sdk::signature::Signature;
use solana_sdk::transaction::Transaction;
use std::mem::size_of;
const SIG_OFFSET: usize = 1;
@ -342,6 +347,42 @@ mod tests {
assert_eq!(sig_len, 1);
}
#[test]
fn test_large_sigs() {
// use any large number to be misinterpreted as 2 bytes when decoded as short_vec
let required_num_sigs = 214;
let actual_num_sigs = 5;
let message = Message {
header: MessageHeader {
num_required_signatures: required_num_sigs,
num_credit_only_signed_accounts: 12,
num_credit_only_unsigned_accounts: 11,
},
account_keys: vec![],
recent_blockhash: Hash::default(),
instructions: vec![],
};
let mut tx = Transaction::new_unsigned(message);
// reduce to actual_num_sigs to avoid packet error
tx.signatures = vec![Signature::default(); actual_num_sigs];
let packet = sigverify::make_packet_from_transaction(tx.clone());
let (_sig_len, _sig_start, _msg_start_offset, pubkey_offset) =
sigverify::get_packet_offsets(&packet, 0);
let expected_sig_size = 1;
let expected_sigs_size = actual_num_sigs * size_of::<Signature>();
let expected_msg_header_size = serialized_size(&MessageHeader::default()).unwrap() as usize;
let expected_pubkey_size = 1;
let expected_pubkey_start = expected_sig_size
+ expected_sigs_size
+ expected_msg_header_size
+ expected_pubkey_size;
assert_eq!(expected_pubkey_start, pubkey_offset as usize);
}
#[test]
fn test_system_transaction_data_layout() {
use crate::packet::PACKET_DATA_SIZE;