Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grep: fix output duplication when number of matches is greater than MAX_MATCHES #1442

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

vchimishuk
Copy link

@vchimishuk vchimishuk commented Sep 29, 2024

When color is enable grep(1) searches for MAX_MATCHES, prints the line and then repeats these steps again untill all matches in the line are found. The issue is that every time grep(1) prints the whole line which leads to the situation when line is duplicated (tripled, quadruple, ...) in stdout.

Bug can be reproduced with the next simple command. It prints line twice when only single line is expected.

$ for i in $(seq 33); do echo -n "foobar"; done | ./grep --color=auto foo


By the way, I tried to run tests in usr.bin/grep/tests folder using kyua test command on main branch and looks like tests are broken or something. Many of them fails with failed: atf-check failed; message.

…AX_MATCHES

When color is enable grep(1) searches for MAX_MATCHES, prints the line and then
repeats these steps again untill all matches in the line are found. The issue
is that every time grep(1) prints the whole line which leads to the situation
when line is duplicated (tripled, quadruple, ...) in stdout.

Bug can be reproduced with the next simple command. It prints line twice when
only single line is expected.

$ for i in $(seq 33); do echo -n "foobar"; done | ./grep --color=auto foo
@jlduran
Copy link
Contributor

jlduran commented Oct 3, 2024

By the way, I tried to run tests in usr.bin/grep/tests folder using kyua test command on main branch and looks like tests are broken or something. Many of them fails with failed: atf-check failed; message.

You should be able to run both test suites, the one from FreeBSD you pointed out and the one from NetBSD (contrib/netbsd-tests/usr.bin/grep).
Both get installed (usually) under /usr/tests, more specifically under usr.bin/grep.

For example:

Tested with Cirrus CI

https://github.com/jlduran/freebsd-src/tree/gh_1442
https://cirrus-ci.com/task/6524118865018880

make -C /usr/src/usr.bin/grep -j$(sysctl -n hw.ncpu) all install
kyua test -k /usr/tests/Kyuafile usr.bin/grep/
usr.bin/grep/grep_freebsd_test:gnuext  ->  passed  [0.045s]
usr.bin/grep/grep_freebsd_test:grep_r_implied  ->  passed  [0.019s]
usr.bin/grep/grep_freebsd_test:rgrep  ->  passed  [0.017s]
usr.bin/grep/grep_freebsd_test:zflag  ->  passed  [0.009s]
usr.bin/grep/grep_test:badcontext  ->  passed  [0.029s]
usr.bin/grep/grep_test:basic  ->  passed  [0.018s]
usr.bin/grep/grep_test:begin_end  ->  passed  [0.019s]
usr.bin/grep/grep_test:binary  ->  passed  [0.011s]
usr.bin/grep/grep_test:binary_flags  ->  passed  [0.044s]
usr.bin/grep/grep_test:cflag  ->  passed  [0.026s]
usr.bin/grep/grep_test:color  ->  passed  [0.033s]
usr.bin/grep/grep_test:context  ->  passed  [0.043s]
usr.bin/grep/grep_test:context2  ->  passed  [0.023s]
usr.bin/grep/grep_test:egrep  ->  passed  [0.016s]
usr.bin/grep/grep_test:egrep_empty_invalid  ->  passed  [0.014s]
usr.bin/grep/grep_test:egrep_sanity  ->  passed  [0.032s]
usr.bin/grep/grep_test:emptyfile  ->  passed  [0.015s]
usr.bin/grep/grep_test:escmap  ->  passed  [0.013s]
usr.bin/grep/grep_test:excessive_matches  ->  passed  [0.039s]
usr.bin/grep/grep_test:f_file_empty  ->  passed  [0.010s]
usr.bin/grep/grep_test:fgrep_icase  ->  passed  [0.019s]
usr.bin/grep/grep_test:fgrep_multipattern  ->  passed  [0.016s]
usr.bin/grep/grep_test:fgrep_oflag  ->  passed  [0.044s]
usr.bin/grep/grep_test:fgrep_sanity  ->  passed  [0.017s]
usr.bin/grep/grep_test:file_exp  ->  passed  [0.016s]
usr.bin/grep/grep_test:grep_nomatch_flags  ->  passed  [0.053s]
usr.bin/grep/grep_test:grep_sanity  ->  passed  [0.026s]
usr.bin/grep/grep_test:ignore_case  ->  passed  [0.013s]
usr.bin/grep/grep_test:invert  ->  passed  [0.012s]
usr.bin/grep/grep_test:matchall  ->  passed  [0.025s]
usr.bin/grep/grep_test:mflag  ->  passed  [0.021s]
usr.bin/grep/grep_test:mflag_trail_ctx  ->  passed  [0.020s]
usr.bin/grep/grep_test:mmap  ->  passed  [0.018s]
usr.bin/grep/grep_test:negative  ->  passed  [0.012s]
usr.bin/grep/grep_test:nonexistent  ->  passed  [0.010s]
usr.bin/grep/grep_test:ocolor_metadata  ->  passed  [0.034s]
usr.bin/grep/grep_test:oflag_zerolen  ->  passed  [0.047s]
usr.bin/grep/grep_test:recurse  ->  passed  [0.017s]
usr.bin/grep/grep_test:recurse_symlink  ->  passed  [0.016s]
usr.bin/grep/grep_test:wflag_emptypat  ->  passed  [0.019s]
usr.bin/grep/grep_test:whole_line  ->  passed  [0.015s]
usr.bin/grep/grep_test:word_regexps  ->  passed  [0.018s]
usr.bin/grep/grep_test:wv_combo_break  ->  passed  [0.021s]
usr.bin/grep/grep_test:xflag  ->  passed  [0.012s]
usr.bin/grep/grep_test:xflag_emptypat  ->  passed  [0.045s]
usr.bin/grep/grep_test:xflag_emptypat_plus  ->  passed  [0.020s]
usr.bin/grep/grep_test:zerolen  ->  passed  [0.017s]
usr.bin/grep/grep_test:zgrep  ->  passed  [0.019s]
usr.bin/grep/grep_test:zgrep_combined_flags  ->  expected_failure: known but unsolved zgrep wrapper script regression: atf-check failed; see the output of the test for details  [0.029s]
usr.bin/grep/grep_test:zgrep_eflag  ->  passed  [0.023s]
usr.bin/grep/grep_test:zgrep_empty_eflag  ->  passed  [0.017s]
usr.bin/grep/grep_test:zgrep_fflag  ->  passed  [0.023s]
usr.bin/grep/grep_test:zgrep_long_eflag  ->  passed  [0.015s]
usr.bin/grep/grep_test:zgrep_multiple_eflags  ->  expected_failure: known but unsolved zgrep wrapper script regression: atf-check failed; see the output of the test for details  [0.016s]
usr.bin/grep/grep_test:zgrep_multiple_files  ->  passed  [0.033s]
Results file id is usr_tests.20241003-063631-149783
Results saved to /.kyua/store/results.usr_tests.20241003-063631-149783.db
55/55 passed (0 failed)

@vchimishuk
Copy link
Author

vchimishuk commented Oct 3, 2024

You should be able to run both test suites, the one from FreeBSD you pointed out and the one from NetBSD (contrib/netbsd-tests/usr.bin/grep). Both get installed (usually) under /usr/tests, more specifically under usr.bin/grep.

For example:

I see now. So, tests are passing, that's a good news.
Thank you.

@jlduran
Copy link
Contributor

jlduran commented Oct 3, 2024

I've added a dumb test:

jlduran@d2a23d6

It would be good if a regression test is added as well.

Given the test is under contrib, try wrapping it with # Begin FreeBSD and # End FreeBSD comments

@jlduran
Copy link
Contributor

jlduran commented Oct 4, 2024

This is more or less what I have in mind:

--- /dev/null
+++ b/contrib/netbsd-tests/usr.bin/grep/d_color_d.out
@@ -0,0 +1 @@
+�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar�[01;31m�[Kfoo�[m�[Kbar
diff --git a/contrib/netbsd-tests/usr.bin/grep/t_grep.sh b/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
index b1412a7a0715..7b181c1bcc54 100755
--- a/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
+++ b/contrib/netbsd-tests/usr.bin/grep/t_grep.sh
@@ -426,6 +426,12 @@ color_body()
 
 	atf_check -o file:"$(atf_get_srcdir)/d_color_c.out" \
 	    grep --color=always -f grepfile "$(atf_get_srcdir)/d_color_b.in"
+	# Begin FreeBSD
+	MAX_MATCHES=32
+	for _ in $(seq $((MAX_MATCHES + 1))); do printf "%s" "foobar"; done > grepfile
+	atf_check -o file:"$(atf_get_srcdir)/d_color_d.out" \
+	    grep --color=always foo grepfile
+	# End FreeBSD
 }
 
 atf_test_case f_file_empty
diff --git a/usr.bin/grep/tests/Makefile b/usr.bin/grep/tests/Makefile
index b3c79657e53c..1db5ebea5c62 100644
--- a/usr.bin/grep/tests/Makefile
+++ b/usr.bin/grep/tests/Makefile
@@ -12,6 +12,7 @@ ${PACKAGE}FILES+=		d_color_a.out
 ${PACKAGE}FILES+=		d_color_b.in
 ${PACKAGE}FILES+=		d_color_b.out
 ${PACKAGE}FILES+=		d_color_c.out
+${PACKAGE}FILES+=		d_color_d.out
 ${PACKAGE}FILES+=		d_context2_a.out
 ${PACKAGE}FILES+=		d_context2_b.out
 ${PACKAGE}FILES+=		d_context2_c.out

@vchimishuk
Copy link
Author

Thank you, @jlduran. I'll add tests tomorrow. I want to run tests locally to make sure everything is fine.

@vchimishuk
Copy link
Author

@jlduran, I've added a commit with the testcase you proposed. Unfortunately I was not able to run tests locally, looks like I messed up with permissions or something. make buildworld takes 7 hours on my machine, so I left it for now. Hope Github CI verification will do the check.
Thank you for helping with the testcase.

Copy link
Contributor

@jlduran jlduran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thank you!
There should be no need to buildworld, try:

make -C /usr/src/usr.bin/grep -j$(sysctl -n hw.ncpu) all install
kyua test -k /usr/tests/Kyuafile usr.bin/grep/

@@ -426,6 +426,13 @@ color_body()

atf_check -o file:"$(atf_get_srcdir)/d_color_c.out" \
grep --color=always -f grepfile "$(atf_get_srcdir)/d_color_b.in"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This empty line is not present in the NetBSD test suite. While aesthetically pleasing, it worsens the diffs when importing the changes from NetBSD.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Fixed.

@vchimishuk
Copy link
Author

Nice, thank you! There should be no need to buildworld, try:

make -C /usr/src/usr.bin/grep -j$(sysctl -n hw.ncpu) all install
kyua test -k /usr/tests/Kyuafile usr.bin/grep/

Without buildworld /usr/tests/Kyuafile file was missing for me.

I have the next error by the way. But /usr/tests/usr.bin/grep/ folder seems to be fine and contains test files.

$ sudo kyua test -k /usr/tests/Kyuafile usr.bin/grep/
Results file id is usr_tests.20241007-122554-057863          
Results saved to /root/.kyua/store/results.usr_tests.20241007-122554-057863.db
kyua: W: No test cases matched by the filter 'usr.bin/grep'.

@jlduran
Copy link
Contributor

jlduran commented Oct 7, 2024

Nice, thank you! There should be no need to buildworld, try:

make -C /usr/src/usr.bin/grep -j$(sysctl -n hw.ncpu) all install
kyua test -k /usr/tests/Kyuafile usr.bin/grep/

Without buildworld /usr/tests/Kyuafile file was missing for me.

I have the next error by the way. But /usr/tests/usr.bin/grep/ folder seems to be fine and contains test files.

$ sudo kyua test -k /usr/tests/Kyuafile usr.bin/grep/
Results file id is usr_tests.20241007-122554-057863          
Results saved to /root/.kyua/store/results.usr_tests.20241007-122554-057863.db
kyua: W: No test cases matched by the filter 'usr.bin/grep'.

Try changing into the /usr/tests/usr.bin/grep directory and listing the tests:

$ cd /usr/tests/usr.bin/grep
$ kyua list
grep_freebsd_test:gnuext
grep_freebsd_test:grep_r_implied
...

There should be a Kyuafile. If there are no syntax errors with the tests, the list shows up.
You should be able to run the tests:

# kyua test

Or debug a specific test:

# kyua debug grep_test:color
Executing command [ grep --color=auto -e .* -e a /usr/tests/usr.bin/grep/d_color_a.in ]
Executing command [ grep --color=auto -f grepfile /usr/tests/usr.bin/grep/d_color_b.in ]
Executing command [ grep --color=always -f grepfile /usr/tests/usr.bin/grep/d_color_b.in ]
Executing command [ grep --color=always foo grepfile ]
grep_test:color  ->  passed

@vchimishuk
Copy link
Author

kyua works just fine when executing directly from /usr/tests/usr.bin/grep/. Thank you!
I need to learn more about this tool. Using it for the first time.

$ kyua debug grep_test:color
Executing command [ grep --color=auto -e .* -e a /usr/tests/usr.bin/grep/d_color_a.in ]
Executing command [ grep --color=auto -f grepfile /usr/tests/usr.bin/grep/d_color_b.in ]
Executing command [ grep --color=always -f grepfile /usr/tests/usr.bin/grep/d_color_b.in ]
Executing command [ grep --color=always foo grepfile ]
grep_test:color  ->  passed
$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants