diff --git a/token/js/client/token.js b/token/js/client/token.js index 220c10cbb14..1e4918f2585 100644 --- a/token/js/client/token.js +++ b/token/js/client/token.js @@ -133,7 +133,8 @@ const AccountInfoLayout = BufferLayout.struct([ Layout.publicKey('token'), Layout.publicKey('owner'), Layout.uint64('amount'), - BufferLayout.nu64('option'), + BufferLayout.u32('option'), + BufferLayout.u32('padding'), Layout.publicKey('source'), Layout.uint64('originalAmount'), ]); diff --git a/token/src/instruction.rs b/token/src/instruction.rs index 17f57320ee3..7f5dfbc4b7c 100644 --- a/token/src/instruction.rs +++ b/token/src/instruction.rs @@ -89,33 +89,48 @@ pub enum TokenInstruction { impl TokenInstruction { /// Deserializes a byte buffer into an [TokenInstruction](enum.TokenInstruction.html) pub fn deserialize(input: &[u8]) -> Result { - if input.len() < size_of::() { + if input.len() < size_of::() { return Err(ProgramError::InvalidAccountData); } Ok(match input[0] { 0 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let info: &TokenInfo = unsafe { &*(&input[1] as *const u8 as *const TokenInfo) }; Self::NewToken(*info) } 1 => Self::NewAccount, 2 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let amount: &u64 = unsafe { &*(&input[1] as *const u8 as *const u64) }; Self::Transfer(*amount) } 3 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let amount: &u64 = unsafe { &*(&input[1] as *const u8 as *const u64) }; Self::Approve(*amount) } 4 => Self::SetOwner, 5 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let amount: &u64 = unsafe { &*(&input[1] as *const u8 as *const u64) }; Self::MintTo(*amount) } 6 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let amount: &u64 = unsafe { &*(&input[1] as *const u8 as *const u64) }; Self::Burn(*amount) diff --git a/token/src/state.rs b/token/src/state.rs index c47dc56603d..30fa47d4dc6 100644 --- a/token/src/state.rs +++ b/token/src/state.rs @@ -468,17 +468,23 @@ impl<'a> State { /// Deserializes a byte buffer into a Token Program [State](struct.State.html) pub fn deserialize(input: &'a [u8]) -> Result { - if input.len() < size_of::() { + if input.len() < size_of::() { return Err(ProgramError::InvalidAccountData); } Ok(match input[0] { 0 => Self::Unallocated, 1 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let token: &Token = unsafe { &*(&input[1] as *const u8 as *const Token) }; Self::Token(*token) } 2 => { + if input.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } #[allow(clippy::cast_ptr_alignment)] let account: &Account = unsafe { &*(&input[1] as *const u8 as *const Account) }; Self::Account(*account) @@ -490,18 +496,24 @@ impl<'a> State { /// Serializes Token Program [State](struct.State.html) into a byte buffer pub fn serialize(self: &Self, output: &mut [u8]) -> ProgramResult { - if output.len() < size_of::() { + if output.len() < size_of::() { return Err(ProgramError::InvalidAccountData); } match self { Self::Unallocated => output[0] = 0, Self::Token(token) => { + if output.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } output[0] = 1; #[allow(clippy::cast_ptr_alignment)] let value = unsafe { &mut *(&mut output[1] as *mut u8 as *mut Token) }; *value = *token; } Self::Account(account) => { + if output.len() < size_of::() + size_of::() { + return Err(ProgramError::InvalidAccountData); + } output[0] = 2; #[allow(clippy::cast_ptr_alignment)] let value = unsafe { &mut *(&mut output[1] as *mut u8 as *mut Account) };