Fix a bad slice into erroring utf-8 buffer (#872)

This commit is contained in:
JT 2022-01-28 15:32:46 -05:00 committed by GitHub
parent 020ad24b25
commit 86eeb4a5e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 44 additions and 19 deletions

View File

@ -121,7 +121,11 @@ impl Command for Open {
let buf_reader = BufReader::new(file); let buf_reader = BufReader::new(file);
let output = PipelineData::RawStream( let output = PipelineData::RawStream(
RawStream::new(Box::new(BufferedReader { input: buf_reader }), ctrlc), RawStream::new(
Box::new(BufferedReader { input: buf_reader }),
ctrlc,
call_span,
),
call_span, call_span,
None, None,
); );

View File

@ -362,6 +362,7 @@ fn response_to_buffer(
input: buffered_input, input: buffered_input,
}), }),
engine_state.ctrlc.clone(), engine_state.ctrlc.clone(),
span,
), ),
span, span,
None, None,

View File

@ -42,11 +42,18 @@ impl Command for StrCollect {
// let output = input.collect_string(&separator.unwrap_or_default(), &config)?; // let output = input.collect_string(&separator.unwrap_or_default(), &config)?;
// Hmm, not sure what we actually want. If you don't use debug_string, Date comes out as human readable // Hmm, not sure what we actually want. If you don't use debug_string, Date comes out as human readable
// which feels funny // which feels funny
#[allow(clippy::needless_collect)] let mut strings: Vec<String> = vec![];
let strings: Vec<String> = input
.into_iter() for value in input {
.map(|value| value.debug_string("\n", &config)) match value {
.collect(); Value::Error { error } => {
return Err(error);
}
value => {
strings.push(value.debug_string("\n", &config));
}
}
}
let output = if let Some(separator) = separator { let output = if let Some(separator) = separator {
strings.join(&separator) strings.join(&separator)

View File

@ -243,7 +243,7 @@ impl ExternalCommand {
let receiver = ChannelReceiver::new(rx); let receiver = ChannelReceiver::new(rx);
Ok(PipelineData::RawStream( Ok(PipelineData::RawStream(
RawStream::new(Box::new(receiver), output_ctrlc), RawStream::new(Box::new(receiver), output_ctrlc, head),
head, head,
None, None,
)) ))

View File

@ -72,6 +72,7 @@ impl Command for Table {
.into_iter(), .into_iter(),
), ),
ctrlc, ctrlc,
head,
), ),
head, head,
None, None,
@ -187,6 +188,7 @@ impl Command for Table {
stream, stream,
}), }),
ctrlc, ctrlc,
head,
), ),
head, head,
None, None,

View File

@ -175,11 +175,14 @@ impl Value {
Value::Binary { val, .. } => Ok(match std::str::from_utf8(val) { Value::Binary { val, .. } => Ok(match std::str::from_utf8(val) {
Ok(s) => s.to_string(), Ok(s) => s.to_string(),
Err(_) => { Err(_) => {
// println!("{:?}", e);
// println!("bytes: {}", pretty_hex::pretty_hex(&val));
// panic!("let's see it");
return Err(ShellError::CantConvert( return Err(ShellError::CantConvert(
"binary".into(),
"string".into(), "string".into(),
"binary".into(),
self.span()?, self.span()?,
)) ));
} }
}), }),
x => Err(ShellError::CantConvert( x => Err(ShellError::CantConvert(
@ -203,8 +206,8 @@ impl Value {
}, },
Err(_) => { Err(_) => {
return Err(ShellError::CantConvert( return Err(ShellError::CantConvert(
"binary".into(),
"string".into(), "string".into(),
"binary".into(),
self.span()?, self.span()?,
)) ))
} }
@ -299,7 +302,7 @@ impl Value {
match self { match self {
Value::Int { val, .. } => Ok(*val), Value::Int { val, .. } => Ok(*val),
x => Err(ShellError::CantConvert( x => Err(ShellError::CantConvert(
"float".into(), "integer".into(),
x.get_type().to_string(), x.get_type().to_string(),
self.span()?, self.span()?,
)), )),

View File

@ -19,13 +19,14 @@ impl RawStream {
pub fn new( pub fn new(
stream: Box<dyn Iterator<Item = Result<Vec<u8>, ShellError>> + Send + 'static>, stream: Box<dyn Iterator<Item = Result<Vec<u8>, ShellError>> + Send + 'static>,
ctrlc: Option<Arc<AtomicBool>>, ctrlc: Option<Arc<AtomicBool>>,
span: Span,
) -> Self { ) -> Self {
Self { Self {
stream, stream,
leftover: vec![], leftover: vec![],
ctrlc, ctrlc,
is_binary: false, is_binary: false,
span: Span::new(0, 0), span,
} }
} }
@ -63,8 +64,10 @@ impl Iterator for RawStream {
match self.stream.next() { match self.stream.next() {
Some(buffer) => match buffer { Some(buffer) => match buffer {
Ok(mut v) => { Ok(mut v) => {
while let Some(b) = self.leftover.pop() { if !self.leftover.is_empty() {
v.insert(0, b); while let Some(b) = self.leftover.pop() {
v.insert(0, b);
}
} }
Some(Ok(Value::Binary { Some(Ok(Value::Binary {
val: v, val: v,
@ -81,8 +84,10 @@ impl Iterator for RawStream {
match self.stream.next() { match self.stream.next() {
Some(buffer) => match buffer { Some(buffer) => match buffer {
Ok(mut v) => { Ok(mut v) => {
while let Some(b) = self.leftover.pop() { if !self.leftover.is_empty() {
v.insert(0, b); while let Some(b) = self.leftover.pop() {
v.insert(0, b);
}
} }
match String::from_utf8(v.clone()) { match String::from_utf8(v.clone()) {
@ -113,8 +118,7 @@ impl Iterator for RawStream {
// Okay, we have a tiny bit of error at the end of the buffer. This could very well be // Okay, we have a tiny bit of error at the end of the buffer. This could very well be
// a character that spans two frames. Since this is the case, remove the error from // a character that spans two frames. Since this is the case, remove the error from
// the current frame an dput it in the leftover buffer. // the current frame an dput it in the leftover buffer.
self.leftover = self.leftover = v[err.utf8_error().valid_up_to()..].to_vec();
v[(err.utf8_error().valid_up_to() + 1)..].to_vec();
let buf = v[0..err.utf8_error().valid_up_to()].to_vec(); let buf = v[0..err.utf8_error().valid_up_to()].to_vec();

View File

@ -120,7 +120,11 @@ fn main() -> Result<()> {
let buf_reader = BufReader::new(stdin); let buf_reader = BufReader::new(stdin);
PipelineData::RawStream( PipelineData::RawStream(
RawStream::new(Box::new(BufferedReader::new(buf_reader)), Some(ctrlc)), RawStream::new(
Box::new(BufferedReader::new(buf_reader)),
Some(ctrlc),
redirect_stdin.span,
),
redirect_stdin.span, redirect_stdin.span,
None, None,
) )