Skip to content

memory_budget_bytes is accepted but never enforced #104

Description

@GeneralPawz

ExecutionOptions::with_memory_budget accepts a budget that nothing
enforces. A caller can ask for a 1 KB ceiling on a large boolean and
the operation runs to completion, allocating far more, with no error
and no diagnostic.

Evidence

The machinery exists. ScratchRequirement::fits_budget is implemented
and unit-tested in crates/contracts/common/base/:

$ grep -rn "fits_budget" crates/ --include=*.rs
crates/contracts/common/base/tests/execution_contracts.rs:158
crates/contracts/common/base/tests/execution_contracts.rs:164
crates/contracts/common/base/tests/execution_contracts.rs:167
crates/contracts/common/base/tests/execution_contracts.rs:177
crates/contracts/common/base/tests/execution_contracts.rs:178

Every hit is a test. There is no production caller anywhere in
crates/, so no operation consults memory_budget_bytes().

Measured by the new benchmark scorecard:

  1 KB memory budget    rec    ignored

The workload is a 20-unit bar minus 24 tools, which allocates on the
order of 85 KB for a far smaller union. It completes successfully under
a 1024-byte budget.

Why it matters

A silently inert option is worse than an absent one. A caller that sets
a budget reasonably believes it is protected, and an embedder using it
to bound memory on untrusted input gets no protection at all. The
failure is invisible: no error, no warning, no evidence field.

This is the same shape as the cancellation contract, which IS honoured
and IS declared through cancellation_granularity() -- the boolean
provider refuses a pre-cancelled batch correctly. Budget has the
declaration machinery but no enforcement.

Suggested resolution

Either enforce it or refuse it, not silence. Two defensible options:

  1. Call fits_budget at dispatch, where the doc comment already says
    budget checks belong ("once per dispatch, not on a hot path"), and
    return a typed refusal when the requirement exceeds the budget.
  2. If a provider cannot estimate its scratch requirement, declare that
    explicitly the way cancellation granularity is declared, so callers
    can tell "unbounded" from "bounded and checked".

Option 1 matches the existing design intent; the doc comment on
fits_budget reads as though dispatch was the intended caller.

Found by: axiolid-benchmarks --only=cancel

Activity

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

Metadata

Metadata

Assignees

Labels

needs-triageFiled but not yet accepted, sized, or scheduled

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions