Skip to content

docs: document overflow risks in bulk-op fuel and bounds prologues - #176

Open
dmitry123 wants to merge 1 commit into
develfrom
claude/flu-1104-bulk-op-fuel-d64656
Open

docs: document overflow risks in bulk-op fuel and bounds prologues#176
dmitry123 wants to merge 1 commit into
develfrom
claude/flu-1104-bulk-op-fuel-d64656

Conversation

@dmitry123

Copy link
Copy Markdown
Member

Summary

Documents the integer-overflow risks in the compiler-injected bulk-op prologues, per the direction on FLU-1104no behavior change, comments only.

The audit finding is that two patterns in the injected guards do not do what they were written to do:

  • Signed comparison on unsigned quantities. op_memory_grow_checked, op_memory_init_checked, op_table_grow_checked and op_table_init_checked compare size + delta (or n + s) against a limit with i32.gt_s over a wrapping i32.add. An operand near i32::MAX makes the sum negative, so the guard passes.
  • Wrapping round-up in the fuel calculation. All six bulk prologues charge (n + PER_FUEL - 1) >> PER_FUEL_LOG2; the add wraps for n near u32::MAX, yielding (almost) zero fuel for a nominally multi-gigabyte operation.

Neither is exploitable at the current limits — every input large enough to wrap is rejected by the runtime bounds check behind the guard before any memory or table element is touched, so no undercharged work is ever performed. The point is that the safety rests entirely on that bounds check, and a future change to the limits could make it exploitable with no visible change to the prologue code.

Changes

  • src/types/mod.rs# Safety notes on N_MAX_ALLOWED_MEMORY_PAGES and N_MAX_TABLE_SIZE explaining that the injected guards depend on these limits staying far below i32::MAX, and what must change first if they are raised.
  • src/isa/memory.rs — file-level SAFETY NOTE on the MEMORY_BYTES_PER_FUEL round-up, a # Safety note on op_memory_grow_checked, a note on the memory.init guard, and pointers at each wrapping site.
  • src/isa/table.rs — equivalent file-level SAFETY NOTE covering both the signed compares and the TABLE_ELEMS_PER_FUEL round-up, with pointers at each site.

Also replaces the stale comment in op_memory_grow_checked — "overflow is impossible here (we pass max pages in trustless mode)" — which asserted exactly the invariant the signed compare above it fails to establish.

Verification

Claims about the runtime backstops were checked against the code rather than assumed: GlobalMemory::grow uses checked_add plus the page cap, Pages::new rejects oversized deltas, TableEntity::grow_untyped uses checked_add plus N_MAX_TABLE_SIZE, and the bulk ops go through slice bounds checks.

cargo build, cargo test --lib (75 passed), and cargo doc --no-deps all clean — the new intra-doc links resolve, and the only warning in the touched files is the pre-existing [addr] one at src/isa/memory.rs:41.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@dmitry123, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 56 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d36d91a7-42b5-4fb1-bd6f-eb2cc0c8f1c7

📥 Commits

Reviewing files that changed from the base of the PR and between b8f6091 and 6cafdf8.

📒 Files selected for processing (3)
  • src/isa/memory.rs
  • src/isa/table.rs
  • src/types/mod.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Criterion results (vs baseline)


running 75 tests
test compiler::compiled_expr::tests::compiledexpr_eval_const_returns_none_for_global_or_funcref ... ignored
test compiler::compiled_expr::tests::compiledexpr_from_const_roundtrips ... ignored
test compiler::compiled_expr::tests::compiledexpr_funcref_and_global_introspection ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_global_get_uses_context ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i32_add_mixed_const_and_global ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i32_add_mixed_global_and_funcref ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i32_add_wraps ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i32_const ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i32_sub_wraps ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i64_const ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_i64_mul_wraps ... ignored
test compiler::compiled_expr::tests::compiledexpr_new_ref_func_uses_context ... ignored
test compiler::compiled_expr::tests::compiledexpr_zero_is_zero ... ignored
test compiler::compiled_expr::tests::constop_eval_returns_value ... ignored
test compiler::compiled_expr::tests::empty_eval_context_always_none ... ignored
test compiler::compiled_expr::tests::eval_with_context_reads_globals_and_funcs ... ignored
test compiler::compiled_expr::tests::expr_op_combines_operands_and_propagates_none ... ignored
test compiler::compiled_expr::tests::funcrefop_reads_from_context ... ignored
test compiler::compiled_expr::tests::globalop_maps_value_kinds_correctly ... ignored
test compiler::compiled_expr::tests::op_clone_panics_for_expr_variant - should panic ... ignored
test compiler::compiled_expr::tests::op_clone_works_for_non_expr_variants ... ignored
test compiler::compiled_expr::tests::op_constant_encodes_f32_f64_bits ... ignored
test compiler::compiled_expr::tests::op_constant_encodes_funcref_externref_ids ... ignored
test compiler::compiled_expr::tests::op_constant_encodes_i32_i64 ... ignored
test compiler::drop_keep::tests::test_drop_keep_translation ... ignored
test compiler::func_type_registry::tests::deduplicates_matching_signatures ... ignored
test compiler::func_type_registry::tests::index_lookup_is_stable ... ignored
test compiler::func_type_registry::tests::resolves_unique_signatures_correctly ... ignored
test compiler::parser::tests::unsupported_component_model_returns_error ... ignored
test module::tests::test_decode_exact_rejects_trailing_garbage ... ignored
test module::tests::test_decode_module_wo_source_pc ... ignored
test module::tests::test_decode_rejects_partial_source_pc ... ignored
test module::tests::test_endianness ... ignored
test module::tests::test_module_encoding ... ignored
test module::verification::tests::accepts_verified_encoded_module ... ignored
test module::verification::tests::regular_construction_does_not_verify ... ignored
test module::verification::tests::regular_decode_does_not_verify ... ignored
test module::verification::tests::rejects_branch_target_outside_code_section ... ignored
test module::verification::tests::rejects_call_target_outside_code_section ... ignored
test module::verification::tests::rejects_missing_table_index_payload ... ignored
test module::verification::tests::rejects_section_index_outside_limits ... ignored
test module::verification::tests::rejects_source_pc_outside_code_section ... ignored
test module::verification::tests::rejects_zero_local_depth ... ignored
test strategy::types::tests::checked_memory_range_end_rejects_overflow ... ignored
test types::nan_preserving_float::tests::test_neg_nan_f32 ... ignored
test types::nan_preserving_float::tests::test_neg_nan_f64 ... ignored
test types::nan_preserving_float::tests::test_ops_f32 ... ignored
test types::nan_preserving_float::tests::test_ops_f64 ... ignored
test types::opcode::tests::test_fpu_opcode_encoding_uses_offset ... ignored
test types::opcode::tests::test_opcode_code_values ... ignored
test types::opcode::tests::test_opcode_encoding ... ignored
test types::opcode::tests::test_opcode_encoding_uses_explicit_code ... ignored
test types::opcode::tests::test_opcode_size ... ignored
test types::units::tests::bytes_new16 ... ignored
test types::units::tests::bytes_new32 ... ignored
test types::units::tests::bytes_new64 ... ignored
test types::units::tests::pages_checked_add ... ignored
test types::units::tests::pages_checked_sub ... ignored
test types::units::tests::pages_max ... ignored
test types::units::tests::pages_new ... ignored
test types::units::tests::pages_to_bytes ... ignored
test types::value::copysign_regression_works ... ignored
test types::value::wasm_float_max_regression_works ... ignored
test types::value::wasm_float_min_regression_works ... ignored
test vm::store::tests::clamps_runtime_memory_limit_to_global_maximum ... ignored
test wasmtime::tests::test_call_with_charging_linear_wasmtime ... ignored
test wasmtime::tests::test_call_with_charging_param_overflow_wasmtime ... ignored
test wasmtime::tests::test_call_with_charging_quadratic_wasmtime ... ignored
test wasmtime::tests::test_wasmtime_caller_memory_read_into_vec_checks_bounds_before_allocating ... ignored
test wasmtime::tests::test_wasmtime_caller_missing_memory_returns_trap ... ignored
test wasmtime::tests::test_wasmtime_executor_memory_read_into_vec_checks_bounds_before_allocating ... ignored
test wasmtime::tests::test_wasmtime_executor_missing_entrypoint_returns_trap ... ignored
test wasmtime::tests::test_wasmtime_snapshot_missing_memory_returns_trap ... ignored
test wasmtime::types::tests::maps_unknown_wasmtime_error_to_illegal_opcode ... ignored
test wasmtime::types::tests::maps_wasmtime_traps_to_rwasm_traps ... ignored

test result: ok. 0 passed; 0 failed; 75 ignored; 0 measured; 0 filtered out; finished in 0.00s

Comparisons/bench_native
                        time:   [5.4475 ns 5.5877 ns 5.7460 ns]
Found 90 outliers among 1000 measurements (9.00%)
  39 (3.90%) high mild
  51 (5.10%) high severe
Comparisons/bench_strategy_wasmtime
                        time:   [17.521 µs 17.966 µs 18.452 µs]
Found 179 outliers among 1000 measurements (17.90%)
  125 (12.50%) high mild
  54 (5.40%) high severe
Comparisons/bench_strategy_rwasm
                        time:   [13.577 µs 13.854 µs 14.167 µs]
Found 113 outliers among 1000 measurements (11.30%)
  45 (4.50%) high mild
  68 (6.80%) high severe

Heads-up: runner perf is noisy; treat deltas as a smoke check.

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/isa/table.rs 66.66% 2 Missing ⚠️
src/isa/memory.rs 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

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.

2 participants