Skip to content

fix: save timeout inputs as solutions - #393

Merged
Wenzel merged 2 commits into
intel:mainfrom
Wenzel:fix/timeout-objective-392
Oct 28, 2026
Merged

Wenzel merged 2 commits into
intel:mainfrom
Wenzel:fix/timeout-objective-392

Conversation

@Wenzel

@Wenzel Wenzel commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Fixes #392

Summary

The objective chain used TimeFeedback, whose is_interesting always returns false (it only stamps exec time as metadata). So ExitKind::Timeout never reached the solutions corpus: timeouts were only logged, and hanging inputs with new coverage were added to the corpus instead, where the fuzzer kept re-running them.

 objective = feedback_or_fast!(
     CrashFeedback::new(),
-    TimeFeedback::new("time"),   // never interesting
+    TimeoutFeedback::new(),      // interesting on ExitKind::Timeout
 )

The TimeFeedback in the normal feedback chain (exec-time metadata) stays. The now-unused TIMEOUT_FEEDBACK_NAME constant is removed.

x86_64_edk2_timeout_{latest,6_0_185} previously asserted nothing. They now seed the corpus with A (the harness stalls 10s, over the 3s timeout) and D (normal, so the corpus isn't empty), then assert that solutions/ holds at least one input and that every solution starts with A.

Evidence

cargo test -r --test x86_64_edk2_timeout_latest (Simics 7.70.0, QSP-x86 7.48.0):

  • Before (test only, without the fix): fails
    [tsffs info] Timeout input for AFL indices [334, 2475, ...]
    [Testcase #0] ... corpus: 2, objectives: 0, executions: 2
    Expected timeout solutions (inputs starting with 'A') in the solutions directory, found first bytes: []
    test result: FAILED. 0 passed; 1 failed; ... finished in 83.37s
    
  • After: passes
    [Objective #0] ... corpus: 0, objectives: 1, executions: 1
    [Testcase #0] ... corpus: 1, objectives: 1, executions: 2
    Configured iteration count 30 reached.
    TSFFS_SOLUTIONS 41 END
    test result: ok. 1 passed; 0 failed; ... finished in 14.11s
    

Merge Danger

Door: two-way

Blast Radius: fuzzing campaigns

  • Timeouts now appear in solutions/ and in the objectives count, and no longer enter the corpus. Campaigns with a tight timeout will report more solutions.
  • Because the objective short-circuits before the map feedback, the per-timeout Timeout input for AFL indices ... log line no longer fires. It is replaced by the LibAFL [Objective #N] monitor line, which is the same behavior crash solutions already have.
  • The _6_0_185 variant was updated identically but only the _latest variant was run.

Wenzel and others added 2 commits October 23, 2026 14:16
The objective used TimeFeedback, which never reports an input as
interesting, so timeouts were only logged and never written to the
solutions directory. Hanging inputs with new coverage were added to the
corpus instead. Use TimeoutFeedback, which flags ExitKind::Timeout.

The timeout test now seeds a hanging input and asserts it lands in
solutions.

Fixes intel#392

Co-authored-by: Claude <noreply@anthropic.com>
The x86_64_manual tests called fuzz.stop() on magic 2, but the harness
stop is N_STOP_NORMAL (4), so every iteration ended in a timeout. Now
that timeouts are solutions, no input reached the corpus and the fuzzer
aborted with 'No interesting cases found from inputs'. Also drop the
duplicated on_magic definition.
@Wenzel
Wenzel merged commit 79972db into intel:main Oct 28, 2026
24 checks passed
@Wenzel
Wenzel deleted the fix/timeout-objective-392 branch October 28, 2026 09:09
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.

Timeout/hang testcases are not saved to solutions directory due to TimeFeedback in objective chain

1 participant