Skip to content

Fix floating-point remainder soundness and add soundness documentation#4570

Open
feliperodri wants to merge 4 commits intomodel-checking:mainfrom
feliperodri:fix-soundness-issues
Open

Fix floating-point remainder soundness and add soundness documentation#4570
feliperodri wants to merge 4 commits intomodel-checking:mainfrom
feliperodri:fix-soundness-issues

Conversation

@feliperodri
Copy link
Copy Markdown
Contributor

Two soundness-related fixes:

  1. Fix incorrect floating-point remainder (Incorrect floating point result with remainder (%) operator #2669): The % operator on f32/f64 was silently producing wrong results because Kani emitted CBMC's integer mod operation for floating-point operands. CBMC ignores integer mod on floatbv types, leading to incorrect verification results (false negatives).

  2. Add soundness documentation (Soundness documentation #1495): New docs/src/soundness.md page documenting what Kani checks, what it does not check, and known soundness caveats.

Fix for #2669

Added FloatbvMod as a new BinaryOperator variant that maps to CBMC's floatbv_mod expression, which implements IEEE 754 fmod semantics. The Expr::rem() method now dispatches to FloatbvMod for floating-point operands and Mod for integers.

Changes:

  • cprover_bindings/src/goto_program/expr.rs — Add FloatbvMod variant, type validation, return type, and conditional dispatch in rem().
  • cprover_bindings/src/irep/irep_id.rs — Add FloatbvMod IREP ID and string mapping.
  • cprover_bindings/src/irep/to_irep.rs — Add FloatbvModIrepId::FloatbvMod conversion.
  • tests/kani/FloatingPoint/float_remainder.rs — Regression test with symbolic f32 and f64 remainder verification.

Fix for #1495

New documentation page covering:

  • What Kani checks: Arithmetic overflow, division by zero, pointer validity, array bounds, panics, shift distance, float-to-int conversion, NaN, memory leaks (always on); valid value invariants and uninitialized memory (opt-in).
  • What Kani does NOT check: Data races, aliasing violations, immutable data mutation, inline assembly, ABI violations, transmute of invalid values.
  • Soundness caveats: CBMC backend risks, bounded verification, floating-point model, object size limits, function pointer imprecision.

Resolves #2669
Resolves #1495

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.

@feliperodri feliperodri added this to the Soundness milestone Apr 2, 2026
@feliperodri feliperodri added the [F] Soundness Kani failed to detect an issue label Apr 2, 2026
@github-actions github-actions bot added Z-EndToEndBenchCI Tag a PR to run benchmark CI Z-CompilerBenchCI Tag a PR to run benchmark CI labels Apr 2, 2026
The remainder (%) operator on floating-point types was incorrectly
using CBMC's integer 'mod' operation, which CBMC silently ignores for
floatbv types, producing incorrect verification results.

Use the floatbv_mod binary operator for float/double operands, which
correctly implements IEEE 754 fmod semantics matching Rust's % on
floating-point types.

Resolves model-checking#2669

Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
Document what Kani checks (always-on and opt-in), what it does not
check, and known soundness caveats (CBMC backend, bounded verification,
floating-point, object size limits, function pointers).

Resolves model-checking#1495

Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
@feliperodri feliperodri force-pushed the fix-soundness-issues branch from d8f915d to a6380e4 Compare April 2, 2026 01:11
@feliperodri feliperodri marked this pull request as ready for review April 2, 2026 01:13
@feliperodri feliperodri requested a review from a team as a code owner April 2, 2026 01:13
CBMC does not emit a 'division by zero' check for floatbv_mod (float
remainder), unlike integer mod. Remove the expected line since the
float remainder operator now correctly uses floatbv_mod.

Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
…ixed

The float remainder bug tracked by this fixme test is resolved by the
floatbv_mod change. Remove the fixme suffix so it runs as a passing
test in the kani suite instead of an expected-failure in kani-fixme.

Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
@feliperodri
Copy link
Copy Markdown
Contributor Author

Neither benchmark uses floating-point. Our change didn't cause this perf-benchcomp. These are solver runtime fluctuations: the SAT solver (CaDiCaL) is nondeterministic in its performance on shared CI runners. The same benchmarks that regressed on main (inet::checksum::tests::differential at 2.3x) are different from the ones regressing here, which confirms this is runner-level noise, not a code change effect.

The perf-regression.yaml threshold is solver_runtime > 1.5x with a minimum of 10 seconds. These benchmarks are in the 35-82 second range where a 1.5-1.7x fluctuation is common on shared GitHub-hosted runners due to CPU contention from other jobs on the same host.

This is not caused by the floatbv_mod change; neither benchmark involves floating-point operations. This is the same class of CI flakiness that affects the main branch (which also failed its perf benchmark with different benchmarks regressing).

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

Labels

[F] Soundness Kani failed to detect an issue Z-CompilerBenchCI Tag a PR to run benchmark CI Z-EndToEndBenchCI Tag a PR to run benchmark CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect floating point result with remainder (%) operator Soundness documentation

1 participant