aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcontrib/netbsd-tests/usr.bin/grep/t_grep.sh17
-rw-r--r--usr.bin/grep/util.c21
2 files changed, 37 insertions, 1 deletions
diff --git a/contrib/netbsd-tests/usr.bin/grep/t_grep.sh b/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
index ef3f0617465e..d2539a8250de 100755
--- a/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
+++ b/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
@@ -907,6 +907,22 @@ mflag_body()
atf_check -o inline:"test1:2\n" grep -m 2 -EHc "a|b|e|f" test1
}
+atf_test_case mflag_trail_ctx
+mflag_trail_ctx_head()
+{
+ atf_set "descr" "Check proper handling of -m with trailing context (PR 253350)"
+}
+mflag_trail_ctx_body()
+{
+ printf "foo\nfoo\nbar\nfoo\nbar\nfoo\nbar\n" > test1
+
+ # Should pick up the next line after matching the first.
+ atf_check -o inline:"foo\nfoo\n" grep -A1 -m1 foo test1
+
+ # Make sure the trailer is picked up as a non-match!
+ atf_check -o inline:"1:foo\n2-foo\n" grep -A1 -nm1 foo test1
+}
+
atf_test_case zgrep_multiple_files
zgrep_multiple_files_head()
{
@@ -978,6 +994,7 @@ atf_init_test_cases()
atf_add_test_case fgrep_oflag
atf_add_test_case cflag
atf_add_test_case mflag
+ atf_add_test_case mflag_trail_ctx
atf_add_test_case zgrep_multiple_files
# End FreeBSD
}
diff --git a/usr.bin/grep/util.c b/usr.bin/grep/util.c
index f22b7abd79ef..a2520e24de8e 100644
--- a/usr.bin/grep/util.c
+++ b/usr.bin/grep/util.c
@@ -252,6 +252,16 @@ static bool
procmatches(struct mprintc *mc, struct parsec *pc, bool matched)
{
+ if (mflag && mcount <= 0) {
+ /*
+ * We already hit our match count, but we need to keep dumping
+ * lines until we've lost our tail.
+ */
+ grep_printline(&pc->ln, '-');
+ mc->tail--;
+ return (mc->tail != 0);
+ }
+
/*
* XXX TODO: This should loop over pc->matches and handle things on a
* line-by-line basis, setting up a `struct str` as needed.
@@ -265,7 +275,7 @@ procmatches(struct mprintc *mc, struct parsec *pc, bool matched)
/* XXX TODO: Decrement by number of matched lines */
mcount -= 1;
if (mcount <= 0)
- return (false);
+ return (mc->tail != 0);
}
} else if (mc->doctx)
procmatch_nomatch(mc, pc);
@@ -357,6 +367,15 @@ procfile(const char *fn)
return (0);
}
+ if (mflag && mcount <= 0) {
+ /*
+ * Short-circuit, already hit match count and now we're
+ * just picking up any remaining pieces.
+ */
+ if (!procmatches(&mc, &pc, false))
+ break;
+ continue;
+ }
line_matched = procline(&pc) == !vflag;
if (line_matched)
++lines;