Skip to content

Commit

Permalink
Limit line length to 100 MB to not exhaust system memory on /dev/zero
Browse files Browse the repository at this point in the history
  • Loading branch information
Enselic committed Dec 6, 2021
1 parent 7fceb48 commit b19e69d
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
- Python syntax highlighting no longer suffers from abysmal performance in specific scenarios. See #1688 (@keith-hall)
- First line not shown in diff context. See #1891 (@divagant-martian)
- Do not ignore syntaxes that handle file names with a `*.conf` extension. See #1703 (@cbolgiano)
- Limit line length to 100 MB to not exhaust system memory on `/dev/zero`. See #1972 (@Enselic)

## Performance

Expand Down
16 changes: 14 additions & 2 deletions src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ pub(crate) struct InputReader<'a> {
impl<'a> InputReader<'a> {
fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
let mut first_line = vec![];
reader.read_until(b'\n', &mut first_line).ok();
Self::read_line_safely(&mut reader, &mut first_line).ok();

let content_type = if first_line.is_empty() {
None
Expand All @@ -276,14 +276,26 @@ impl<'a> InputReader<'a> {
return Ok(true);
}

let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
let res = Self::read_line_safely(&mut self.inner, buf).map(|size| size > 0)?;

if self.content_type == Some(ContentType::UTF_16LE) {
let _ = self.inner.read_until(0x00, buf);
}

Ok(res)
}

fn read_line_safely<R: BufRead + 'a>(reader: &mut R, buf: &mut Vec<u8>) -> io::Result<usize> {
let limit = 100_000_000_usize;

match reader.take(limit as u64).read_until(b'\n', buf) {
Ok(n) if n == limit => Err(io::Error::new(
io::ErrorKind::Other,
"Lines longer than 100 MB are not supported",
)),
r => r,
}
}
}

#[test]
Expand Down
12 changes: 12 additions & 0 deletions tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,18 @@ fn no_args_doesnt_break() {
assert!(exit_status.success());
}

#[cfg(unix)]
#[test]
fn dev_zero() {
bat()
.arg("/dev/zero")
.assert()
.failure()
.stderr(predicate::str::contains(
"Lines longer than 100 MB are not supported",
));
}

#[test]
fn tabs_numbers() {
bat()
Expand Down

0 comments on commit b19e69d

Please # to comment.