Instruction Data Length
Detects missing instruction data length validation before unpacking, the most common source of runtime panics in Solana programs.
Instruction Data Length
Overview
Remediation Guide: How to Fix Instruction Data Length
The instruction data length detector identifies Solana programs that access instruction data at specific byte offsets without first validating that the data buffer is long enough. This is the single most common source of runtime panics in Solana programs and affects DEX programs, NFT marketplaces, and any program that processes variable-length instructions.
When a program reads instruction_data[0..8] to extract a u64 amount but the caller provides only 4 bytes, the runtime panics with an index-out-of-bounds error. Attackers exploit this to crash programs on demand, causing denial of service and wasting compute units.
Why This Is an Issue
An attacker can craft transactions with truncated instruction data to crash any unprotected program. The impact includes runtime panics (the most common panic cause on Solana), denial of service through repeated crash transactions, wasted compute units before the panic occurs, and confusing error messages for legitimate users who accidentally provide malformed data.
How to Resolve
Native Solana program:
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
const MIN_DATA_LENGTH: usize = 40; // 8 (amount) + 32 (recipient)
if instruction_data.len() < MIN_DATA_LENGTH {
return Err(ProgramError::InvalidInstructionData);
}
let amount = u64::from_le_bytes(instruction_data[0..8].try_into().unwrap());
let recipient = Pubkey::new_from_array(instruction_data[8..40].try_into().unwrap());
// Process validated data...
Ok(())
}
Anchor program:
#[derive(AnchorDeserialize)]
pub struct TransferArgs {
pub amount: u64, // 8 bytes
pub recipient: Pubkey, // 32 bytes
// Anchor validates length automatically during Borsh deserialization
}
Examples
Vulnerable Code
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// No length check - panics if data < 40 bytes
let amount = u64::from_le_bytes(instruction_data[0..8].try_into().unwrap());
let recipient = Pubkey::new_from_array(instruction_data[8..40].try_into().unwrap());
Ok(())
}
Fixed Code
pub fn process_instruction(
_program_id: &Pubkey,
_accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
if instruction_data.len() < 40 {
return Err(ProgramError::InvalidInstructionData);
}
let amount = u64::from_le_bytes(instruction_data[0..8].try_into().unwrap());
let recipient = Pubkey::new_from_array(instruction_data[8..40].try_into().unwrap());
Ok(())
}
Sample Sigvex Output
[HIGH] Missing Instruction Data Length Validation
Location: process_instruction
Description: The function accesses instruction data at offsets [0, 8]
(max offset: 8), which requires at least 9 bytes of instruction data,
but does not validate the data length upfront.
CWE: CWE-129 (Improper Validation of Array Index)
Detection Methodology
- Instruction data access tracking: The detector identifies all operations that read from the instruction data buffer and records the byte offsets accessed.
- Maximum offset calculation: It computes the highest byte offset referenced, which determines the minimum required data length.
- Length validation search: The detector searches for conditional checks that compare the instruction data length against a constant value (e.g.,
data.len() >= 40). - Finding generation: If instruction data is accessed but no upfront length validation exists, a finding is reported with the required minimum buffer size.
Limitations
False positives: Programs that use Borsh deserialization (try_from_slice) may be flagged even though Borsh validates length during deserialization. Anchor programs receive significantly reduced confidence scores. False negatives: Dynamic offset calculations (e.g., data[variable_offset]) may not be tracked if the offset is not a compile-time constant.
Related Detectors
- Instruction Data Parsing Edge Cases — detects unsafe parsing patterns beyond length checks
- Insufficient Data Length Check — detects insufficient account data length validation