diff --git a/programs/bpf_loader/src/syscalls.rs b/programs/bpf_loader/src/syscalls.rs index 75e26e5c94091e..b52d6a665b3aaa 100644 --- a/programs/bpf_loader/src/syscalls.rs +++ b/programs/bpf_loader/src/syscalls.rs @@ -23,7 +23,7 @@ use solana_sdk::{ message::Message, process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger}, program_error::ProgramError, - pubkey::{Pubkey, PubkeyError}, + pubkey::{Pubkey, PubkeyError, MAX_SEEDS}, }; use std::{ alloc::Layout, @@ -534,6 +534,9 @@ impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { // TODO need ref? let untranslated_seeds = translate_slice!(&[&u8], seeds_addr, seeds_len, ro_regions, self.loader_id)?; + if untranslated_seeds.len() > MAX_SEEDS { + return Ok(1); + } let seeds = untranslated_seeds .iter() .map(|untranslated_seed| { @@ -548,9 +551,7 @@ impl<'a> SyscallObject for SyscallCreateProgramAddress<'a> { .collect::, EbpfError>>()?; let program_id = translate_type!(Pubkey, program_id_addr, ro_regions, self.loader_id)?; - let new_address = match Pubkey::create_program_address(&seeds, program_id) - .map_err(SyscallError::BadSeeds) - { + let new_address = match Pubkey::create_program_address(&seeds, program_id) { Ok(address) => address, Err(_) => return Ok(1), }; @@ -828,6 +829,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> { ro_regions, self.loader_id )?; + if signers_seeds.len() > MAX_SEEDS { + return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into()); + } for signer_seeds in signers_seeds.iter() { let untranslated_seeds = translate_slice!( &[u8], @@ -1081,6 +1085,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> { ro_regions, self.loader_id )?; + if signers_seeds.len() > MAX_SEEDS { + return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into()); + } Ok(signers_seeds .iter() .map(|signer_seeds| { diff --git a/sdk/program/src/pubkey.rs b/sdk/program/src/pubkey.rs index af7c73903678d0..50597839f861b3 100644 --- a/sdk/program/src/pubkey.rs +++ b/sdk/program/src/pubkey.rs @@ -3,8 +3,10 @@ use num_derive::{FromPrimitive, ToPrimitive}; use std::{convert::TryFrom, fmt, mem, str::FromStr}; use thiserror::Error; -/// maximum length of derived pubkey seed +/// maximum length of derived `Pubkey` seed pub const MAX_SEED_LEN: usize = 32; +/// Maximum number of seeds +pub const MAX_SEEDS: usize = 16; #[derive(Error, Debug, Serialize, Clone, PartialEq, FromPrimitive, ToPrimitive)] pub enum PubkeyError { @@ -136,15 +138,21 @@ impl Pubkey { seeds: &[&[u8]], program_id: &Pubkey, ) -> Result { + if seeds.len() > MAX_SEEDS { + return Err(PubkeyError::MaxSeedLengthExceeded); + } + for seed in seeds.iter() { + if seed.len() > MAX_SEED_LEN { + return Err(PubkeyError::MaxSeedLengthExceeded); + } + } + // Perform the calculation inline, calling this from within a program is // not supported #[cfg(not(target_arch = "bpf"))] { let mut hasher = crate::hash::Hasher::default(); for seed in seeds.iter() { - if seed.len() > MAX_SEED_LEN { - return Err(PubkeyError::MaxSeedLengthExceeded); - } hasher.hash(seed); } hasher.hashv(&[program_id.as_ref(), "ProgramDerivedAddress".as_ref()]);