Insufficient Data Length Check Remediation
How to fix account data access without sufficient length validation.
Insufficient Data Length Check Remediation
Overview
Related Detector: Insufficient Data Length Check
Programs that read or write account data without verifying the buffer is large enough can cause out-of-bounds access or runtime panics. The fix is to check account.data.len() against the required size before any read or write operation.
Recommended Fix
Before (Vulnerable)
pub fn update_config(accounts: &[AccountInfo], new_value: u64) -> ProgramResult {
let config = &accounts[0];
let mut data = config.try_borrow_mut_data()?;
// Writes 8 bytes at offset 32 without checking data length
data[32..40].copy_from_slice(&new_value.to_le_bytes());
Ok(())
}
After (Fixed)
pub fn update_config(accounts: &[AccountInfo], new_value: u64) -> ProgramResult {
let config = &accounts[0];
let mut data = config.try_borrow_mut_data()?;
if data.len() < 40 {
return Err(ProgramError::InvalidAccountData);
}
data[32..40].copy_from_slice(&new_value.to_le_bytes());
Ok(())
}
Alternative Mitigations
Use Anchor’s typed accounts to validate data length automatically during deserialization:
#[account]
pub struct Config {
pub authority: Pubkey, // 32 bytes
pub value: u64, // 8 bytes
// Anchor validates data.len() >= 8 + 32 + 8 during deserialization
}
Define constants for all expected account sizes and validate at the top of each handler:
const CONFIG_SIZE: usize = 8 + 32 + 8; // discriminator + pubkey + u64
pub fn process(accounts: &[AccountInfo]) -> ProgramResult {
let config = &accounts[0];
require!(config.data_len() >= CONFIG_SIZE, InvalidAccountData);
// Safe to access up to CONFIG_SIZE bytes
Ok(())
}
Common Mistakes
Checking the length for reads but not writes. Writes to undersized buffers are more dangerous than reads because they corrupt adjacent memory.
Using the wrong size constant. When account layouts change (e.g., adding a new field), the length constant must be updated. Consider using std::mem::size_of::<T>() for Borsh-serialized structs.
Checking length in the initializer but not in update handlers. Account data can be reallocated to a smaller size. Every handler that accesses account data should validate the length independently.