Bail on small deploy buffers (#14677)
This commit is contained in:
@ -392,6 +392,12 @@ fn process_loader_upgradeable_instruction(
|
|||||||
let buffer_data_len = buffer.data_len()?.saturating_sub(buffer_data_offset);
|
let buffer_data_len = buffer.data_len()?.saturating_sub(buffer_data_offset);
|
||||||
let programdata_data_offset = UpgradeableLoaderState::programdata_data_offset()?;
|
let programdata_data_offset = UpgradeableLoaderState::programdata_data_offset()?;
|
||||||
|
|
||||||
|
if buffer.data_len()? < UpgradeableLoaderState::buffer_data_offset()?
|
||||||
|
|| buffer_data_len == 0
|
||||||
|
{
|
||||||
|
log!(logger, "Buffer account too small");
|
||||||
|
return Err(InstructionError::InvalidAccountData);
|
||||||
|
}
|
||||||
if max_data_len < buffer_data_len {
|
if max_data_len < buffer_data_len {
|
||||||
log!(logger, "Max data length is too small to hold Buffer data");
|
log!(logger, "Max data length is too small to hold Buffer data");
|
||||||
return Err(InstructionError::AccountDataTooSmall);
|
return Err(InstructionError::AccountDataTooSmall);
|
||||||
@ -509,6 +515,13 @@ fn process_loader_upgradeable_instruction(
|
|||||||
let programdata_data_offset = UpgradeableLoaderState::programdata_data_offset()?;
|
let programdata_data_offset = UpgradeableLoaderState::programdata_data_offset()?;
|
||||||
let programdata_balance_required = 1.max(rent.minimum_balance(programdata.data_len()?));
|
let programdata_balance_required = 1.max(rent.minimum_balance(programdata.data_len()?));
|
||||||
|
|
||||||
|
if buffer.data_len()? < UpgradeableLoaderState::buffer_data_offset()?
|
||||||
|
|| buffer_data_len == 0
|
||||||
|
{
|
||||||
|
log!(logger, "Buffer account too small");
|
||||||
|
return Err(InstructionError::InvalidAccountData);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify ProgramData account
|
// Verify ProgramData account
|
||||||
|
|
||||||
if programdata.data_len()? < UpgradeableLoaderState::programdata_len(buffer_data_len)? {
|
if programdata.data_len()? < UpgradeableLoaderState::programdata_len(buffer_data_len)? {
|
||||||
@ -1890,6 +1903,44 @@ mod tests {
|
|||||||
.unwrap_err()
|
.unwrap_err()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Test small buffer account
|
||||||
|
bank.clear_signatures();
|
||||||
|
let mut modified_buffer_account = Account::new(
|
||||||
|
min_programdata_balance,
|
||||||
|
UpgradeableLoaderState::buffer_len(elf.len()).unwrap(),
|
||||||
|
&bpf_loader_upgradeable::id(),
|
||||||
|
);
|
||||||
|
modified_buffer_account
|
||||||
|
.set_state(&UpgradeableLoaderState::Buffer {
|
||||||
|
authority_address: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
modified_buffer_account.data[UpgradeableLoaderState::buffer_data_offset().unwrap()..]
|
||||||
|
.copy_from_slice(&elf);
|
||||||
|
modified_buffer_account.data.truncate(5);
|
||||||
|
bank.store_account(&buffer_address, &modified_buffer_account);
|
||||||
|
bank.store_account(&program_keypair.pubkey(), &Account::default());
|
||||||
|
bank.store_account(&programdata_address, &Account::default());
|
||||||
|
let message = Message::new(
|
||||||
|
&bpf_loader_upgradeable::deploy_with_max_program_len(
|
||||||
|
&mint_keypair.pubkey(),
|
||||||
|
&program_keypair.pubkey(),
|
||||||
|
&buffer_address,
|
||||||
|
None,
|
||||||
|
min_program_balance,
|
||||||
|
elf.len(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Some(&mint_keypair.pubkey()),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
TransactionError::InstructionError(1, InstructionError::InvalidAccountData),
|
||||||
|
bank_client
|
||||||
|
.send_and_confirm_message(&[&mint_keypair, &program_keypair], message)
|
||||||
|
.unwrap_err()
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2439,7 +2490,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Case: bad elf data
|
// Test small buffer account
|
||||||
let (buffer_account, program_account, programdata_account, spill_account) = get_accounts(
|
let (buffer_account, program_account, programdata_account, spill_account) = get_accounts(
|
||||||
&buffer_address,
|
&buffer_address,
|
||||||
&programdata_address,
|
&programdata_address,
|
||||||
@ -2450,8 +2501,13 @@ mod tests {
|
|||||||
min_program_balance,
|
min_program_balance,
|
||||||
min_programdata_balance,
|
min_programdata_balance,
|
||||||
);
|
);
|
||||||
buffer_account.borrow_mut().data[UpgradeableLoaderState::buffer_data_offset().unwrap()..]
|
buffer_account
|
||||||
.copy_from_slice(&vec![0; elf_new.len()]);
|
.borrow_mut()
|
||||||
|
.set_state(&UpgradeableLoaderState::Buffer {
|
||||||
|
authority_address: None,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
buffer_account.borrow_mut().data.truncate(5);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
process_instruction(
|
process_instruction(
|
||||||
|
@ -87,7 +87,7 @@ pub enum UpgradeableLoaderInstruction {
|
|||||||
/// # Account references
|
/// # Account references
|
||||||
/// 0. [writable] The ProgramData account.
|
/// 0. [writable] The ProgramData account.
|
||||||
/// 1. [writable] The Program account.
|
/// 1. [writable] The Program account.
|
||||||
/// 2. [Writable] The Buffer account where the program data has been
|
/// 2. [writable] The Buffer account where the program data has been
|
||||||
/// written.
|
/// written.
|
||||||
/// 3. [writable] The spill account.
|
/// 3. [writable] The spill account.
|
||||||
/// 4. [] Rent sysvar.
|
/// 4. [] Rent sysvar.
|
||||||
|
Reference in New Issue
Block a user