Account Reallocation
Detects unsafe account reallocation patterns that can corrupt data.
Account Reallocation
Overview
Remediation Guide: How to Fix Account Reallocation
The account reallocation detector identifies unsafe patterns when Solana accounts are resized using realloc. Account reallocation is powerful but hazardous: growing an account without zeroing new memory exposes stale data, reading after realloc without discriminator validation risks type confusion, and writing after realloc without rent-exemption checks can leave accounts vulnerable to garbage collection.
Sigvex tracks realloc syscalls and analyzes subsequent operations for missing discriminator checks, absent rent validation, missing zero-fill, and absent data preservation logic.
Why This Is an Issue
Unsafe reallocation leads to several vulnerability classes:
- Information leakage: newly allocated memory may contain stale data from previous occupants when
realloc::zerois false. - Type confusion: after reallocation, the account’s data layout may change, and reading without re-checking the discriminator can misinterpret fields.
- Rent exhaustion: growing an account requires additional lamports for rent exemption. Without adjustment, the account may be garbage-collected.
- Data truncation: shrinking an account without preserving data silently destroys fields beyond the new boundary.
CWE mapping: CWE-119 (Improper Restriction of Operations within Memory Buffer).
How to Resolve
Native Solana
// 1. Read old data before realloc
let old_data = MyAccount::try_from_slice(&account.data.borrow())?;
// 2. Realloc with zero-fill
account.realloc(new_size, true)?;
// 3. Verify rent exemption
let rent = Rent::get()?;
let required = rent.minimum_balance(new_size);
if account.lamports() < required {
let shortfall = required - account.lamports();
**payer.try_borrow_mut_lamports()? -= shortfall;
**account.try_borrow_mut_lamports()? += shortfall;
}
// 4. Re-validate discriminator
let data = account.data.borrow();
require!(data[0..8] == MyAccount::DISCRIMINATOR, InvalidDiscriminator);
// 5. Write migrated data
let new_data = old_data.migrate_to_v2();
new_data.serialize(&mut &mut account.data.borrow_mut()[..])?;
Anchor
#[derive(Accounts)]
pub struct Resize<'info> {
#[account(mut, realloc = new_size, realloc::payer = payer, realloc::zero = true)]
pub my_account: Account<'info, MyAccount>,
#[account(mut)]
pub payer: Signer<'info>,
pub system_program: Program<'info, System>,
}
Examples
Vulnerable
// Realloc without zero-fill or validation
account.realloc(new_size, false)?;
let data = MyAccount::try_from_slice(&account.data.borrow())?; // Reads stale memory
Fixed
account.realloc(new_size, true)?; // Zero-fill new space
let rent = Rent::get()?;
require!(account.lamports() >= rent.minimum_balance(new_size), NotRentExempt);
let data = account.data.borrow();
require!(data[0..8] == MyAccount::DISCRIMINATOR, InvalidDiscriminator);
JSON Finding
{
"detector": "account-reallocation",
"severity": "High",
"confidence": 0.75,
"title": "Account Read After Realloc Without Discriminator Validation",
"description": "An account is reallocated and then read without validating its discriminator.",
"cwe": [119]
}
Detection Methodology
The detector identifies realloc syscalls and classifies subsequent operations into reads, writes, discriminator checks, and rent checks. It reports findings when reads occur after realloc without intervening discriminator validation, when writes occur without rent-exemption checks, when realloc lacks zero-fill, or when data preservation logic (read-before/write-after pattern) is absent.
Limitations
- The detector relies on syscall name matching for realloc identification and may miss custom realloc wrappers.
- Anchor’s realloc constraint provides automatic safety but is not always distinguishable from native realloc in decompiled bytecode.
- Data migration patterns using helper functions across module boundaries may not be detected.
Related Detectors
- Account Realloc Corruption - detects reallocation to dangerous sizes.
- Rent Exempt Reallocation - detects realloc without rent adjustment.