Skip to content

chore: use saturating sub with max_ttl computation#1792

Merged
mootz12 merged 1 commit intomainfrom
fix-missing-checked-sub
Mar 26, 2026
Merged

chore: use saturating sub with max_ttl computation#1792
mootz12 merged 1 commit intomainfrom
fix-missing-checked-sub

Conversation

@mootz12
Copy link
Copy Markdown
Contributor

@mootz12 mootz12 commented Mar 25, 2026

What

Use saturating_sub when computing max_ttl.

Why

Add another defense layer to potential misconfigurations, and improve consistency with math usage in the repository.

Closes #1791

Known limitations

None

Copilot AI review requested due to automatic review settings March 25, 2026 20:41
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes Storage::max_ttl() more defensive and consistent by using saturating arithmetic when computing the maximum TTL from ledger values.

Changes:

  • Switch max_ttl computation from max - seq to max.saturating_sub(seq) to avoid underflow in edge/misconfigured cases.

Comment thread soroban-sdk/src/storage.rs
@mootz12 mootz12 requested a review from a team March 25, 2026 20:44
Copy link
Copy Markdown
Member

@leighmcculloch leighmcculloch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine but the host guarantees that max ttl is greater than the current seq, so in practice this will have no impact.

Will this introduce instructions into the wasm guest side that are redundant? I think so. Although maybe it won't be meaningful difference since the minus will already be doing a check when compiled with checks on.

What's the motivation for doing this?

If we keep it the way it is we can add a comment explaining why the sub is safe.

@mootz12
Copy link
Copy Markdown
Contributor Author

mootz12 commented Mar 26, 2026

Will this introduce instructions into the wasm guest side that are redundant?

Actually, this reduces size. Seems the WASM code for saturating_sub is denser than a regular subtraction with overflow-checks = true. Turning overflow checks off, the regular subtraction is smaller.

The test:

#![no_std]
use soroban_sdk::{contract, contractimpl, Env, Symbol};

#[contract]
pub struct Contract;

#[contractimpl]
impl Contract {
    pub fn put(e: Env, key: Symbol, val: Symbol) {
        e.storage().persistent().set(&key, &val);
        let max_ttl = e.storage().max_ttl();
        e.storage().persistent().extend_ttl(&key, max_ttl, max_ttl);
    }

    pub fn get(e: Env, key: Symbol) -> Option<Symbol> {
        let entry = e.storage().persistent().get(&key);
        let max_ttl = e.storage().max_ttl();
        if entry.is_some() {
            e.storage().persistent().extend_ttl(&key, max_ttl, max_ttl);
        }
        entry
    }

    pub fn del(e: Env, key: Symbol) {
        e.storage().persistent().remove(&key)
    }
}

Results

  • regular sub, overflow checks = 830 bytes
  • saturating sub, overflow checks = 803 bytes
  • regular sub, no overflow checks = 789 bytes

What's the motivation for doing this?

The host does prevent this from occurring. The SDK uses safe math functions in most locations outside of indexes/counters. This just brings this up to that standard.

@mootz12 mootz12 added this pull request to the merge queue Mar 26, 2026
Merged via the queue into main with commit a5c0e4b Mar 26, 2026
196 of 198 checks passed
@mootz12 mootz12 deleted the fix-missing-checked-sub branch March 26, 2026 15:01
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.

Storage::max_ttl() should use saturating_sub for consistency and defensive arithmetic

4 participants