diff --git a/token/program/src/instruction.rs b/token/program/src/instruction.rs index c69c7bbe2eb..7e70b808835 100644 --- a/token/program/src/instruction.rs +++ b/token/program/src/instruction.rs @@ -519,6 +519,9 @@ impl<'a> TokenInstruction<'a> { 10 => Self::FreezeAccount, 11 => Self::ThawAccount, 12 => { + if rest.len() < 8 { + return Err(TokenError::InvalidInstruction.into()); + } let (amount, rest) = rest.split_at(8); let amount = amount .try_into() @@ -530,6 +533,9 @@ impl<'a> TokenInstruction<'a> { Self::TransferChecked { amount, decimals } } 13 => { + if rest.len() < 8 { + return Err(TokenError::InvalidInstruction.into()); + } let (amount, rest) = rest.split_at(8); let amount = amount .try_into() @@ -541,6 +547,9 @@ impl<'a> TokenInstruction<'a> { Self::ApproveChecked { amount, decimals } } 14 => { + if rest.len() < 8 { + return Err(TokenError::InvalidInstruction.into()); + } let (amount, rest) = rest.split_at(8); let amount = amount .try_into() @@ -552,6 +561,9 @@ impl<'a> TokenInstruction<'a> { Self::MintToChecked { amount, decimals } } 15 => { + if rest.len() < 8 { + return Err(TokenError::InvalidInstruction.into()); + } let (amount, rest) = rest.split_at(8); let amount = amount .try_into() @@ -588,6 +600,9 @@ impl<'a> TokenInstruction<'a> { 21 => Self::GetAccountDataSize, 22 => Self::InitializeImmutableOwner, 23 => { + if rest.len() < 8 { + return Err(TokenError::InvalidInstruction.into()); + } let (amount, _rest) = rest.split_at(8); let amount = amount .try_into() @@ -1689,4 +1704,12 @@ mod test { let unpacked = TokenInstruction::unpack(&expect).unwrap(); assert_eq!(unpacked, check); } + + #[test] + fn test_instruction_unpack_panic() { + for i in 0..255u8 { + let expect = Vec::from([i, 1, 0, 0, 0, 0, 0, 0, 0, 2]); + _ = TokenInstruction::unpack(&expect[0..2]); + } + } }