use saturating arithmetic (#23435)

This commit is contained in:
Jack May
2022-03-02 14:50:16 -08:00
committed by GitHub
parent 8184f755ae
commit e9912744ef
4 changed files with 138 additions and 78 deletions

View File

@ -1,3 +1,5 @@
#![allow(clippy::integer_arithmetic)]
use { use {
crate::alloc, crate::alloc,
alloc::{Alloc, AllocErr}, alloc::{Alloc, AllocErr},

View File

@ -1,4 +1,3 @@
#![allow(clippy::integer_arithmetic)]
pub mod alloc; pub mod alloc;
pub mod allocator_bump; pub mod allocator_bump;
pub mod deprecated; pub mod deprecated;
@ -192,16 +191,17 @@ fn write_program_data<'a>(
log_collector: Option<Rc<RefCell<LogCollector>>>, log_collector: Option<Rc<RefCell<LogCollector>>>,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let data = program.get_data_mut(); let data = program.get_data_mut();
if data.len() < program_data_offset + bytes.len() { let write_offset = program_data_offset.saturating_add(bytes.len());
if data.len() < write_offset {
ic_logger_msg!( ic_logger_msg!(
log_collector, log_collector,
"Write overflow: {} < {}", "Write overflow: {} < {}",
data.len(), data.len(),
program_data_offset + bytes.len() write_offset
); );
return Err(InstructionError::AccountDataTooSmall); return Err(InstructionError::AccountDataTooSmall);
} }
data[program_data_offset..program_data_offset + bytes.len()].copy_from_slice(bytes); data[program_data_offset..write_offset].copy_from_slice(bytes);
Ok(()) Ok(())
} }
@ -224,10 +224,11 @@ pub fn create_vm<'a, 'b>(
.feature_set .feature_set
.is_active(&requestable_heap_size::id()) .is_active(&requestable_heap_size::id())
{ {
let _ = invoke_context let _ = invoke_context.get_compute_meter().borrow_mut().consume(
.get_compute_meter() ((heap_size as u64).saturating_div(32_u64.saturating_mul(1024)))
.borrow_mut() .saturating_sub(1)
.consume((heap_size as u64 / (32 * 1024)).saturating_sub(1) * compute_budget.heap_cost); .saturating_mul(compute_budget.heap_cost),
);
} }
let mut heap = let mut heap =
AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN); AlignedMemory::new_with_size(compute_budget.heap_size.unwrap_or(HEAP_LENGTH), HOST_ALIGN);
@ -276,7 +277,7 @@ fn process_instruction_common(
instruction_context.get_index_in_transaction(first_instruction_account)?, instruction_context.get_index_in_transaction(first_instruction_account)?,
)?; )?;
let second_account_key = instruction_context let second_account_key = instruction_context
.get_index_in_transaction(first_instruction_account + 1) .get_index_in_transaction(first_instruction_account.saturating_add(1))
.and_then(|index_in_transaction| { .and_then(|index_in_transaction| {
transaction_context.get_key_of_account_at_index(index_in_transaction) transaction_context.get_key_of_account_at_index(index_in_transaction)
}); });
@ -287,7 +288,7 @@ fn process_instruction_common(
.map(|key| key == program_id) .map(|key| key == program_id)
.unwrap_or(false) .unwrap_or(false)
{ {
first_instruction_account + 1 first_instruction_account.saturating_add(1)
} else { } else {
if instruction_context if instruction_context
.try_borrow_account(transaction_context, first_instruction_account)? .try_borrow_account(transaction_context, first_instruction_account)?
@ -302,9 +303,11 @@ fn process_instruction_common(
let program = let program =
instruction_context.try_borrow_account(transaction_context, program_account_index)?; instruction_context.try_borrow_account(transaction_context, program_account_index)?;
if program.is_executable() { if program.is_executable() {
// First instruction account can only be zero if called from CPI, which
// means stack height better be greater than one
debug_assert_eq!( debug_assert_eq!(
first_instruction_account, first_instruction_account == 0,
1 - (invoke_context.get_stack_height() > 1) as usize, invoke_context.get_stack_height() > 1
); );
if !check_loader_id(program.get_owner()) { if !check_loader_id(program.get_owner()) {
@ -507,8 +510,9 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::Write::Authority as usize, .get_number_of_program_accounts()
.saturating_add(upgradeable_ins_acc_idx::Write::Authority as usize),
)? { )? {
ic_logger_msg!(log_collector, "Buffer authority did not sign"); ic_logger_msg!(log_collector, "Buffer authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -519,7 +523,7 @@ fn process_loader_upgradeable_instruction(
)?; )?;
write_program_data( write_program_data(
&mut program, &mut program,
UpgradeableLoaderState::buffer_data_offset()? + offset as usize, UpgradeableLoaderState::buffer_data_offset()?.saturating_add(offset as usize),
&bytes, &bytes,
invoke_context.get_log_collector(), invoke_context.get_log_collector(),
)?; )?;
@ -582,8 +586,12 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::DeployWithMaxDataLen::UpgradeAuthority as usize, .get_number_of_program_accounts()
.saturating_add(
upgradeable_ins_acc_idx::DeployWithMaxDataLen::UpgradeAuthority
as usize,
),
)? { )? {
ic_logger_msg!(log_collector, "Upgrade authority did not sign"); ic_logger_msg!(log_collector, "Upgrade authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -662,7 +670,7 @@ fn process_loader_upgradeable_instruction(
// Load and verify the program bits // Load and verify the program bits
let executor = create_executor( let executor = create_executor(
first_instruction_account + 3, first_instruction_account.saturating_add(3),
buffer_data_offset, buffer_data_offset,
invoke_context, invoke_context,
use_jit, use_jit,
@ -687,8 +695,8 @@ fn process_loader_upgradeable_instruction(
slot: clock.slot, slot: clock.slot,
upgrade_authority_address, upgrade_authority_address,
})?; })?;
programdata.get_data_mut() programdata.get_data_mut()[programdata_data_offset
[programdata_data_offset..programdata_data_offset + buffer_data_len] ..programdata_data_offset.saturating_add(buffer_data_len)]
.copy_from_slice(&buffer.get_data()[buffer_data_offset..]); .copy_from_slice(&buffer.get_data()[buffer_data_offset..]);
} }
@ -783,8 +791,11 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::Upgrade::UpgradeAuthority as usize, .get_number_of_program_accounts()
.saturating_add(
upgradeable_ins_acc_idx::Upgrade::UpgradeAuthority as usize,
),
)? { )? {
ic_logger_msg!(log_collector, "Upgrade authority did not sign"); ic_logger_msg!(log_collector, "Upgrade authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -817,7 +828,11 @@ fn process_loader_upgradeable_instruction(
ic_logger_msg!(log_collector, "ProgramData account not large enough"); ic_logger_msg!(log_collector, "ProgramData account not large enough");
return Err(InstructionError::AccountDataTooSmall); return Err(InstructionError::AccountDataTooSmall);
} }
if programdata.get_lamports() + buffer.get_lamports() < programdata_balance_required { if programdata
.get_lamports()
.saturating_add(buffer.get_lamports())
< programdata_balance_required
{
ic_logger_msg!( ic_logger_msg!(
log_collector, log_collector,
"Buffer account balance too low to fund upgrade" "Buffer account balance too low to fund upgrade"
@ -839,8 +854,11 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::Upgrade::UpgradeAuthority as usize, .get_number_of_program_accounts()
.saturating_add(
upgradeable_ins_acc_idx::Upgrade::UpgradeAuthority as usize,
),
)? { )? {
ic_logger_msg!(log_collector, "Upgrade authority did not sign"); ic_logger_msg!(log_collector, "Upgrade authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -853,7 +871,7 @@ fn process_loader_upgradeable_instruction(
// Load and verify the program bits // Load and verify the program bits
let executor = create_executor( let executor = create_executor(
first_instruction_account + 2, first_instruction_account.saturating_add(2),
buffer_data_offset, buffer_data_offset,
invoke_context, invoke_context,
use_jit, use_jit,
@ -878,9 +896,10 @@ fn process_loader_upgradeable_instruction(
upgrade_authority_address: current_upgrade_authority_address, upgrade_authority_address: current_upgrade_authority_address,
})?; })?;
programdata.get_data_mut() programdata.get_data_mut()
[programdata_data_offset..programdata_data_offset + buffer_data_len] [programdata_data_offset..programdata_data_offset.saturating_add(buffer_data_len)]
.copy_from_slice(&buffer.get_data()[buffer_data_offset..]); .copy_from_slice(&buffer.get_data()[buffer_data_offset..]);
programdata.get_data_mut()[programdata_data_offset + buffer_data_len..].fill(0); programdata.get_data_mut()[programdata_data_offset.saturating_add(buffer_data_len)..]
.fill(0);
// Fund ProgramData to rent-exemption, spill the rest // Fund ProgramData to rent-exemption, spill the rest
{ {
@ -889,8 +908,10 @@ fn process_loader_upgradeable_instruction(
upgradeable_ins_acc_idx::Upgrade::Spill as usize, upgradeable_ins_acc_idx::Upgrade::Spill as usize,
)?; )?;
spill.checked_add_lamports( spill.checked_add_lamports(
(programdata.get_lamports() + buffer.get_lamports()) (programdata
.saturating_sub(programdata_balance_required), .get_lamports()
.saturating_add(buffer.get_lamports()))
.saturating_sub(programdata_balance_required),
)?; )?;
buffer.set_lamports(0); buffer.set_lamports(0);
programdata.set_lamports(programdata_balance_required); programdata.set_lamports(programdata_balance_required);
@ -931,8 +952,11 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::SetAuthority::CurrentAuthority as usize, .get_number_of_program_accounts()
.saturating_add(
upgradeable_ins_acc_idx::SetAuthority::CurrentAuthority as usize,
),
)? { )? {
ic_logger_msg!(log_collector, "Buffer authority did not sign"); ic_logger_msg!(log_collector, "Buffer authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -954,8 +978,11 @@ fn process_loader_upgradeable_instruction(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::SetAuthority::CurrentAuthority as usize, .get_number_of_program_accounts()
.saturating_add(
upgradeable_ins_acc_idx::SetAuthority::CurrentAuthority as usize,
),
)? { )? {
ic_logger_msg!(log_collector, "Upgrade authority did not sign"); ic_logger_msg!(log_collector, "Upgrade authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -976,9 +1003,11 @@ fn process_loader_upgradeable_instruction(
UpgradeableLoaderInstruction::Close => { UpgradeableLoaderInstruction::Close => {
instruction_context.check_number_of_instruction_accounts(2)?; instruction_context.check_number_of_instruction_accounts(2)?;
if instruction_context.get_index_in_transaction( if instruction_context.get_index_in_transaction(
first_instruction_account + upgradeable_ins_acc_idx::Close::Account as usize, first_instruction_account
.saturating_add(upgradeable_ins_acc_idx::Close::Account as usize),
)? == instruction_context.get_index_in_transaction( )? == instruction_context.get_index_in_transaction(
first_instruction_account + upgradeable_ins_acc_idx::Close::Recipient as usize, first_instruction_account
.saturating_add(upgradeable_ins_acc_idx::Close::Recipient as usize),
)? { )? {
ic_logger_msg!( ic_logger_msg!(
log_collector, log_collector,
@ -1029,8 +1058,9 @@ fn process_loader_upgradeable_instruction(
} => { } => {
instruction_context.check_number_of_instruction_accounts(4)?; instruction_context.check_number_of_instruction_accounts(4)?;
if !instruction_context.is_writable( if !instruction_context.is_writable(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::Close::Program as usize, .get_number_of_program_accounts()
.saturating_add(upgradeable_ins_acc_idx::Close::Program as usize),
)? { )? {
ic_logger_msg!(log_collector, "Program account is not writable"); ic_logger_msg!(log_collector, "Program account is not writable");
return Err(InstructionError::InvalidArgument); return Err(InstructionError::InvalidArgument);
@ -1105,8 +1135,9 @@ fn common_close_account(
return Err(InstructionError::IncorrectAuthority); return Err(InstructionError::IncorrectAuthority);
} }
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ upgradeable_ins_acc_idx::Close::Authority as usize, .get_number_of_program_accounts()
.saturating_add(upgradeable_ins_acc_idx::Close::Authority as usize),
)? { )? {
ic_logger_msg!(log_collector, "Authority did not sign"); ic_logger_msg!(log_collector, "Authority did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -1158,8 +1189,9 @@ fn process_loader_instruction(
match limited_deserialize(instruction_data)? { match limited_deserialize(instruction_data)? {
LoaderInstruction::Write { offset, bytes } => { LoaderInstruction::Write { offset, bytes } => {
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ deprecated_ins_acc_idx::Write::Program as usize, .get_number_of_program_accounts()
.saturating_add(deprecated_ins_acc_idx::Write::Program as usize),
)? { )? {
ic_msg!(invoke_context, "Program account did not sign"); ic_msg!(invoke_context, "Program account did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -1176,8 +1208,9 @@ fn process_loader_instruction(
} }
LoaderInstruction::Finalize => { LoaderInstruction::Finalize => {
if !instruction_context.is_signer( if !instruction_context.is_signer(
instruction_context.get_number_of_program_accounts() instruction_context
+ deprecated_ins_acc_idx::Finalize::Program as usize, .get_number_of_program_accounts()
.saturating_add(deprecated_ins_acc_idx::Finalize::Program as usize),
)? { )? {
ic_msg!(invoke_context, "Program account did not sign"); ic_msg!(invoke_context, "Program account did not sign");
return Err(InstructionError::MissingRequiredSignature); return Err(InstructionError::MissingRequiredSignature);
@ -1281,7 +1314,7 @@ impl Executor for BpfExecutor {
log_collector, log_collector,
"Program {} consumed {} of {} compute units", "Program {} consumed {} of {} compute units",
&program_id, &program_id,
before - after, before.saturating_sub(after),
before before
); );
if log_enabled!(Trace) { if log_enabled!(Trace) {

View File

@ -1,3 +1,5 @@
#![allow(clippy::integer_arithmetic)]
use { use {
byteorder::{ByteOrder, LittleEndian, WriteBytesExt}, byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
solana_rbpf::{aligned_memory::AlignedMemory, ebpf::HOST_ALIGN}, solana_rbpf::{aligned_memory::AlignedMemory, ebpf::HOST_ALIGN},

View File

@ -1037,7 +1037,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallTryFindProgramAddress<'a, 'b> {
return; return;
} }
} }
bump_seed[0] -= 1; bump_seed[0] = bump_seed[0].saturating_sub(1);
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
} }
*result = Ok(1); *result = Ok(1);
@ -1115,10 +1115,12 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallSha256<'a, 'b> {
compute_budget.mem_op_base_cost.max( compute_budget.mem_op_base_cost.max(
compute_budget compute_budget
.sha256_byte_cost .sha256_byte_cost
.saturating_mul(val.len() as u64 / 2), .saturating_mul((val.len() as u64).saturating_div(2)),
) )
} else { } else {
compute_budget.sha256_byte_cost * (val.len() as u64 / 2) compute_budget
.sha256_byte_cost
.saturating_mul((val.len() as u64).saturating_div(2))
}; };
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
hasher.hash(bytes); hasher.hash(bytes);
@ -1136,9 +1138,12 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
memory_mapping: &MemoryMapping, memory_mapping: &MemoryMapping,
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<u64, EbpfError<BpfError>> { ) -> Result<u64, EbpfError<BpfError>> {
invoke_context invoke_context.get_compute_meter().consume(
.get_compute_meter() invoke_context
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?; .get_compute_budget()
.sysvar_base_cost
.saturating_add(size_of::<T>() as u64),
)?;
let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?; let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?;
let sysvar: Arc<T> = sysvar.map_err(SyscallError::InstructionError)?; let sysvar: Arc<T> = sysvar.map_err(SyscallError::InstructionError)?;
@ -1349,10 +1354,12 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallKeccak256<'a, 'b> {
compute_budget.mem_op_base_cost.max( compute_budget.mem_op_base_cost.max(
compute_budget compute_budget
.sha256_byte_cost .sha256_byte_cost
.saturating_mul(val.len() as u64 / 2), .saturating_mul((val.len() as u64).saturating_div(2)),
) )
} else { } else {
compute_budget.sha256_byte_cost * (val.len() as u64 / 2) compute_budget
.sha256_byte_cost
.saturating_mul((val.len() as u64).saturating_div(2))
}; };
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
hasher.hash(bytes); hasher.hash(bytes);
@ -1366,8 +1373,8 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallKeccak256<'a, 'b> {
/// This function is incorrect due to arithmetic overflow and only exists for /// This function is incorrect due to arithmetic overflow and only exists for
/// backwards compatibility. Instead use program_stubs::is_nonoverlapping. /// backwards compatibility. Instead use program_stubs::is_nonoverlapping.
fn check_overlapping_do_not_use(src_addr: u64, dst_addr: u64, n: u64) -> bool { fn check_overlapping_do_not_use(src_addr: u64, dst_addr: u64, n: u64) -> bool {
(src_addr <= dst_addr && src_addr + n > dst_addr) (src_addr <= dst_addr && src_addr.saturating_add(n) > dst_addr)
|| (dst_addr <= src_addr && dst_addr + n > src_addr) || (dst_addr <= src_addr && dst_addr.saturating_add(n) > src_addr)
} }
fn mem_op_consume<'a, 'b>( fn mem_op_consume<'a, 'b>(
@ -1381,9 +1388,9 @@ fn mem_op_consume<'a, 'b>(
{ {
compute_budget compute_budget
.mem_op_base_cost .mem_op_base_cost
.max(n / compute_budget.cpi_bytes_per_unit) .max(n.saturating_div(compute_budget.cpi_bytes_per_unit))
} else { } else {
n / compute_budget.cpi_bytes_per_unit n.saturating_div(compute_budget.cpi_bytes_per_unit)
}; };
invoke_context.get_compute_meter().consume(cost) invoke_context.get_compute_meter().consume(cost)
} }
@ -1417,7 +1424,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallMemcpy<'a, 'b> {
if update_syscall_base_costs { if update_syscall_base_costs {
let cost = compute_budget let cost = compute_budget
.mem_op_base_cost .mem_op_base_cost
.max(n / compute_budget.cpi_bytes_per_unit); .max(n.saturating_div(compute_budget.cpi_bytes_per_unit));
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
} }
@ -1439,7 +1446,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallMemcpy<'a, 'b> {
} }
if !update_syscall_base_costs { if !update_syscall_base_costs {
let cost = n / compute_budget.cpi_bytes_per_unit; let cost = n.saturating_div(compute_budget.cpi_bytes_per_unit);
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
}; };
@ -1537,11 +1544,11 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallMemcmp<'a, 'b> {
let a = s1[i]; let a = s1[i];
let b = s2[i]; let b = s2[i];
if a != b { if a != b {
*cmp_result = a as i32 - b as i32; *cmp_result = (a as i32).saturating_sub(b as i32);
*result = Ok(0); *result = Ok(0);
return; return;
} }
i += 1; i = i.saturating_add(1);
} }
*cmp_result = 0; *cmp_result = 0;
*result = Ok(0); *result = Ok(0);
@ -1924,10 +1931,12 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallBlake3<'a, 'b> {
compute_budget.mem_op_base_cost.max( compute_budget.mem_op_base_cost.max(
compute_budget compute_budget
.sha256_byte_cost .sha256_byte_cost
.saturating_mul(val.len() as u64 / 2), .saturating_mul((val.len() as u64).saturating_div(2)),
) )
} else { } else {
compute_budget.sha256_byte_cost * (val.len() as u64 / 2) compute_budget
.sha256_byte_cost
.saturating_mul((val.len() as u64).saturating_div(2))
}; };
question_mark!(invoke_context.get_compute_meter().consume(cost), result); question_mark!(invoke_context.get_compute_meter().consume(cost), result);
hasher.hash(bytes); hasher.hash(bytes);
@ -2082,7 +2091,8 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
)?; )?;
invoke_context.get_compute_meter().consume( invoke_context.get_compute_meter().consume(
data.len() as u64 / invoke_context.get_compute_budget().cpi_bytes_per_unit, (data.len() as u64)
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
)?; )?;
let translated = translate( let translated = translate(
@ -2352,7 +2362,9 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
let vm_data_addr = account_info.data_addr; let vm_data_addr = account_info.data_addr;
invoke_context.get_compute_meter().consume( invoke_context.get_compute_meter().consume(
account_info.data_len / invoke_context.get_compute_budget().cpi_bytes_per_unit, account_info
.data_len
.saturating_div(invoke_context.get_compute_budget().cpi_bytes_per_unit),
)?; )?;
let data = translate_slice_mut::<u8>( let data = translate_slice_mut::<u8>(
@ -2364,7 +2376,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
let first_info_addr = &account_infos[0] as *const _ as u64; let first_info_addr = &account_infos[0] as *const _ as u64;
let addr = &account_info.data_len as *const u64 as u64; let addr = &account_info.data_len as *const u64 as u64;
let vm_addr = account_infos_addr + (addr - first_info_addr); let vm_addr = account_infos_addr.saturating_add(addr.saturating_sub(first_info_addr));
let _ = translate( let _ = translate(
memory_mapping, memory_mapping,
AccessType::Store, AccessType::Store,
@ -2580,7 +2592,9 @@ fn check_account_infos(
len: usize, len: usize,
invoke_context: &mut InvokeContext, invoke_context: &mut InvokeContext,
) -> Result<(), EbpfError<BpfError>> { ) -> Result<(), EbpfError<BpfError>> {
if len * size_of::<Pubkey>() > invoke_context.get_compute_budget().max_cpi_instruction_size { if len.saturating_mul(size_of::<Pubkey>())
> invoke_context.get_compute_budget().max_cpi_instruction_size
{
// Cap the number of account_infos a caller can pass to approximate // Cap the number of account_infos a caller can pass to approximate
// maximum that accounts that could be passed in an instruction // maximum that accounts that could be passed in an instruction
return Err(SyscallError::TooManyAccounts.into()); return Err(SyscallError::TooManyAccounts.into());
@ -2710,9 +2724,16 @@ fn call<'a, 'b: 'a>(
); );
} }
let data_overflow = if do_support_realloc { let data_overflow = if do_support_realloc {
new_len > caller_account.original_data_len + MAX_PERMITTED_DATA_INCREASE new_len
> caller_account
.original_data_len
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
} else { } else {
new_len > caller_account.data.len() + MAX_PERMITTED_DATA_INCREASE new_len
> caller_account
.data
.len()
.saturating_add(MAX_PERMITTED_DATA_INCREASE)
}; };
if data_overflow { if data_overflow {
ic_msg!( ic_msg!(
@ -2770,9 +2791,10 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallSetReturnData<'a, 'b> {
let budget = invoke_context.get_compute_budget(); let budget = invoke_context.get_compute_budget();
question_mark!( question_mark!(
invoke_context invoke_context.get_compute_meter().consume(
.get_compute_meter() len.saturating_div(budget.cpi_bytes_per_unit)
.consume(len / budget.cpi_bytes_per_unit + budget.syscall_base_cost), .saturating_add(budget.syscall_base_cost)
),
result result
); );
@ -2845,9 +2867,10 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetReturnData<'a, 'b> {
length = length.min(return_data.len() as u64); length = length.min(return_data.len() as u64);
if length != 0 { if length != 0 {
question_mark!( question_mark!(
invoke_context invoke_context.get_compute_meter().consume(
.get_compute_meter() (length.saturating_add(size_of::<Pubkey>() as u64))
.consume((length + size_of::<Pubkey>() as u64) / budget.cpi_bytes_per_unit), .saturating_div(budget.cpi_bytes_per_unit)
),
result result
); );
@ -2994,7 +3017,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetProcessedSiblingInstruction<'
if index == current_index { if index == current_index {
return true; return true;
} else { } else {
current_index += 1; current_index = current_index.saturating_add(1);
} }
} }
false false
@ -4190,7 +4213,7 @@ mod tests {
MemoryRegion { MemoryRegion {
host_addr: mock_slices.as_ptr() as u64, host_addr: mock_slices.as_ptr() as u64,
vm_addr: SEEDS_VA, vm_addr: SEEDS_VA,
len: (seeds.len() * size_of::<MockSlice>()) as u64, len: (seeds.len().saturating_mul(size_of::<MockSlice>()) as u64),
vm_gap_shift: 63, vm_gap_shift: 63,
is_writable: false, is_writable: false,
}, },
@ -4218,7 +4241,7 @@ mod tests {
]; ];
for (i, seed) in seeds.iter().enumerate() { for (i, seed) in seeds.iter().enumerate() {
let vm_addr = SEED_VA + (i as u64 * 0x100000000); let vm_addr = SEED_VA.saturating_add((i as u64).saturating_mul(0x100000000));
let mock_slice = MockSlice { let mock_slice = MockSlice {
vm_addr, vm_addr,
len: seed.len(), len: seed.len(),