grep: fix -x -v with certain pattern orders
authorAri Sundholm <ari@tuxera.com>
Tue, 29 Jan 2019 13:42:57 +0000 (14:42 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 29 Jan 2019 13:42:57 +0000 (14:42 +0100)
We found out that busybox -x -v is a bit broken:

ari@ari-thinkpad:~/busybox$ echo '  aa bb cc' | ./busybox grep -x -e 'aa.*' -e '.*bb.*'
  aa bb cc
ari@ari-thinkpad:~/busybox$ echo '  aa bb cc' | ./busybox grep -x -v -e 'aa.*' -e '.*bb.*'
ari@ari-thinkpad:~/busybox$ echo '  aa bb cc' | ./busybox grep -x -e '.*aa.*' -e 'bb.*'
  aa bb cc
ari@ari-thinkpad:~/busybox$ echo '  aa bb cc' | ./busybox grep -x -v -e '.*aa.*' -e 'bb.*'
  aa bb cc

Last one is wrong.

This patch fixes the issue by making sure that the variable 'found'
never makes a transition from 1 to 0, as this would mean that
grep previously found a match on this input line.

Signed-off-by: Ari Sundholm <ari@tuxera.com>
Signed-off-by: Niko Vähäsarja <niko@tuxera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
findutils/grep.c
testsuite/grep.tests

index a4033a40bcadd48d067eb34ae04b493460b641b3..9d9da422c04758a8346c808ce37c554387f441d6 100644 (file)
@@ -404,7 +404,7 @@ static int grep_file(FILE *file)
 #endif
                                ) {
                                        if (option_mask32 & OPT_x) {
-                                               found = (gl->matched_range.rm_so == 0
+                                               found |= (gl->matched_range.rm_so == 0
                                                         && match_at[gl->matched_range.rm_eo] == '\0');
                                        } else
                                        if (!(option_mask32 & OPT_w)) {
index e578897905e3a0f48b1c3f78937af3bb670f5d35..26f8e69cfd44f08a68128a20035306cffa218bea 100755 (executable)
@@ -177,6 +177,13 @@ testing "grep -w word match second word" \
        "bword,word\n""wordb,word\n""bwordb,word\n" \
        ""
 
+
+testing "grep -x -v -e EXP1 -e EXP2 finds nothing if either EXP matches" \
+       "grep -x -v -e '.*aa.*' -e 'bb.*'; echo \$?" \
+       "1\n" \
+       "" \
+       "  aa bb cc\n"
+
 # -r on symlink to dir should recurse into dir
 mkdir -p grep.testdir/foo
 echo bar > grep.testdir/foo/file