From 9dd5d4407bc1fbfa78feba57a467919ee03c4391 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Thu, 21 Jan 2021 02:37:50 +0000 Subject: [PATCH] Sanitize base58 pubkeys and sigs (bp #14708) (#14711) * SDK: Sanitize base58 pubkey input (cherry picked from commit 250b3969d4f5ce154c4e84885687b6670162b480) * SDK: Sanitize base58 signature input (cherry picked from commit 2783aee4839cad19f5c77a40bac498a071930f45) Co-authored-by: Trent Nelson --- sdk/program/src/pubkey.rs | 12 ++++++++++++ sdk/src/signature.rs | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/sdk/program/src/pubkey.rs b/sdk/program/src/pubkey.rs index a65928d1b7..3eb1c33976 100644 --- a/sdk/program/src/pubkey.rs +++ b/sdk/program/src/pubkey.rs @@ -9,6 +9,8 @@ pub const PUBKEY_BYTES: usize = 32; pub const MAX_SEED_LEN: usize = 32; /// Maximum number of seeds pub const MAX_SEEDS: usize = 16; +/// Maximum string length of a base58 encoded pubkey +const MAX_BASE58_LEN: usize = 44; #[derive(Error, Debug, Serialize, Clone, PartialEq, FromPrimitive, ToPrimitive)] pub enum PubkeyError { @@ -58,6 +60,9 @@ impl FromStr for Pubkey { type Err = ParsePubkeyError; fn from_str(s: &str) -> Result { + if s.len() > MAX_BASE58_LEN { + return Err(ParsePubkeyError::WrongSize); + } let pubkey_vec = bs58::decode(s) .into_vec() .map_err(|_| ParsePubkeyError::Invalid)?; @@ -336,6 +341,13 @@ mod tests { pubkey_base58_str.parse::(), Err(ParsePubkeyError::Invalid) ); + + // too long input string + // longest valid encoding + let mut too_long = bs58::encode(&[255u8; PUBKEY_BYTES]).into_string(); + // and one to grow on + too_long.push('1'); + assert_eq!(too_long.parse::(), Err(ParsePubkeyError::WrongSize)); } #[test] diff --git a/sdk/src/signature.rs b/sdk/src/signature.rs index 278e2ca65d..19d01a4ff4 100644 --- a/sdk/src/signature.rs +++ b/sdk/src/signature.rs @@ -58,6 +58,11 @@ impl Keypair { } } +/// Number of bytes in a signature +pub const SIGNATURE_BYTES: usize = 64; +/// Maximum string length of a base58 encoded signature +const MAX_BASE58_SIGNATURE_LEN: usize = 88; + #[repr(transparent)] #[derive( Serialize, Deserialize, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash, AbiExample, @@ -138,6 +143,9 @@ impl FromStr for Signature { type Err = ParseSignatureError; fn from_str(s: &str) -> Result { + if s.len() > MAX_BASE58_SIGNATURE_LEN { + return Err(ParseSignatureError::WrongSize); + } let bytes = bs58::decode(s) .into_vec() .map_err(|_| ParseSignatureError::Invalid)?; @@ -521,6 +529,21 @@ mod tests { signature_base58_str.parse::(), Err(ParseSignatureError::Invalid) ); + + // too long input string + // longest valid encoding + let mut too_long: GenericArray = GenericArray::default(); + // *sigh* + for i in &mut too_long { + *i = 255u8; + } + let mut too_long = bs58::encode(too_long).into_string(); + // and one to grow on + too_long.push('1'); + assert_eq!( + too_long.parse::(), + Err(ParseSignatureError::WrongSize) + ); } #[test]