File: fuzzing_simulation.rs

package info (click to toggle)
rust-coreutils 0.7.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 505,620 kB
  • sloc: ansic: 103,594; asm: 28,570; sh: 8,910; python: 5,581; makefile: 472; cpp: 97; javascript: 72
file content (163 lines) | stat: -rw-r--r-- 5,271 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.

use rand::Rng;
use std::ffi::OsString;
use uufuzz::{generate_and_run_uumain, generate_random_string, run_gnu_cmd};

// Mock echo implementation with some bugs for demonstration
fn mock_buggy_echo_main(args: std::vec::IntoIter<OsString>) -> i32 {
    let args: Vec<OsString> = args.collect();

    let mut should_add_newline = true;
    let mut enable_escapes = false;
    let mut start_index = 1;

    // Parse arguments (simplified)
    for arg in args.iter().skip(1) {
        let arg_str = arg.to_string_lossy();
        if arg_str == "-n" {
            should_add_newline = false;
            start_index += 1;
        } else if arg_str == "-e" {
            enable_escapes = true;
            start_index += 1;
        } else {
            break;
        }
    }

    // Print arguments
    for (i, arg) in args.iter().skip(start_index).enumerate() {
        if i > 0 {
            print!(" ");
        }
        let arg_str = arg.to_string_lossy();

        if enable_escapes {
            // Simulate a bug: incomplete escape sequence handling
            let processed = arg_str.replace("\\n", "\n").replace("\\t", "\t");
            print!("{}", processed);
        } else {
            print!("{}", arg_str);
        }
    }

    if should_add_newline {
        println!();
    }

    0
}

// Generate test arguments for echo command
fn generate_echo_args() -> Vec<OsString> {
    let mut rng = rand::rng();
    let mut args = vec![OsString::from("echo")];

    // Randomly add flags
    if rng.random_bool(0.3) {
        // 30% chance
        args.push(OsString::from("-n"));
    }
    if rng.random_bool(0.2) {
        // 20% chance
        args.push(OsString::from("-e"));
    }

    // Add 1-3 random string arguments
    let num_args = rng.random_range(1..=3);
    for _ in 0..num_args {
        let arg = generate_random_string(rng.random_range(1..=15));
        args.push(OsString::from(arg));
    }

    args
}

fn main() {
    println!("=== Fuzzing Simulation uufuzz Example ===");
    println!("This simulates how libFuzzer would test our echo implementation");
    println!("against GNU echo with random inputs.\n");

    let num_tests = 10;
    let mut passed = 0;
    let mut failed = 0;

    for i in 1..=num_tests {
        println!("--- Fuzz Test {} ---", i);

        let args = generate_echo_args();
        println!(
            "Testing with args: {:?}",
            args.iter().map(|s| s.to_string_lossy()).collect::<Vec<_>>()
        );

        // Run our implementation
        let rust_result = generate_and_run_uumain(&args, mock_buggy_echo_main, None);

        // Run GNU implementation
        match run_gnu_cmd("echo", &args[1..], false, None) {
            Ok(gnu_result) => {
                // Check if results match
                let stdout_match = rust_result.stdout.trim() == gnu_result.stdout.trim();
                let exit_code_match = rust_result.exit_code == gnu_result.exit_code;

                if stdout_match && exit_code_match {
                    println!("✓ PASS: Implementations match");
                    passed += 1;
                } else {
                    println!("✗ FAIL: Implementations differ");
                    failed += 1;

                    // Show the difference in a controlled way (not panicking like compare_result)
                    if !stdout_match {
                        println!("  Stdout difference:");
                        println!(
                            "    Ours: '{}'",
                            rust_result.stdout.trim().replace('\n', "\\n")
                        );
                        println!(
                            "    GNU:  '{}'",
                            gnu_result.stdout.trim().replace('\n', "\\n")
                        );
                    }
                    if !exit_code_match {
                        println!(
                            "  Exit code difference: {} vs {}",
                            rust_result.exit_code, gnu_result.exit_code
                        );
                    }
                }
            }
            Err(error_result) => {
                println!("⚠ GNU echo not available: {}", error_result.stderr);
                println!("  Our result: '{}'", rust_result.stdout.trim());
                // Don't count this as pass or fail
                continue;
            }
        }

        println!();
    }

    println!("=== Fuzzing Results ===");
    println!("Total tests: {}", num_tests);
    println!("Passed: {}", passed);
    println!("Failed: {}", failed);

    if failed > 0 {
        println!(
            "\n⚠ Found {} discrepancies! In real fuzzing, these would be investigated.",
            failed
        );
        println!("This demonstrates how differential fuzzing can find bugs in implementations.");
    } else {
        println!("\n✓ All tests passed! The implementations appear compatible.");
    }

    println!("\nIn a real libfuzzer setup, this would run thousands of iterations");
    println!("automatically with more sophisticated input generation.");
}