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:
@ -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);
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user