1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

Merge pull request #5758 from sylvestre/fuzz-thread

fuzz: use thread to bypass the limitation of output
This commit is contained in:
Daniel Hofstetter 2024-01-03 14:47:52 +01:00 committed by GitHub
commit f3833bb652
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 24 additions and 24 deletions

View file

@ -48,7 +48,7 @@ jobs:
- { name: fuzz_expr, should_pass: true } - { name: fuzz_expr, should_pass: true }
- { name: fuzz_printf, should_pass: false } - { name: fuzz_printf, should_pass: false }
- { name: fuzz_echo, should_pass: true } - { name: fuzz_echo, should_pass: true }
# - { name: fuzz_seq, should_pass: false } - { name: fuzz_seq, should_pass: false }
- { name: fuzz_parse_glob, should_pass: true } - { name: fuzz_parse_glob, should_pass: true }
- { name: fuzz_parse_size, should_pass: true } - { name: fuzz_parse_size, should_pass: true }
- { name: fuzz_parse_time, should_pass: true } - { name: fuzz_parse_time, should_pass: true }

View file

@ -8,12 +8,12 @@ use libc::{close, dup, dup2, pipe, STDERR_FILENO, STDOUT_FILENO};
use rand::prelude::SliceRandom; use rand::prelude::SliceRandom;
use rand::Rng; use rand::Rng;
use std::ffi::OsString; use std::ffi::OsString;
use std::io;
use std::io::{Seek, SeekFrom, Write}; use std::io::{Seek, SeekFrom, Write};
use std::os::fd::{AsRawFd, RawFd}; use std::os::fd::{AsRawFd, RawFd};
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use std::sync::{atomic::AtomicBool, Once}; use std::sync::{atomic::AtomicBool, Once};
use std::{io, thread};
/// Represents the result of running a command, including its standard output, /// Represents the result of running a command, including its standard output,
/// standard error, and exit code. /// standard error, and exit code.
@ -56,7 +56,7 @@ pub fn generate_and_run_uumain<F>(
pipe_input: Option<&str>, pipe_input: Option<&str>,
) -> CommandResult ) -> CommandResult
where where
F: FnOnce(std::vec::IntoIter<OsString>) -> i32, F: FnOnce(std::vec::IntoIter<OsString>) -> i32 + Send + 'static,
{ {
// Duplicate the stdout and stderr file descriptors // Duplicate the stdout and stderr file descriptors
let original_stdout_fd = unsafe { dup(STDOUT_FILENO) }; let original_stdout_fd = unsafe { dup(STDOUT_FILENO) };
@ -68,6 +68,7 @@ where
exit_code: -1, exit_code: -1,
}; };
} }
println!("Running test {:?}", &args[0..]); println!("Running test {:?}", &args[0..]);
let mut pipe_stdout_fds = [-1; 2]; let mut pipe_stdout_fds = [-1; 2];
let mut pipe_stderr_fds = [-1; 2]; let mut pipe_stderr_fds = [-1; 2];
@ -120,10 +121,20 @@ where
None None
}; };
let uumain_exit_status = uumain_function(args.to_owned().into_iter()); let (uumain_exit_status, captured_stdout, captured_stderr) = thread::scope(|s| {
let out = s.spawn(|| read_from_fd(pipe_stdout_fds[0]));
let err = s.spawn(|| read_from_fd(pipe_stderr_fds[0]));
let status = uumain_function(args.to_owned().into_iter());
io::stdout().flush().unwrap(); io::stdout().flush().unwrap();
io::stderr().flush().unwrap(); io::stderr().flush().unwrap();
unsafe {
close(pipe_stdout_fds[1]);
close(pipe_stderr_fds[1]);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
(status, out.join().unwrap(), err.join().unwrap())
});
// Restore the original stdout and stderr // Restore the original stdout and stderr
if unsafe { dup2(original_stdout_fd, STDOUT_FILENO) } == -1 if unsafe { dup2(original_stdout_fd, STDOUT_FILENO) } == -1
@ -135,13 +146,6 @@ where
exit_code: -1, exit_code: -1,
}; };
} }
unsafe {
close(original_stdout_fd);
close(original_stderr_fd);
close(pipe_stdout_fds[1]);
close(pipe_stderr_fds[1]);
}
// Restore the original stdin if it was modified // Restore the original stdin if it was modified
if let Some(fd) = original_stdin_fd { if let Some(fd) = original_stdin_fd {
@ -155,18 +159,14 @@ where
unsafe { close(fd) }; unsafe { close(fd) };
} }
let captured_stdout = read_from_fd(pipe_stdout_fds[0]).trim().to_string(); CommandResult {
let captured_stderr = read_from_fd(pipe_stderr_fds[0]).to_string(); stdout: captured_stdout,
let captured_stderr = captured_stderr stderr: captured_stderr
.split_once(':') .split_once(':')
.map(|x| x.1) .map(|x| x.1)
.unwrap_or("") .unwrap_or("")
.trim() .trim()
.to_string(); .to_string(),
CommandResult {
stdout: captured_stdout,
stderr: captured_stderr,
exit_code: uumain_exit_status, exit_code: uumain_exit_status,
} }
} }