Subject: Re: bug#22181: endless loop in grep 2.22

From: Jim Meyering <[email-masked]>
Date: Fri, 18 Dec 2015 12:52:35 -0800

On Tue, Dec 15, 2015 at 12:20 PM, Christian Boltz <[email-masked]> wrote:
> Hello,
>
> I hit an endless loop in grep 2.22. I can reproduce it with
>
> # grep -obUa -P '\x04\x08\x00profile\x00\x07' cache--usr.sbin.smbldap-useradd
> 16profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> 27801profile
> [...]
>
> I get this line over and over (some minutes long) - but for testing,
> you might want to use   ... | head -n50   to avoid heating your office
> using your computer ;-)
>
> The file needed for the reproducer is attached.
> To make sure you have an unmodified copy - its sha256sum is
> 89f458796dcb1cdcaec534fec84c6c3440844dbd6dc014e51a5d74e9800c2aab
>
> I have more files that can reproduce the endless loop - basically it
> looks like lots of (or all?) AppArmor cache files of profiles that
> contain subprofiles or hats trigger this. OTOH, cache files from single
> profiles don't trigger the endless loop.
>
> As the subject says, I'm using grep 2.22 on openSUSE Tumbleweed.
>
> This bug seems to be a regression. I wasn't able to reproduce this bug
> with grep 2.14, and sarnold on #apparmor also couldn't reproduce it with
> grep 2.21 on Ubuntu. OTOH, he could reproduce the endless loop with
> grep 2.22 on Ubuntu.
>
> I also downloaded and compiled the grep 2.21 and 2.22 tarballs.
> Result (not too surprising):
> - 2.21 works as expected
> - 2.22 enters an endless loop
>
> -> This is clearly a regression between 2.21 and 2.22.
>
>
> For comparison: The expected output (with grep 2.21) is:
>
> #2.21# ./grep -obUa -P '\x04\x08\x00profile\x00\x07' cache--usr.sbin.smbldap-useradd
> 16profile
> 27801profile

Thank you for the report. That is indeed a bug in the latest.
Here's a small reproducer:

  printf '\201ab\0'|LC_ALL=en_US.utf8 grep -oa -P ab

And here is the patch that will form the basis of a complete fix:
diff --git a/src/pcresearch.c b/src/pcresearch.c
index b1f8310..dc68345 100644
--- a/src/pcresearch.c
+++ b/src/pcresearch.c
@@ -289,7 +289,9 @@ Pexecute (char const *buf, size_t size, size_t *match_size,
             break;

           /* Treat the encoding error as data that cannot match.  */
-          p = subject += valid_bytes + 1;
+          subject += valid_bytes + 1;
+          if (p < subject)
+            p = subject;
           bol = false;
         }