Cap number of program address seeds (#13924)

This commit is contained in:
Jack May
2020-12-02 14:25:06 -08:00
committed by GitHub
parent 9b143f030e
commit 3f841df7cf
2 changed files with 24 additions and 8 deletions

View File

@ -24,7 +24,7 @@ use solana_sdk::{
message::Message, message::Message,
process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger}, process_instruction::{stable_log, ComputeMeter, InvokeContext, Logger},
program_error::ProgramError, program_error::ProgramError,
pubkey::{Pubkey, PubkeyError}, pubkey::{Pubkey, PubkeyError, MAX_SEEDS},
}; };
use std::{ use std::{
alloc::Layout, alloc::Layout,
@ -600,6 +600,10 @@ impl<'a> SyscallObject<BPFError> for SyscallCreateProgramAddress<'a> {
translate_slice::<&[&u8]>(memory_mapping, seeds_addr, seeds_len, self.loader_id), translate_slice::<&[&u8]>(memory_mapping, seeds_addr, seeds_len, self.loader_id),
result result
); );
if untranslated_seeds.len() > MAX_SEEDS {
*result = Ok(1);
return;
}
let seeds = question_mark!( let seeds = question_mark!(
untranslated_seeds untranslated_seeds
.iter() .iter()
@ -619,9 +623,7 @@ impl<'a> SyscallObject<BPFError> for SyscallCreateProgramAddress<'a> {
result result
); );
let new_address = match Pubkey::create_program_address(&seeds, program_id) let new_address = match Pubkey::create_program_address(&seeds, program_id) {
.map_err(SyscallError::BadSeeds)
{
Ok(address) => address, Ok(address) => address,
Err(_) => { Err(_) => {
*result = Ok(1); *result = Ok(1);
@ -921,6 +923,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedRust<'a> {
signers_seeds_len, signers_seeds_len,
self.loader_id, self.loader_id,
)?; )?;
if signers_seeds.len() > MAX_SEEDS {
return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
}
for signer_seeds in signers_seeds.iter() { for signer_seeds in signers_seeds.iter() {
let untranslated_seeds = translate_slice::<&[u8]>( let untranslated_seeds = translate_slice::<&[u8]>(
memory_mapping, memory_mapping,
@ -1170,6 +1175,9 @@ impl<'a> SyscallInvokeSigned<'a> for SyscallInvokeSignedC<'a> {
signers_seeds_len, signers_seeds_len,
self.loader_id, self.loader_id,
)?; )?;
if signers_seeds.len() > MAX_SEEDS {
return Err(SyscallError::BadSeeds(PubkeyError::MaxSeedLengthExceeded).into());
}
Ok(signers_seeds Ok(signers_seeds
.iter() .iter()
.map(|signer_seeds| { .map(|signer_seeds| {

View File

@ -3,8 +3,10 @@ use num_derive::{FromPrimitive, ToPrimitive};
use std::{convert::TryFrom, fmt, mem, str::FromStr}; use std::{convert::TryFrom, fmt, mem, str::FromStr};
use thiserror::Error; use thiserror::Error;
/// maximum length of derived pubkey seed /// maximum length of derived `Pubkey` seed
pub const MAX_SEED_LEN: usize = 32; 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)] #[derive(Error, Debug, Serialize, Clone, PartialEq, FromPrimitive, ToPrimitive)]
pub enum PubkeyError { pub enum PubkeyError {
@ -136,15 +138,21 @@ impl Pubkey {
seeds: &[&[u8]], seeds: &[&[u8]],
program_id: &Pubkey, program_id: &Pubkey,
) -> Result<Pubkey, PubkeyError> { ) -> Result<Pubkey, PubkeyError> {
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 // Perform the calculation inline, calling this from within a program is
// not supported // not supported
#[cfg(not(target_arch = "bpf"))] #[cfg(not(target_arch = "bpf"))]
{ {
let mut hasher = crate::hash::Hasher::default(); let mut hasher = crate::hash::Hasher::default();
for seed in seeds.iter() { for seed in seeds.iter() {
if seed.len() > MAX_SEED_LEN {
return Err(PubkeyError::MaxSeedLengthExceeded);
}
hasher.hash(seed); hasher.hash(seed);
} }
hasher.hashv(&[program_id.as_ref(), "ProgramDerivedAddress".as_ref()]); hasher.hashv(&[program_id.as_ref(), "ProgramDerivedAddress".as_ref()]);