diff --git a/client/src/chain_data_fetcher.rs b/client/src/chain_data_fetcher.rs index 0749d4837..26f7f8221 100644 --- a/client/src/chain_data_fetcher.rs +++ b/client/src/chain_data_fetcher.rs @@ -38,6 +38,13 @@ impl AccountFetcher { let acc = self.fetch_raw(address)?; let data = acc.data(); + if data.len() < 8 { + anyhow::bail!( + "account at {} has only {} bytes of data", + address, + data.len() + ); + } let disc_bytes = &data[0..8]; if disc_bytes != MangoAccount::discriminator() { anyhow::bail!("not a mango account at {}", address); diff --git a/liquidator/src/util.rs b/liquidator/src/util.rs index 95b87abc5..880562ca2 100644 --- a/liquidator/src/util.rs +++ b/liquidator/src/util.rs @@ -12,7 +12,7 @@ pub fn is_mango_account<'a>( group_id: &Pubkey, ) -> Option> { let data = account.data(); - if account.owner() != program_id || data.is_empty() { + if account.owner() != program_id || data.len() < 8 { return None; } @@ -37,7 +37,7 @@ pub fn is_mango_bank<'a>( group_id: &Pubkey, ) -> Option<&'a Bank> { let data = account.data(); - if account.owner() != program_id || data.is_empty() { + if account.owner() != program_id || data.len() < 8 { return None; } @@ -61,7 +61,7 @@ pub fn is_mint_info<'a>( group_id: &Pubkey, ) -> Option<&'a MintInfo> { let data = account.data(); - if account.owner() != program_id || data.is_empty() { + if account.owner() != program_id || data.len() < 8 { return None; } @@ -85,7 +85,7 @@ pub fn is_perp_market<'a>( group_id: &Pubkey, ) -> Option<&'a PerpMarket> { let data = account.data(); - if account.owner() != program_id || data.is_empty() { + if account.owner() != program_id || data.len() < 8 { return None; } diff --git a/programs/mango-v4/src/accounts_zerocopy.rs b/programs/mango-v4/src/accounts_zerocopy.rs index 5de640e22..e1fb765f4 100644 --- a/programs/mango-v4/src/accounts_zerocopy.rs +++ b/programs/mango-v4/src/accounts_zerocopy.rs @@ -157,6 +157,9 @@ impl LoadZeroCopy for A { } let data = self.data(); + if data.len() < 8 { + return Err(ErrorCode::AccountDiscriminatorNotFound.into()); + } let disc_bytes = array_ref![data, 0, 8]; if disc_bytes != &T::discriminator() { return Err(ErrorCode::AccountDiscriminatorMismatch.into()); @@ -178,6 +181,9 @@ impl<'info, 'a> LoadMutZeroCopy for AccountInfoRefMut<'info, 'a> { return Err(ErrorCode::AccountOwnedByWrongProgram.into()); } + if self.data.len() < 8 { + return Err(ErrorCode::AccountDiscriminatorNotFound.into()); + } let disc_bytes = array_ref![self.data, 0, 8]; if disc_bytes != &T::discriminator() { return Err(ErrorCode::AccountDiscriminatorMismatch.into()); @@ -202,6 +208,9 @@ impl<'info> LoadZeroCopyRef for AccountInfo<'info> { } let data = self.try_borrow_data()?; + if data.len() < 8 { + return Err(ErrorCode::AccountDiscriminatorNotFound.into()); + } let disc_bytes = array_ref![data, 0, 8]; if disc_bytes != &T::discriminator() { @@ -228,6 +237,9 @@ impl<'info> LoadMutZeroCopyRef for AccountInfo<'info> { } let data = self.try_borrow_mut_data()?; + if data.len() < 8 { + return Err(ErrorCode::AccountDiscriminatorNotFound.into()); + } let disc_bytes = array_ref![data, 0, 8]; if disc_bytes != &T::discriminator() { diff --git a/programs/mango-v4/src/state/health.rs b/programs/mango-v4/src/state/health.rs index ef03cdb82..7eabb3263 100644 --- a/programs/mango-v4/src/state/health.rs +++ b/programs/mango-v4/src/state/health.rs @@ -189,6 +189,7 @@ fn can_load_as<'a, T: ZeroCopy + Owner>( match load_result { Err(Error::AnchorError(error)) if error.error_code_number == ErrorCode::AccountDiscriminatorMismatch as u32 + || error.error_code_number == ErrorCode::AccountDiscriminatorNotFound as u32 || error.error_code_number == ErrorCode::AccountOwnedByWrongProgram as u32 => { return None;