Skip to content

fix: detect interprocedural storage TOCTOU through qualified Self:: calls - #454

Merged
luhrhenz merged 2 commits into
Veritas-Vaults-Network:mainfrom
luhrhenzthedev:fix/interprocedural-storage-toctou-split-function
Aug 26, 2026
Merged

luhrhenz merged 2 commits into
Veritas-Vaults-Network:mainfrom
luhrhenzthedev:fix/interprocedural-storage-toctou-split-function

Conversation

@luhrhenzthedev

Copy link
Copy Markdown
Contributor

Fix interprocedural storage TOCTOU detection for qualified Self:: calls

Problem

cargo test -p soroban-guard-checks failed on main:

---- interprocedural_storage_toctou::tests::flags_claim_do_claim_split stdout ----
thread 'interprocedural_storage_toctou::tests::flags_claim_do_claim_split' panicked at
crates/checks/src/interprocedural_storage_toctou.rs:300:9:
assertion `left == right` failed: should flag the TOCTOU pattern
  left: 0
 right: 1

The check was registered and running, but it returned 0 findings on a fixture that clearly demonstrates the split-function TOCTOU pattern: claim() reads storage via already_claimed(), then writes storage via do_claim(). Because the read and write happen in different functions, the guard in claim() does not protect the write in do_claim().

Root Cause

In collect_ops_visitor, visit_expr_call extracted the callee name using:

if let Some(ident) = p.path.get_ident() {
    let callee = ident.to_string();

get_ident() only returns Some for simple, unqualified identifiers (e.g., foo()). For qualified calls like Self::already_claimed(&env) or Self::do_claim(&env), the path is Path with multiple segments, so get_ident() returns None. As a result, the visitor never descended into called helper functions, and their storage operations were never collected. With no writes collected, the read/write matching logic had nothing to flag.

Fix

Changed callee extraction to use the last segment of the path:

if let Some(segment) = p.path.segments.last() {
    let callee = segment.ident.to_string();

This works for both:

  • Unqualified calls: foo() → segment foo
  • Qualified calls: Self::foo() → segment foo

Now the interprocedural visitor correctly traverses into helper functions and collects their storage reads/writes, allowing the TOCTOU pattern to be detected.

Verification

cargo test -p soroban-guard-checks --lib

Result: 741 passed; 0 failed

The previously failing test now passes, and all existing tests continue to pass.

Files Changed

  • crates/checks/src/interprocedural_storage_toctou.rs

closes #441

@luhrhenz
luhrhenz merged commit eb4b7a0 into Veritas-Vaults-Network:main Aug 26, 2026
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.

Failing test on main: interprocedural-storage-toctou never fires

2 participants