mirror of
https://github.com/uutils/coreutils.git
synced 2025-12-23 08:47:37 +00:00
Merge pull request #8435 from julian-klode/tr-enomem
tr: fix high memory use, possible heap exhaustion
This commit is contained in:
commit
76bb429d19
2 changed files with 14 additions and 13 deletions
|
|
@ -672,15 +672,17 @@ where
|
|||
R: BufRead,
|
||||
W: Write,
|
||||
{
|
||||
let mut buf = Vec::new();
|
||||
let mut buf = [0; 8192];
|
||||
let mut output_buf = Vec::new();
|
||||
|
||||
while let Ok(length) = input.read_until(b'\n', &mut buf) {
|
||||
while let Ok(length) = input.read(&mut buf[..]) {
|
||||
if length == 0 {
|
||||
break; // EOF reached
|
||||
}
|
||||
|
||||
let filtered = buf.iter().filter_map(|&c| translator.translate(c));
|
||||
let filtered = buf[..length]
|
||||
.iter()
|
||||
.filter_map(|&c| translator.translate(c));
|
||||
output_buf.extend(filtered);
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
|
@ -698,7 +700,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
buf.clear();
|
||||
output_buf.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use operation::{
|
|||
translate_input,
|
||||
};
|
||||
use std::ffi::OsString;
|
||||
use std::io::{BufWriter, Write, stdin, stdout};
|
||||
use std::io::{Write, stdin, stdout};
|
||||
use uucore::display::Quotable;
|
||||
use uucore::error::{FromIo, UResult, USimpleError, UUsageError};
|
||||
use uucore::fs::is_stdin_directory;
|
||||
|
|
@ -107,7 +107,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
|
||||
let stdin = stdin();
|
||||
let mut locked_stdin = stdin.lock();
|
||||
let mut buffered_stdout = BufWriter::new(stdout().lock());
|
||||
let mut locked_stdout = stdout().lock();
|
||||
|
||||
// According to the man page: translating only happens if deleting or if a second set is given
|
||||
let translating = !delete_flag && sets.len() > 1;
|
||||
|
|
@ -131,34 +131,34 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
|
|||
let delete_op = DeleteOperation::new(set1);
|
||||
let squeeze_op = SqueezeOperation::new(set2);
|
||||
let op = delete_op.chain(squeeze_op);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
|
||||
} else {
|
||||
let op = DeleteOperation::new(set1);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
|
||||
}
|
||||
} else if squeeze_flag {
|
||||
if sets_len == 1 {
|
||||
let op = SqueezeOperation::new(set1);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
|
||||
} else {
|
||||
let translate_op = TranslateOperation::new(set1, set2.clone())?;
|
||||
let squeeze_op = SqueezeOperation::new(set2);
|
||||
let op = translate_op.chain(squeeze_op);
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
|
||||
}
|
||||
} else {
|
||||
let op = TranslateOperation::new(set1, set2)?;
|
||||
translate_input(&mut locked_stdin, &mut buffered_stdout, op)?;
|
||||
translate_input(&mut locked_stdin, &mut locked_stdout, op)?;
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
buffered_stdout
|
||||
locked_stdout
|
||||
.flush()
|
||||
.map_err_context(|| translate!("tr-error-write-error"))?;
|
||||
|
||||
// SIGPIPE is not available on Windows.
|
||||
#[cfg(target_os = "windows")]
|
||||
match buffered_stdout.flush() {
|
||||
match locked_stdout.flush() {
|
||||
Ok(()) => {}
|
||||
Err(err) if err.kind() == std::io::ErrorKind::BrokenPipe => std::process::exit(13),
|
||||
Err(err) => return Err(err.map_err_context(|| translate!("tr-error-write-error"))),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue