Skip to content

fix: validate account count and enforce payer mutability#83

Open
L0STE wants to merge 1 commit intomasterfrom
fix/validate-init-if-needed-complete
Open

fix: validate account count and enforce payer mutability#83
L0STE wants to merge 1 commit intomasterfrom
fix/validate-init-if-needed-complete

Conversation

@L0STE
Copy link
Contributor

@L0STE L0STE commented Mar 24, 2026

Context

The dispatch! macro and __handle_event both skip the num_accounts u64 at the start of the SVM input buffer without ever reading it. If a transaction provides fewer accounts than the instruction expects, parse_accounts walks past the valid account data into unmapped memory and the SBF VM traps with an access violation. Not a security vulnerability (the crash is safe — no state changes, no fund loss), but a correctness issue: programs should return NotEnoughAccountKeys instead of crashing.

Separately, there was no compile-time enforcement that payer accounts are writable. The Solana runtime catches this at execution time, but a build error is strictly better than a failed transaction on testnet.

Ref: #80 (QSR-01, QSR-04, QSR-05). QSR-02 is a compile-time-only footgun, QSR-03 is wrong (intentional SIMD-0321 entrypoint).

Changes

lang/src/entrypoint.rs — Read num_accounts from offset 0 of the SVM buffer. Each dispatch! match arm now checks num_accounts >= COUNT before calling parse_accounts. ~2 CU cost.

derive/src/program.rs__handle_event checks num_accounts > 0 before dereferencing the first account for the event authority signer/address check.

derive/src/accounts/fields.rsprocess_fields now rejects at compile time if the init or realloc payer field is not &mut or #[account(mut)].

Test plan

  • cargo check — clean
  • cargo fmt — clean
  • cargo clippy — clean
  • Full test suite — 729 passed, 0 failed

Validate num_accounts from the SVM input buffer before dispatch and
event handling to return NotEnoughAccountKeys instead of crashing on
malformed transactions. Add compile-time check that init and realloc
payers are declared writable.
@github-actions
Copy link

⚡ CU Benchmark (Vault)

Instruction Base PR Delta
Deposit 1,575 1,577 +2 🔴
Withdraw 409 411 +2 🔴

Binary size: 6,928 bytes (+40 🔴 bytes)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant