Skip to content

feat(fuzzer): add bounded fuzzing and CI action for prism-core - #298

Merged
codeZe-us merged 1 commit into
Boxkit-Labs:mainfrom
Peaostrel:fix/issue-296-fuzzer-ci
Jul 27, 2026
Merged

feat(fuzzer): add bounded fuzzing and CI action for prism-core#298
codeZe-us merged 1 commit into
Boxkit-Labs:mainfrom
Peaostrel:fix/issue-296-fuzzer-ci

Conversation

@Peaostrel

@Peaostrel Peaostrel commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Fixes #296

Added the following:

  • --max-iterations flag in rust-address-fuzzer.
  • JSON summary output (inputs, findings, divergences).
  • Exit non-zero on panics/findings.
  • fuzz.yml GitHub action to run bounded fuzz testing in CI.

Summary by CodeRabbit

  • New Features

    • Added structured JSON reporting for fuzzing runs, including processed inputs, findings, and divergence counts.
    • Added configurable iteration limits for random, corpus, and standard-input fuzzing.
    • Fuzzing now captures parser crashes and saves the triggering input for reproduction.
  • Chores

    • Added automated fuzzing checks for pushes and pull requests, with failure artifacts available for investigation.

@drips-wave

drips-wave Bot commented Jul 27, 2026

Copy link
Copy Markdown

@Peaostrel Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The fuzzer adds bounded execution, structured JSON reporting, parser panic capture with reproducer output, and CI automation that runs the bounded fuzz command and uploads failures.

Changes

Fuzzer reporting and CI execution

Layer / File(s) Summary
Reporting and bounded run orchestration
examples/rust-address-fuzzer/src/report.rs, examples/rust-address-fuzzer/src/main.rs
Adds report counters and JSON output, introduces --max-iterations, routes the limit through fuzzing modes, and exits non-zero for findings or divergences.
Bounded execution and panic capture
examples/rust-address-fuzzer/src/main.rs
Limits corpus and stdin processing, catches parser panics, increments panic statistics, and writes reproducer.txt.
Continuous fuzz workflow
.github/workflows/fuzz.yml
Runs the release fuzzer on pushes to main and pull requests, uploading the reproducer artifact when the job fails.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant FuzzModes
  participant Parser
  participant Report
  participant GitHubActions
  CLI->>FuzzModes: Select mode and max_iterations
  FuzzModes->>Parser: Parse fuzz input
  Parser-->>FuzzModes: Findings, divergences, or panic
  FuzzModes->>Report: Record run metrics
  Report-->>CLI: Print JSON report
  GitHubActions->>CLI: Run bounded release fuzz command
  CLI-->>GitHubActions: Exit status and reproducer.txt
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The workflow only runs on pushes to main and pull requests, not on every push as required by #296. Trigger the fuzz workflow on all push events, and keep the bounded pass, JSON report, and CI failure gate intact.
✅ Passed checks (4 passed)
Check name Status Explanation
Out of Scope Changes check ✅ Passed The changes stay within fuzzing, reporting, CI gating, and reproducer preservation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: bounded fuzzing plus a CI workflow for the fuzzer.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@Peaostrel
Peaostrel force-pushed the fix/issue-296-fuzzer-ci branch from 2c39756 to 54dc0af Compare July 27, 2026 11:24

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/fuzz.yml:
- Around line 3-6: Update the workflow’s on.push trigger to remove the branches
filter, so fuzzing runs on every push while preserving the existing pull_request
trigger.

In `@examples/rust-address-fuzzer/src/main.rs`:
- Line 105: Replace unwrap_or_default() in the corpus line-reading path at
examples/rust-address-fuzzer/src/main.rs:105-105 with explicit error handling
that reports the read or UTF-8 error and terminates with an input-error status
instead of calling fuzz_one on an empty string. Apply the same handling to the
stdin path at examples/rust-address-fuzzer/src/main.rs:116-116.
- Around line 139-142: Update the panic handling in
examples/rust-address-fuzzer/src/main.rs:139-142 around the Err(_) branch to
write each reproducer to a distinct file under reproducers, using the panic
count for uniqueness, and surface any write failure instead of discarding it.
Update .github/workflows/fuzz.yml:23-28 to upload
examples/rust-address-fuzzer/reproducers/** so all captured panic inputs are
retained.

In `@examples/rust-address-fuzzer/src/report.rs`:
- Around line 1-14: Implement the Default trait for Report so Stats::default()
can construct its report field, preserving the zero-value initialization
currently provided by Report::new. Prefer deriving Default on Report and retain
Report::new as appropriate for existing callers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9aed8557-eafc-411e-8414-417c410e7b1e

📥 Commits

Reviewing files that changed from the base of the PR and between d2898d4 and 54dc0af.

📒 Files selected for processing (3)
  • .github/workflows/fuzz.yml
  • examples/rust-address-fuzzer/src/main.rs
  • examples/rust-address-fuzzer/src/report.rs

Comment on lines +3 to +6
on:
push:
branches: ["main"]
pull_request:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Run the fuzzer on every push.

The branch filter limits push-triggered fuzzing to main; direct pushes to other branches are skipped, contrary to the PR objective.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/fuzz.yml around lines 3 - 6, Update the workflow’s on.push
trigger to remove the branches filter, so fuzzing runs on every push while
preserving the existing pull_request trigger.

if let Some(m) = max_iters {
if i >= m { break; }
}
fuzz_one(&line.unwrap_or_default(), verbose, &mut stats);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not fuzz an empty string on input read failure. unwrap_or_default() hides corpus/stdin I/O or UTF-8 errors, inflates inputs_run, and can let CI pass after processing corrupted input.

  • examples/rust-address-fuzzer/src/main.rs#L105-L105: report the line-read error and terminate with an input-error status.
  • examples/rust-address-fuzzer/src/main.rs#L116-L116: apply the same error handling for stdin.
📍 Affects 1 file
  • examples/rust-address-fuzzer/src/main.rs#L105-L105 (this comment)
  • examples/rust-address-fuzzer/src/main.rs#L116-L116
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/rust-address-fuzzer/src/main.rs` at line 105, Replace
unwrap_or_default() in the corpus line-reading path at
examples/rust-address-fuzzer/src/main.rs:105-105 with explicit error handling
that reports the read or UTF-8 error and terminates with an input-error status
instead of calling fuzz_one on an empty string. Apply the same handling to the
stdin path at examples/rust-address-fuzzer/src/main.rs:116-116.

Comment on lines +139 to +142
Err(_) => {
stats.panics += 1;
eprintln!("PANIC ← {input:?}");
let _ = std::fs::write("reproducer.txt", input);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve each distinct panic reproducer. Writing every finding to reproducer.txt overwrites prior failures, and CI uploads only that final file.

  • examples/rust-address-fuzzer/src/main.rs#L139-L142: write each panic to a unique file, such as reproducers/panic-<count>.txt, and surface write failures.
  • .github/workflows/fuzz.yml#L23-L28: upload examples/rust-address-fuzzer/reproducers/** so all captured inputs are retained.
📍 Affects 2 files
  • examples/rust-address-fuzzer/src/main.rs#L139-L142 (this comment)
  • .github/workflows/fuzz.yml#L23-L28
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/rust-address-fuzzer/src/main.rs` around lines 139 - 142, Update the
panic handling in examples/rust-address-fuzzer/src/main.rs:139-142 around the
Err(_) branch to write each reproducer to a distinct file under reproducers,
using the panic count for uniqueness, and surface any write failure instead of
discarding it. Update .github/workflows/fuzz.yml:23-28 to upload
examples/rust-address-fuzzer/reproducers/** so all captured panic inputs are
retained.

Comment on lines +1 to +14
pub struct Report {
pub inputs_run: usize,
pub findings_count: usize,
pub divergences: usize,
}

impl Report {
pub fn new() -> Self {
Self {
inputs_run: 0,
findings_count: 0,
divergences: 0,
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
ast-grep outline examples/rust-address-fuzzer/src/main.rs --items all --type struct,impl
rg -n -A10 -B3 'struct Stats|impl Default for Stats|derive\(.*Default' examples/rust-address-fuzzer/src/main.rs

Repository: Boxkit-Labs/stellar-address-kit

Length of output: 452


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== report.rs =="
cat -n examples/rust-address-fuzzer/src/report.rs

echo
echo "== main.rs stats section =="
sed -n '1,90p' examples/rust-address-fuzzer/src/main.rs

Repository: Boxkit-Labs/stellar-address-kit

Length of output: 3517


Implement Default for Report. Stats derives Default, so Stats::default() requires report::Report: Default; add that impl here, or replace Stats with a manual Default.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/rust-address-fuzzer/src/report.rs` around lines 1 - 14, Implement
the Default trait for Report so Stats::default() can construct its report field,
preserving the zero-value initialization currently provided by Report::new.
Prefer deriving Default on Report and retain Report::new as appropriate for
existing callers.

@codeZe-us
codeZe-us merged commit 46d3b87 into Boxkit-Labs:main Jul 27, 2026
1 of 2 checks passed
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.

Emit a structured findings report and CI gate.

2 participants