Skip to content

Commit fb6afec

Browse files
committed
uufuzz: add a README
1 parent 536abfb commit fb6afec

File tree

1 file changed

+137
-0
lines changed

1 file changed

+137
-0
lines changed

fuzz/uufuzz/README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# uufuzz
2+
3+
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.
4+
5+
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.
6+
7+
## Features
8+
9+
- **Command Execution**: Run and capture output from both Rust and reference implementations
10+
- **Result Comparison**: Detailed comparison of stdout, stderr, and exit codes with diff output
11+
- **Input Generation**: Utilities for generating random strings, files, and test inputs
12+
- **GNU Compatibility**: Built-in support for detecting and running GNU coreutils
13+
- **Pretty Output**: Colorized and formatted test result display
14+
15+
## Usage
16+
17+
Add to your `Cargo.toml`:
18+
19+
```toml
20+
[dependencies]
21+
uufuzz = "0.1.0"
22+
```
23+
24+
### Basic Example
25+
26+
```rust
27+
use std::ffi::OsString;
28+
use uufuzz::{generate_and_run_uumain, run_gnu_cmd, compare_result};
29+
30+
// Your utility's main function
31+
fn my_echo_main(args: std::vec::IntoIter<OsString>) -> i32 {
32+
// Implementation here
33+
0
34+
}
35+
36+
// Test against GNU implementation
37+
let args = vec![OsString::from("echo"), OsString::from("hello")];
38+
39+
// Run your implementation
40+
let rust_result = generate_and_run_uumain(&args, my_echo_main, None);
41+
42+
// Run GNU implementation
43+
let gnu_result = run_gnu_cmd("echo", &args[1..], false, None).unwrap();
44+
45+
// Compare results
46+
compare_result("echo", "hello", None, &rust_result, &gnu_result, true);
47+
```
48+
49+
### With Pipe Input
50+
51+
```rust
52+
let pipe_input = "test data";
53+
let rust_result = generate_and_run_uumain(&args, my_cat_main, Some(pipe_input));
54+
let gnu_result = run_gnu_cmd("cat", &args[1..], false, Some(pipe_input)).unwrap();
55+
compare_result("cat", "", Some(pipe_input), &rust_result, &gnu_result, true);
56+
```
57+
58+
### Random Input Generation
59+
60+
```rust
61+
use uufuzz::{generate_random_string, generate_random_file};
62+
63+
// Generate random string up to 50 characters
64+
let random_input = generate_random_string(50);
65+
66+
// Generate random temporary file
67+
let file_path = generate_random_file().expect("Failed to create file");
68+
```
69+
70+
## Use Cases
71+
72+
### Fuzzing Testing
73+
Perfect for libFuzzer-based differential fuzzing:
74+
75+
```rust
76+
#![no_main]
77+
use libfuzzer_sys::fuzz_target;
78+
use uufuzz::*;
79+
80+
fuzz_target!(|_data: &[u8]| {
81+
let args = generate_test_args();
82+
let rust_result = generate_and_run_uumain(&args, my_utility_main, None);
83+
let gnu_result = run_gnu_cmd("utility", &args[1..], false, None).unwrap();
84+
compare_result("utility", &format!("{:?}", args), None, &rust_result, &gnu_result, true);
85+
});
86+
```
87+
88+
### Integration Testing
89+
Use in regular test suites to verify compatibility:
90+
91+
```rust
92+
#[test]
93+
fn test_basic_functionality() {
94+
let args = vec![OsString::from("sort"), OsString::from("-n")];
95+
let input = "3\n1\n2\n";
96+
97+
let rust_result = generate_and_run_uumain(&args, sort_main, Some(input));
98+
let gnu_result = run_gnu_cmd("sort", &args[1..], false, Some(input)).unwrap();
99+
100+
assert_eq!(rust_result.stdout, gnu_result.stdout);
101+
assert_eq!(rust_result.exit_code, gnu_result.exit_code);
102+
}
103+
```
104+
105+
## Environment Variables
106+
107+
- `LC_ALL=C` - Automatically set when running GNU commands for consistent behavior
108+
109+
## Platform Support
110+
111+
- **Linux**: Full support with GNU coreutils
112+
- **macOS**: Works with GNU coreutils via Homebrew (`brew install coreutils`)
113+
- **Windows**: Limited support (depends on available reference implementations)
114+
115+
## Examples
116+
117+
The library includes several working examples in the `examples/` directory:
118+
119+
### Running Examples
120+
121+
```bash
122+
# Basic differential comparison
123+
cargo run --example basic_echo
124+
125+
# Pipe input handling
126+
cargo run --example pipe_input
127+
128+
# Simple integration testing (recommended approach)
129+
cargo run --example simple_integration
130+
131+
# Complex integration testing (demonstrates file descriptor handling issues)
132+
cargo run --example integration_testing
133+
```
134+
135+
## License
136+
137+
Licensed under the MIT License, same as uutils coreutils.

0 commit comments

Comments
 (0)