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