Put empty accounts in the accounts list on load (#9840)

Indexing into accounts array does not match account_keys otherwise.
Also enforce program accounts not at index 0
Enforce at least 1 Read-write signing fee-payer account.
This commit is contained in:
sakridge
2020-05-01 17:23:33 -07:00
committed by GitHub
parent fc46a0d441
commit 894549f002
5 changed files with 196 additions and 61 deletions

View File

@ -165,19 +165,27 @@ pub struct Message {
impl Sanitize for Message {
fn sanitize(&self) -> std::result::Result<(), SanitizeError> {
if self.header.num_required_signatures as usize > self.account_keys.len() {
return Err(SanitizeError::IndexOutOfBounds);
}
if self.header.num_readonly_unsigned_accounts as usize
+ self.header.num_readonly_signed_accounts as usize
// signing area and read-only non-signing area should not overlap
if self.header.num_required_signatures as usize
+ self.header.num_readonly_unsigned_accounts as usize
> self.account_keys.len()
{
return Err(SanitizeError::IndexOutOfBounds);
}
// there should be at least 1 RW fee-payer account.
if self.header.num_readonly_signed_accounts >= self.header.num_required_signatures {
return Err(SanitizeError::IndexOutOfBounds);
}
for ci in &self.instructions {
if ci.program_id_index as usize >= self.account_keys.len() {
return Err(SanitizeError::IndexOutOfBounds);
}
// A program cannot be a payer.
if ci.program_id_index == 0 {
return Err(SanitizeError::IndexOutOfBounds);
}
for ai in &ci.accounts {
if *ai as usize >= self.account_keys.len() {
return Err(SanitizeError::IndexOutOfBounds);

View File

@ -510,6 +510,21 @@ mod tests {
tx = o.clone();
tx.message.instructions[0].accounts[0] = 3;
assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
tx = o.clone();
tx.message.instructions[0].program_id_index = 0;
assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
tx = o.clone();
tx.message.header.num_readonly_signed_accounts = 2;
tx.message.header.num_readonly_unsigned_accounts = 3;
tx.message.account_keys.resize(4, Pubkey::default());
assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
tx = o.clone();
tx.message.header.num_readonly_signed_accounts = 2;
tx.message.header.num_required_signatures = 1;
assert_eq!(tx.sanitize(), Err(SanitizeError::IndexOutOfBounds));
}
fn create_sample_transaction() -> Transaction {