coreutils/fuzz/uufuzz
Sylvestre Ledru f253efefaa
Some checks failed
CICD / Separate Builds (push) Waiting to run
CICD / Style/cargo-deny (push) Waiting to run
CICD / Style/deps (push) Waiting to run
CICD / Documentation/warnings (push) Waiting to run
CICD / MinRustV (push) Waiting to run
CICD / Safe Traversal Security Check (push) Blocked by required conditions
CICD / Dependencies (push) Waiting to run
CICD / Build/Makefile (push) Blocked by required conditions
CICD / Build/stable (push) Blocked by required conditions
CICD / Build/nightly (push) Blocked by required conditions
CICD / Binary sizes (push) Blocked by required conditions
CICD / Build (push) Blocked by required conditions
CICD / Tests/BusyBox test suite (push) Blocked by required conditions
CICD / Tests/Toybox test suite (push) Blocked by required conditions
CICD / Code Coverage (push) Waiting to run
CICD / Test all features separately (push) Blocked by required conditions
CICD / Build/SELinux (push) Blocked by required conditions
CICD / Build/SELinux-Stubs (Non-Linux) (push) Blocked by required conditions
GnuTests / Run GNU tests (native) (push) Waiting to run
GnuTests / Run GNU tests (SELinux) (push) Waiting to run
GnuTests / Aggregate GNU test results (push) Blocked by required conditions
Android / Test builds (push) Waiting to run
Benchmarks / Run benchmarks (CodSpeed) (push) Waiting to run
Code Quality / Style/format (push) Waiting to run
Code Quality / Style/lint (push) Waiting to run
Code Quality / Style/spelling (push) Waiting to run
Code Quality / Style/toml (push) Waiting to run
Code Quality / Style/Python (push) Waiting to run
Code Quality / Pre-commit hooks (push) Waiting to run
Devcontainer / Verify devcontainer (push) Waiting to run
Check uudoc Documentation Generation / Verify uudoc generates correct documentation (push) Waiting to run
FreeBSD / Style and Lint (push) Waiting to run
FreeBSD / Tests (push) Waiting to run
WSL2 / Test (push) Waiting to run
CheckScripts / ShellScript/Check (push) Has been cancelled
CheckScripts / ShellScript/Format (push) Has been cancelled
prepare version 0.3.0 (#8890)
* prepare version 0.3.0

* also update uu_stdbuf_libstdbuf

* also update fuzz
2025-10-12 13:31:16 +02:00
..
examples uufuzz: add examples and them in the CI 2025-09-06 12:19:40 +02:00
src fuzz: remove a warning 2025-09-06 12:19:40 +02:00
Cargo.toml prepare version 0.3.0 (#8890) 2025-10-12 13:31:16 +02:00
README.md uufuzz: add a README 2025-09-06 12:19:40 +02:00

uufuzz

A Rust library for differential fuzzing of command-line utilities. Originally designed for testing uutils coreutils against GNU coreutils, but can be used to compare any two implementations of command-line tools.

Differential fuzzing is a testing technique that compares the behavior of two implementations of the same functionality using randomly generated inputs. This helps identify bugs, inconsistencies, and security vulnerabilities by finding cases where implementations diverge unexpectedly.

Features

  • Command Execution: Run and capture output from both Rust and reference implementations
  • Result Comparison: Detailed comparison of stdout, stderr, and exit codes with diff output
  • Input Generation: Utilities for generating random strings, files, and test inputs
  • GNU Compatibility: Built-in support for detecting and running GNU coreutils
  • Pretty Output: Colorized and formatted test result display

Usage

Add to your Cargo.toml:

[dependencies]
uufuzz = "0.1.0"

Basic Example

use std::ffi::OsString;
use uufuzz::{generate_and_run_uumain, run_gnu_cmd, compare_result};

// Your utility's main function
fn my_echo_main(args: std::vec::IntoIter<OsString>) -> i32 {
    // Implementation here
    0
}

// Test against GNU implementation
let args = vec![OsString::from("echo"), OsString::from("hello")];

// Run your implementation
let rust_result = generate_and_run_uumain(&args, my_echo_main, None);

// Run GNU implementation
let gnu_result = run_gnu_cmd("echo", &args[1..], false, None).unwrap();

// Compare results
compare_result("echo", "hello", None, &rust_result, &gnu_result, true);

With Pipe Input

let pipe_input = "test data";
let rust_result = generate_and_run_uumain(&args, my_cat_main, Some(pipe_input));
let gnu_result = run_gnu_cmd("cat", &args[1..], false, Some(pipe_input)).unwrap();
compare_result("cat", "", Some(pipe_input), &rust_result, &gnu_result, true);

Random Input Generation

use uufuzz::{generate_random_string, generate_random_file};

// Generate random string up to 50 characters
let random_input = generate_random_string(50);

// Generate random temporary file
let file_path = generate_random_file().expect("Failed to create file");

Use Cases

Fuzzing Testing

Perfect for libFuzzer-based differential fuzzing:

#![no_main]
use libfuzzer_sys::fuzz_target;
use uufuzz::*;

fuzz_target!(|_data: &[u8]| {
    let args = generate_test_args();
    let rust_result = generate_and_run_uumain(&args, my_utility_main, None);
    let gnu_result = run_gnu_cmd("utility", &args[1..], false, None).unwrap();
    compare_result("utility", &format!("{:?}", args), None, &rust_result, &gnu_result, true);
});

Integration Testing

Use in regular test suites to verify compatibility:

#[test]
fn test_basic_functionality() {
    let args = vec![OsString::from("sort"), OsString::from("-n")];
    let input = "3\n1\n2\n";

    let rust_result = generate_and_run_uumain(&args, sort_main, Some(input));
    let gnu_result = run_gnu_cmd("sort", &args[1..], false, Some(input)).unwrap();

    assert_eq!(rust_result.stdout, gnu_result.stdout);
    assert_eq!(rust_result.exit_code, gnu_result.exit_code);
}

Environment Variables

  • LC_ALL=C - Automatically set when running GNU commands for consistent behavior

Platform Support

  • Linux: Full support with GNU coreutils
  • macOS: Works with GNU coreutils via Homebrew (brew install coreutils)
  • Windows: Limited support (depends on available reference implementations)

Examples

The library includes several working examples in the examples/ directory:

Running Examples

# Basic differential comparison
cargo run --example basic_echo

# Pipe input handling
cargo run --example pipe_input

# Simple integration testing (recommended approach)
cargo run --example simple_integration

# Complex integration testing (demonstrates file descriptor handling issues)
cargo run --example integration_testing

License

Licensed under the MIT License, same as uutils coreutils.