Skip to content

fix: the nightly fuzz's offset_executive_p2 timeout (offset refuses a distance below the B-rep tolerance) and name-seeded fuzz cases - #2737

Merged
jyviko merged 4 commits into
mainfrom
fix/nightly-fuzz
Nov 4, 2026
Merged

jyviko merged 4 commits into
mainfrom
fix/nightly-fuzz

Conversation

@jyviko

@jyviko jyviko commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator

Fixes the nightly fuzz's offset.offset_executive_p2 fuzz00175 timeout: the offset now refuses, before building anything, a distance below the input's B-rep tolerance, and fuzz cases are seeded by fixture name so adding a fixture no longer reshuffles every case. fuzz00167 (the C++ SIGSEGV with a negative approximation tolerance) is left to #2733.

Units: offset.offset_executive_p2 (kernel, shim, runner), difftest fuzz driver.

What changes

  1. Kernel refusal (fuzz00175). offset_brep, do_solid_offset and do_extended_offset refuse an offset distance that is not a finite length of at least the input B-rep's tolerance: OffsetFailure::DistanceUnresolved { distance, resolution }, kind ErrorKind::InvalidInput, message naming both values. Bound: the input B-rep's tolerance, the distance below which the model does not tell two points apart, so an offset that close lies within tolerance of its own face. (SolidError::InvalidInput carries only a &'static str, so the refusal is a structured Errors: report solidcore-specific, descriptive errors instead of bare SMLib statuses and SMLib names #2615 Failure of kind InvalidInput, which can name the values.) The shells already refuse below twice the tolerance (upstream's guard), so they never reach it. A member distance of 1e-300 took 31.5 s in Rust and 21 s in C++, in SubdivideToTolerances; recorded as HANG-53.
    • The p2 shim refuses the same inputs before the C++ runs ([-2] → Outcome::Refused → a rejected case), using the built source's GetTolerance(), so the two sides stay aligned, including file sources and nonpositive fixture tolerances.
    • Test: crates/solidcore/tests/offset_negative_approximation_tolerance.rs. 1e-300 is refused, naming it and the tolerance, with the input unchanged. tolerance * (1 + ε) still builds, both extended and rounded.
  2. C++ extended-offset calls in a child process. Generalises the existing UB-241 crash trap: every p2 C++ call that reaches DoExtendedOffset (the extended operation, or any operation with extend_convex) runs through eval_in_child / the new eval_measured_in_child. A C++ crash there is a rejected case, not a dead nightly. The mechanism is general and is not keyed to fuzz00167.
  3. Fuzz cases are seeded by fixture name. Each base case b seeds fnv1a64("fuzz:" + unit + ":" + b) + i, and the largest first draw wins (rendezvous hashing). Adding a fixture changes only the ~1/(n+1) cases it wins. The nightly's case inputs change once because of this, so every unit's fuzzNNNNN names map to new inputs from this PR on. A test checks that inserting a base leaves every case it doesn't win unchanged.

Results that change

Evidence

  • cargo clippy -p solidcore -p difftest -p solidcore-ffi --features difftest/cpp --all-targets -D warnings: clean (aarch64 box).
  • cargo test -p solidcore --test offset_negative_approximation_tolerance: 4 passed.
  • Not run yet: the fuzz00175 / fuzz00167 replays, the unit difftest against a baseline, the unit's --fuzz 300, and the difftest crate's unit tests (including the new fuzz-seed test). The owner asked to wrap up first; these come before ready-for-review.

Status: draft.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

Explain Change →

Caution

Review failed

The pull request is closed.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

@jyviko jyviko closed this Nov 4, 2026
@jyviko jyviko reopened this Nov 4, 2026
jyviko and others added 3 commits November 4, 2026 15:32
Each base case seeds a generator with fnv1a64("fuzz:" + unit + ":" + name) + i;
the base whose generator draws the largest first value wins (rendezvous hashing)
and that generator makes the mutations. Adding a fixture now changes only the
cases it wins instead of reshuffling every case's input.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DtL5M41G8Nua7HvuFPZkmJ
… fuzz00175)

The static, solid and extended offsets refuse, before building anything, an
offset distance that is not a finite length of at least the input's B-rep
tolerance (OffsetFailure::DistanceUnresolved, kind InvalidInput, naming the
distance and the tolerance). A member distance of 1e-300 took 31.5 s in Rust
and 21 s in C++ (HANG-53). The p2 shim refuses the same inputs before the C++
runs them ([-2], Outcome::Refused -> a rejected case).

The p2 runner runs every C++ call that reaches DoExtendedOffset in a fresh
child process (the crash trap, generalised from UB-241), so a C++ crash there
is a rejected case rather than a dead nightly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DtL5M41G8Nua7HvuFPZkmJ
…e input resolves (HANG-53)

They passed the default distance 0, which the offset now refuses before
anything is built, so they no longer reached the collapse they test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DtL5M41G8Nua7HvuFPZkmJ
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.

1 participant