diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d0e1175..fc64451d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ Bug fixes: Fix stdin detection when using PowerShell in UNIX environments. * [BUG #1866](https://github.com/BurntSushi/ripgrep/issues/1866#issuecomment-841635553): Fix bug when computing column numbers in `--vimgrep` mode. +* [BUG #1878](https://github.com/BurntSushi/ripgrep/issues/1878): + Fix bug where `\A` could produce unanchored matches in multiline search. 12.1.1 (2020-05-29) diff --git a/crates/regex/src/non_matching.rs b/crates/regex/src/non_matching.rs index 2270f94d..e2e0755b 100644 --- a/crates/regex/src/non_matching.rs +++ b/crates/regex/src/non_matching.rs @@ -13,7 +13,10 @@ pub fn non_matching_bytes(expr: &Hir) -> ByteSet { /// the given expression. fn remove_matching_bytes(expr: &Hir, set: &mut ByteSet) { match *expr.kind() { - HirKind::Empty | HirKind::Anchor(_) | HirKind::WordBoundary(_) => {} + HirKind::Empty | HirKind::WordBoundary(_) => {} + HirKind::Anchor(_) => { + set.remove(b'\n'); + } HirKind::Literal(hir::Literal::Unicode(c)) => { for &b in c.encode_utf8(&mut [0; 4]).as_bytes() { set.remove(b); diff --git a/tests/regression.rs b/tests/regression.rs index 2935a43e..9aba2746 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -882,3 +882,26 @@ test:3:5:foo quux "; eqnice!(expected, cmd.stdout()); }); + +rgtest!(r1878, |dir: Dir, _: TestCommand| { + dir.create("test", "a\nbaz\nabc\n"); + + // Since ripgrep enables (?m) by default, '^' will match at the beginning + // of a line, even when -U/--multiline is used. + let args = &["-U", "--no-mmap", r"^baz", "test"]; + eqnice!("baz\n", dir.command().args(args).stdout()); + let args = &["-U", "--mmap", r"^baz", "test"]; + eqnice!("baz\n", dir.command().args(args).stdout()); + + // But when (?-m) is disabled, or when \A is used, then there should be no + // matches that aren't anchored to the beginning of the file. + let args = &["-U", "--no-mmap", r"(?-m)^baz", "test"]; + dir.command().args(args).assert_err(); + let args = &["-U", "--mmap", r"(?-m)^baz", "test"]; + dir.command().args(args).assert_err(); + + let args = &["-U", "--no-mmap", r"\Abaz", "test"]; + dir.command().args(args).assert_err(); + let args = &["-U", "--mmap", r"\Abaz", "test"]; + dir.command().args(args).assert_err(); +});