Use bytes, not strings, for stdio observers (#885)
Previously, the `CommandExecutor` attempted to decode its child process's stdout and stderr as UTF-8 `String`s. This could fail if the output was not UTF-8. However, the `Std{Out,Err}Observer`s should probably be able to be used in such a situation - Consider fuzzing `echo` with a random `BytesInput`. The fix is to not decode the output, but rather directly store and provide the bytes of stdout/stderr in the observers.
This commit is contained in:
parent
1486c204eb
commit
893f284482
@ -1,5 +1,5 @@
|
|||||||
//! The command executor executes a sub program for each run
|
//! The command executor executes a sub program for each run
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::vec::Vec;
|
||||||
use core::{
|
use core::{
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
@ -335,21 +335,21 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.observers.observes_stderr() {
|
if self.observers.observes_stderr() {
|
||||||
let mut stderr = String::new();
|
let mut stderr = Vec::new();
|
||||||
child.stderr.as_mut().ok_or_else(|| {
|
child.stderr.as_mut().ok_or_else(|| {
|
||||||
Error::illegal_state(
|
Error::illegal_state(
|
||||||
"Observer tries to read stderr, but stderr was not `Stdio::pipe` in CommandExecutor",
|
"Observer tries to read stderr, but stderr was not `Stdio::pipe` in CommandExecutor",
|
||||||
)
|
)
|
||||||
})?.read_to_string(&mut stderr)?;
|
})?.read_to_end(&mut stderr)?;
|
||||||
self.observers.observe_stderr(&stderr);
|
self.observers.observe_stderr(&stderr);
|
||||||
}
|
}
|
||||||
if self.observers.observes_stdout() {
|
if self.observers.observes_stdout() {
|
||||||
let mut stdout = String::new();
|
let mut stdout = Vec::new();
|
||||||
child.stdout.as_mut().ok_or_else(|| {
|
child.stdout.as_mut().ok_or_else(|| {
|
||||||
Error::illegal_state(
|
Error::illegal_state(
|
||||||
"Observer tries to read stdout, but stdout was not `Stdio::pipe` in CommandExecutor",
|
"Observer tries to read stdout, but stdout was not `Stdio::pipe` in CommandExecutor",
|
||||||
)
|
)
|
||||||
})?.read_to_string(&mut stdout)?;
|
})?.read_to_end(&mut stdout)?;
|
||||||
self.observers.observe_stdout(&stdout);
|
self.observers.observe_stdout(&stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,13 +151,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Runs `observe_stdout` for all stdout observers in the list
|
/// Runs `observe_stdout` for all stdout observers in the list
|
||||||
fn observe_stdout(&mut self, stdout: &str) {
|
fn observe_stdout(&mut self, stdout: &[u8]) {
|
||||||
self.primary.as_mut().observe_stderr(stdout);
|
self.primary.as_mut().observe_stderr(stdout);
|
||||||
self.secondary.as_mut().observe_stderr(stdout);
|
self.secondary.as_mut().observe_stderr(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs `observe_stderr` for all stderr observers in the list
|
/// Runs `observe_stderr` for all stderr observers in the list
|
||||||
fn observe_stderr(&mut self, stderr: &str) {
|
fn observe_stderr(&mut self, stderr: &[u8]) {
|
||||||
self.primary.as_mut().observe_stderr(stderr);
|
self.primary.as_mut().observe_stderr(stderr);
|
||||||
self.secondary.as_mut().observe_stderr(stderr);
|
self.secondary.as_mut().observe_stderr(stderr);
|
||||||
}
|
}
|
||||||
|
@ -106,13 +106,13 @@ where
|
|||||||
/// To use this, always return `true` from `observes_stdout`
|
/// To use this, always return `true` from `observes_stdout`
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn observe_stdout(&mut self, stdout: &str) {}
|
fn observe_stdout(&mut self, stdout: &[u8]) {}
|
||||||
|
|
||||||
/// React to new `stderr`
|
/// React to new `stderr`
|
||||||
/// To use this, always return `true` from `observes_stderr`
|
/// To use this, always return `true` from `observes_stderr`
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn observe_stderr(&mut self, stderr: &str) {}
|
fn observe_stderr(&mut self, stderr: &[u8]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the observer type shared across traits of the type.
|
/// Defines the observer type shared across traits of the type.
|
||||||
@ -155,9 +155,9 @@ where
|
|||||||
fn observes_stderr(&self) -> bool;
|
fn observes_stderr(&self) -> bool;
|
||||||
|
|
||||||
/// Runs `observe_stdout` for all stdout observers in the list
|
/// Runs `observe_stdout` for all stdout observers in the list
|
||||||
fn observe_stdout(&mut self, stdout: &str);
|
fn observe_stdout(&mut self, stdout: &[u8]);
|
||||||
/// Runs `observe_stderr` for all stderr observers in the list
|
/// Runs `observe_stderr` for all stderr observers in the list
|
||||||
fn observe_stderr(&mut self, stderr: &str);
|
fn observe_stderr(&mut self, stderr: &[u8]);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> ObserversTuple<S> for ()
|
impl<S> ObserversTuple<S> for ()
|
||||||
@ -205,12 +205,12 @@ where
|
|||||||
/// Runs `observe_stdout` for all stdout observers in the list
|
/// Runs `observe_stdout` for all stdout observers in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn observe_stdout(&mut self, stdout: &str) {}
|
fn observe_stdout(&mut self, stdout: &[u8]) {}
|
||||||
|
|
||||||
/// Runs `observe_stderr` for all stderr observers in the list
|
/// Runs `observe_stderr` for all stderr observers in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn observe_stderr(&mut self, stderr: &str) {}
|
fn observe_stderr(&mut self, stderr: &[u8]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Head, Tail, S> ObserversTuple<S> for (Head, Tail)
|
impl<Head, Tail, S> ObserversTuple<S> for (Head, Tail)
|
||||||
@ -263,14 +263,14 @@ where
|
|||||||
|
|
||||||
/// Runs `observe_stdout` for all stdout observers in the list
|
/// Runs `observe_stdout` for all stdout observers in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observe_stdout(&mut self, stdout: &str) {
|
fn observe_stdout(&mut self, stdout: &[u8]) {
|
||||||
self.0.observe_stdout(stdout);
|
self.0.observe_stdout(stdout);
|
||||||
self.1.observe_stdout(stdout);
|
self.1.observe_stdout(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs `observe_stderr` for all stderr observers in the list
|
/// Runs `observe_stderr` for all stderr observers in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observe_stderr(&mut self, stderr: &str) {
|
fn observe_stderr(&mut self, stderr: &[u8]) {
|
||||||
self.0.observe_stderr(stderr);
|
self.0.observe_stderr(stderr);
|
||||||
self.1.observe_stderr(stderr);
|
self.1.observe_stderr(stderr);
|
||||||
}
|
}
|
||||||
@ -991,10 +991,10 @@ pub mod pybind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observe_stderr(&mut self, _: &str) {}
|
fn observe_stderr(&mut self, _: &[u8]) {}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn observe_stdout(&mut self, _: &str) {}
|
fn observe_stdout(&mut self, _: &[u8]) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchName for PythonObserversTuple {
|
impl MatchName for PythonObserversTuple {
|
||||||
|
@ -269,8 +269,8 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Do nothing on new `stderr`
|
/// Do nothing on new `stderr`
|
||||||
fn observe_stderr(&mut self, stderr: &str) {
|
fn observe_stderr(&mut self, stderr: &[u8]) {
|
||||||
self.parse_asan_output(stderr);
|
self.parse_asan_output(&String::from_utf8_lossy(stderr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
//! For example, they are supported on the [`crate::executors::CommandExecutor`].
|
//! For example, they are supported on the [`crate::executors::CommandExecutor`].
|
||||||
|
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ pub struct StdOutObserver {
|
|||||||
/// The name of the observer.
|
/// The name of the observer.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
/// The stdout of the target during its last execution.
|
/// The stdout of the target during its last execution.
|
||||||
pub stdout: Option<String>,
|
pub stdout: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An observer that captures stdout of a target.
|
/// An observer that captures stdout of a target.
|
||||||
@ -37,7 +38,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// React to new `stdout`
|
/// React to new `stdout`
|
||||||
fn observe_stdout(&mut self, stdout: &str) {
|
fn observe_stdout(&mut self, stdout: &[u8]) {
|
||||||
self.stdout = Some(stdout.into());
|
self.stdout = Some(stdout.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,7 +56,7 @@ pub struct StdErrObserver {
|
|||||||
/// The name of the observer.
|
/// The name of the observer.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
/// The stderr of the target during its last execution.
|
/// The stderr of the target during its last execution.
|
||||||
pub stderr: Option<String>,
|
pub stderr: Option<Vec<u8>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An observer that captures stderr of a target.
|
/// An observer that captures stderr of a target.
|
||||||
@ -77,7 +78,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// React to new `stderr`
|
/// React to new `stderr`
|
||||||
fn observe_stderr(&mut self, stderr: &str) {
|
fn observe_stderr(&mut self, stderr: &[u8]) {
|
||||||
self.stderr = Some(stderr.into());
|
self.stderr = Some(stderr.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user