mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge pull request #5337 from sylvestre/fuzz3
fuzzing: remove some duplicated code + clippy fixes
This commit is contained in:
commit
7f876e4bdb
5 changed files with 47 additions and 57 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
use libc::{dup, dup2, STDOUT_FILENO};
|
||||
use std::ffi::OsString;
|
||||
use std::io;
|
||||
use std::process::Command;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{atomic::AtomicBool, Once};
|
||||
|
@ -31,7 +32,7 @@ pub fn is_gnu_cmd(cmd_path: &str) -> Result<(), std::io::Error> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn generate_and_run_uumain<F>(args: &mut Vec<OsString>, uumain_function: F) -> (String, i32)
|
||||
pub fn generate_and_run_uumain<F>(args: &[OsString], uumain_function: F) -> (String, i32)
|
||||
where
|
||||
F: FnOnce(std::vec::IntoIter<OsString>) -> i32,
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ where
|
|||
|
||||
{
|
||||
unsafe { dup2(pipe_fds[1], STDOUT_FILENO) };
|
||||
uumain_exit_status = uumain_function(args.clone().into_iter());
|
||||
uumain_exit_status = uumain_function(args.to_owned().into_iter());
|
||||
unsafe { dup2(original_stdout_fd, STDOUT_FILENO) };
|
||||
unsafe { libc::close(original_stdout_fd) };
|
||||
}
|
||||
|
@ -75,3 +76,32 @@ where
|
|||
|
||||
(my_output, uumain_exit_status)
|
||||
}
|
||||
|
||||
pub fn run_gnu_cmd(
|
||||
cmd_path: &str,
|
||||
args: &[OsString],
|
||||
check_gnu: bool,
|
||||
) -> Result<(String, i32), io::Error> {
|
||||
if check_gnu {
|
||||
is_gnu_cmd(cmd_path)?; // Check if it's a GNU implementation
|
||||
}
|
||||
|
||||
let mut command = Command::new(cmd_path);
|
||||
for arg in args {
|
||||
command.arg(arg);
|
||||
}
|
||||
|
||||
let output = command.output()?;
|
||||
let exit_code = output.status.code().unwrap_or(-1);
|
||||
if output.status.success() || !check_gnu {
|
||||
Ok((
|
||||
String::from_utf8_lossy(&output.stdout).to_string(),
|
||||
exit_code,
|
||||
))
|
||||
} else {
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("GNU command execution failed with exit code {}", exit_code),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ fuzz_target!(|data: &[u8]| {
|
|||
let args = data
|
||||
.split(|b| *b == delim)
|
||||
.filter_map(|e| std::str::from_utf8(e).ok())
|
||||
.map(|e| OsString::from(e));
|
||||
.map(OsString::from);
|
||||
uumain(args);
|
||||
});
|
||||
|
|
|
@ -12,35 +12,11 @@ use rand::seq::SliceRandom;
|
|||
use rand::Rng;
|
||||
use std::ffi::OsString;
|
||||
|
||||
use std::process::Command;
|
||||
mod fuzz_common;
|
||||
use crate::fuzz_common::generate_and_run_uumain;
|
||||
use crate::fuzz_common::is_gnu_cmd;
|
||||
use crate::fuzz_common::{generate_and_run_uumain, run_gnu_cmd};
|
||||
|
||||
static CMD_PATH: &str = "expr";
|
||||
|
||||
fn run_gnu_expr(args: &[OsString]) -> Result<(String, i32), std::io::Error> {
|
||||
is_gnu_cmd(CMD_PATH)?; // Check if it's a GNU implementation
|
||||
|
||||
let mut command = Command::new(CMD_PATH);
|
||||
for arg in args {
|
||||
command.arg(arg);
|
||||
}
|
||||
let output = command.output()?;
|
||||
let exit_code = output.status.code().unwrap_or(-1);
|
||||
if output.status.success() {
|
||||
Ok((
|
||||
String::from_utf8_lossy(&output.stdout).to_string(),
|
||||
exit_code,
|
||||
))
|
||||
} else {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
format!("GNU expr execution failed with exit code {}", exit_code),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_random_string(max_length: usize) -> String {
|
||||
let mut rng = rand::thread_rng();
|
||||
let valid_utf8: Vec<char> = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
@ -108,10 +84,10 @@ fuzz_target!(|_data: &[u8]| {
|
|||
let mut args = vec![OsString::from("expr")];
|
||||
args.extend(expr.split_whitespace().map(OsString::from));
|
||||
|
||||
let (rust_output, uumain_exit_code) = generate_and_run_uumain(&mut args, uumain);
|
||||
let (rust_output, uumain_exit_code) = generate_and_run_uumain(&args, uumain);
|
||||
|
||||
// Run GNU expr with the provided arguments and compare the output
|
||||
match run_gnu_expr(&args[1..]) {
|
||||
match run_gnu_cmd(CMD_PATH, &args[1..], true) {
|
||||
Ok((gnu_output, gnu_exit_code)) => {
|
||||
let gnu_output = gnu_output.trim().to_owned();
|
||||
if uumain_exit_code != gnu_exit_code {
|
||||
|
@ -120,16 +96,16 @@ fuzz_target!(|_data: &[u8]| {
|
|||
println!("GNU code: {}", gnu_exit_code);
|
||||
panic!("Different error codes");
|
||||
}
|
||||
if rust_output != gnu_output {
|
||||
println!("Expression: {}", expr);
|
||||
println!("Rust output: {}", rust_output);
|
||||
println!("GNU output: {}", gnu_output);
|
||||
panic!("Different output between Rust & GNU");
|
||||
} else {
|
||||
if rust_output == gnu_output {
|
||||
println!(
|
||||
"Outputs matched for expression: {} => Result: {}",
|
||||
expr, rust_output
|
||||
);
|
||||
} else {
|
||||
println!("Expression: {}", expr);
|
||||
println!("Rust output: {}", rust_output);
|
||||
println!("GNU output: {}", gnu_output);
|
||||
panic!("Different output between Rust & GNU");
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
|
|
|
@ -5,6 +5,6 @@ use uucore::parse_glob;
|
|||
|
||||
fuzz_target!(|data: &[u8]| {
|
||||
if let Ok(s) = std::str::from_utf8(data) {
|
||||
_ = parse_glob::from_str(s)
|
||||
_ = parse_glob::from_str(s);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -12,10 +12,8 @@ use rand::seq::SliceRandom;
|
|||
use rand::Rng;
|
||||
use std::ffi::OsString;
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
mod fuzz_common;
|
||||
use crate::fuzz_common::generate_and_run_uumain;
|
||||
use crate::fuzz_common::{generate_and_run_uumain, run_gnu_cmd};
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
enum ArgType {
|
||||
|
@ -30,20 +28,6 @@ enum ArgType {
|
|||
|
||||
static CMD_PATH: &str = "test";
|
||||
|
||||
fn run_gnu_test(args: &[OsString]) -> Result<(String, i32), std::io::Error> {
|
||||
let mut command = Command::new(CMD_PATH);
|
||||
|
||||
for arg in args {
|
||||
command.arg(arg);
|
||||
}
|
||||
let output = command.output()?;
|
||||
let exit_status = output.status.code().unwrap_or(-1); // Capture the exit status code
|
||||
Ok((
|
||||
String::from_utf8_lossy(&output.stdout).to_string(),
|
||||
exit_status,
|
||||
))
|
||||
}
|
||||
|
||||
fn generate_random_string(max_length: usize) -> String {
|
||||
let mut rng = rand::thread_rng();
|
||||
let valid_utf8: Vec<char> = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
@ -158,7 +142,7 @@ fn generate_test_arg() -> String {
|
|||
0 => {
|
||||
arg.push_str(&rng.gen_range(-100..=100).to_string());
|
||||
}
|
||||
1 | 2 | 3 => {
|
||||
1..=3 => {
|
||||
let test_arg = test_args
|
||||
.choose(&mut rng)
|
||||
.expect("Failed to choose a random test argument");
|
||||
|
@ -220,10 +204,10 @@ fuzz_target!(|_data: &[u8]| {
|
|||
args.push(OsString::from(generate_test_arg()));
|
||||
}
|
||||
|
||||
let (rust_output, uumain_exit_status) = generate_and_run_uumain(&mut args, uumain);
|
||||
let (rust_output, uumain_exit_status) = generate_and_run_uumain(&args, uumain);
|
||||
|
||||
// Run GNU test with the provided arguments and compare the output
|
||||
match run_gnu_test(&args[1..]) {
|
||||
match run_gnu_cmd(CMD_PATH, &args[1..], false) {
|
||||
Ok((gnu_output, gnu_exit_status)) => {
|
||||
let gnu_output = gnu_output.trim().to_owned();
|
||||
println!("gnu_exit_status {}", gnu_exit_status);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue