diff options
author | Andrew Gallant <jamslam@gmail.com> | 2021-05-30 11:13:27 -0400 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2021-05-31 21:51:18 -0400 |
commit | 12dd455ee9aa731acfeb0d2dfed568a0103cae73 (patch) | |
tree | bfc7ace9721b67e4891600753f2f4657ed9594c7 | |
parent | e6cac8b119d0d50646b3ba1aaf53e648c779901a (diff) |
printer: fix \r\n line terminator handling
This fixes a bug where it was assumed that 'is_suffix' when CRLF
handling was enabled mean that '\r\n' was present. But that's not the
case, and it is intentional that 'is_suffix' only looks for '\n'. (Which
is why #1803 wasn't taken, which tries to fix this by changing
'is_suffix'.)
Fixes #1765, Closes #1803
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | crates/printer/src/standard.rs | 33 | ||||
-rw-r--r-- | tests/regression.rs | 10 |
3 files changed, 41 insertions, 4 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index e322d4d5..19994d23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ Bug fixes: Clarify that CLI invocation must always be valid, regardless of config file. * [BUG #1741](https://github.com/BurntSushi/ripgrep/issues/1741): Fix stdin detection when using PowerShell in UNIX environments. +* [BUG #1765](https://github.com/BurntSushi/ripgrep/issues/1765): + Fix panic when `--crlf` is used in some cases. * [BUG #1816](https://github.com/BurntSushi/ripgrep/issues/1816): Add documentation for glob alternate syntax, e.g., `{a,b,..}`. * [BUG #1847](https://github.com/BurntSushi/ripgrep/issues/1847): diff --git a/crates/printer/src/standard.rs b/crates/printer/src/standard.rs index 943bd794..27f91c0c 100644 --- a/crates/printer/src/standard.rs +++ b/crates/printer/src/standard.rs @@ -1474,7 +1474,10 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> { let lineterm = self.searcher.line_terminator(); if lineterm.is_suffix(&buf[*line]) { let mut end = line.end() - 1; - if lineterm.is_crlf() && buf[end - 1] == b'\r' { + if lineterm.is_crlf() + && end > 0 + && buf.get(end - 1) == Some(&b'\r') + { end -= 1; } *line = line.with_end(end); @@ -1547,11 +1550,12 @@ impl<'a, M: Matcher, W: WriteColor> StandardImpl<'a, M, W> { #[cfg(test)] mod tests { - use grep_regex::RegexMatcher; + use grep_matcher::LineTerminator; + use grep_regex::{RegexMatcher, RegexMatcherBuilder}; use grep_searcher::SearcherBuilder; - use termcolor::NoColor; + use termcolor::{Ansi, NoColor}; - use super::{Standard, StandardBuilder}; + use super::{ColorSpecs, Standard, StandardBuilder}; const SHERLOCK: &'static str = "\ For the Doctor Watsons of this world, as opposed to the Sherlock @@ -1576,6 +1580,10 @@ and exhibited clearly, with a label attached.\ String::from_utf8(printer.get_mut().get_ref().to_owned()).unwrap() } + fn printer_contents_ansi(printer: &mut Standard<Ansi<Vec<u8>>>) -> String { + String::from_utf8(printer.get_mut().get_ref().to_owned()).unwrap() + } + #[test] fn reports_match() { let matcher = RegexMatcher::new("Sherlock").unwrap(); @@ -3388,4 +3396,21 @@ and xxx clearly, with a label attached. "; assert_eq_printed!(expected, got); } + + #[test] + fn regression_search_empty_with_crlf() { + let matcher = + RegexMatcherBuilder::new().crlf(true).build(r"x?").unwrap(); + let mut printer = StandardBuilder::new() + .color_specs(ColorSpecs::default_with_color()) + .build(Ansi::new(vec![])); + SearcherBuilder::new() + .line_terminator(LineTerminator::crlf()) + .build() + .search_reader(&matcher, &b"\n"[..], printer.sink(&matcher)) + .unwrap(); + + let got = printer_contents_ansi(&mut printer); + assert!(!got.is_empty()); + } } diff --git a/tests/regression.rs b/tests/regression.rs index 1c2b5c15..2ecd2399 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -867,6 +867,16 @@ use B; eqnice!("2\n", cmd.stdout()); }); +// See: https://github.com/BurntSushi/ripgrep/issues/1765 +rgtest!(r1765, |dir: Dir, mut cmd: TestCommand| { + dir.create("test", "\n"); + // We need to add --color=always here to force the failure, since the bad + // code path is only triggered when colors are enabled. + cmd.args(&[r"x?", "--crlf", "--color", "always"]); + + assert!(!cmd.stdout().is_empty()); +}); + rgtest!(r1866, |dir: Dir, mut cmd: TestCommand| { dir.create("test", "foobar\nfoobar\nfoo quux"); cmd.args(&[ |