Instruction Data Parsing Edge Cases
Detects unsafe instruction data parsing patterns that may cause panics or errors with malformed data.
Instruction Data Parsing Edge Cases
Overview
Remediation Guide: How to Fix Instruction Data Parsing Edge Cases
The instruction data parsing edge cases detector identifies Solana programs that parse instruction data without adequate validation. It targets instruction handler functions (identified by naming conventions such as process_instruction, handle, or parse) that lack conditional branches, input checks, or discriminator validation. These patterns indicate the program blindly trusts incoming data.
Unlike the instruction data length detector which focuses on buffer size, this detector looks for higher-level parsing safety: missing discriminator validation, absence of error-handling branches, and overly simplistic instruction handlers that contain no validation logic at all.
Why This Is an Issue
Instruction data is entirely caller-controlled. A program that deserializes without validation can be crashed with malformed data, leading to transaction failures and denial of service. Simplistic handlers that contain no branching or error paths typically indicate missing input validation, which can result in unexpected behavior when the program encounters data formats it was not designed to handle.
How to Resolve
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// 1. Validate minimum length
if instruction_data.len() < 1 {
return Err(ProgramError::InvalidInstructionData);
}
// 2. Validate discriminator
let discriminator = instruction_data[0];
match discriminator {
0 => handle_initialize(program_id, accounts, &instruction_data[1..]),
1 => handle_transfer(program_id, accounts, &instruction_data[1..]),
_ => Err(ProgramError::InvalidInstructionData),
}
}
Examples
Vulnerable Code
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
// No validation, no branching, no error handling
let data = MyData::try_from_slice(instruction_data).unwrap();
execute(accounts, data)
}
Fixed Code
pub fn process_instruction(
_program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
if instruction_data.is_empty() {
return Err(ProgramError::InvalidInstructionData);
}
let data = MyData::try_from_slice(instruction_data)
.map_err(|_| ProgramError::InvalidInstructionData)?;
execute(accounts, data)
}
Sample Sigvex Output
[MEDIUM] Instruction Handler Without Validation
Location: process_instruction
Description: Function 'process_instruction' appears to handle instruction
data but contains no validation checks.
CWE: CWE-20 (Improper Input Validation)
Detection Methodology
- Function name heuristic: Identifies functions whose names contain keywords like
instruction,process,handle,parse, ordeserialize. - Validation check scanning: Searches for signer checks, owner checks, key checks, writable checks, and conditional branches within the function body.
- Complexity analysis: Single-block instruction handlers with no validation are flagged at low severity. Multi-block handlers without validation are flagged at medium severity.
Limitations
False positives: Helper functions called from validated entry points may be flagged if their names match instruction handler patterns. Anchor programs receive significantly reduced confidence because Anchor handles deserialization automatically. False negatives: Functions with non-standard naming conventions may not be identified as instruction handlers.
Related Detectors
- Instruction Data Length — detects missing buffer length validation
- Instruction Fallback Handler — detects unsafe default cases for unknown discriminators