On Thu, Oct 23, 2025 at 03:28:06PM +0200, Frank Busse wrote:
> Hi,
> 
> again found by KLEE:
> 
> ---
> $ printf '\x00\x00\n\x00\x00\x00\x00\x00' > A
> $ ./grep -xsf A
> ERROR: AddressSanitizer: global-buffer-overflow
> $ ./grep -wf A
> ERROR: AddressSanitizer: global-buffer-overflow

The following patch should solve these problems. While we were
analyzing the problem it was discovered that the flag -x doesn't
work well, but that is a different topic to be addessed in a different
commit.

-- >8 --

>From e285ed315fb47fb3775c4ccdcece24b61ed5403b Mon Sep 17 00:00:00 2001
From: "Roberto E. Vargas Caballero" <[email protected]>
Date: Wed, 5 Nov 2025 09:59:44 +0100
Subject: [PATCH] grep: Don't modify constant strings

The pattern pointer was assigned to a constant string and later it was
modified, which is UB. But even worse, as we were trusting the patlen
parameter received, patlen was meaningless after that assignment.

The addpattern() had many problems because it trusted the patlen
parameter, but in some places it used string functions that depend of
having a NUL character creating many problems when embedded NUL characters
were found in the pattern. As mandated by POSIX in [1]:

        The interfaces specified in POSIX.1-2017 do not permit the
        inclusion of a NUL character in an RE or in the string to be
        matched. If during the operation of a standard utility a NUL
        is included in the text designated to be matched, that NUL may
        designate the end of the text string for the purposes of matching.

so, the simples solution is just discard the patlen parameter and call
strlen() in addpattern() and use that as size of the pattern.

[1] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html
---
 grep.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/grep.c b/grep.c
index 1c97807..9b9f5a9 100644
--- a/grep.c
+++ b/grep.c
@@ -10,7 +10,7 @@
 
 enum { Match = 0, NoMatch = 1, Error = 2 };
 
-static void addpattern(const char *, size_t);
+static void addpattern(const char *);
 static void addpatternfile(FILE *);
 static int grep(FILE *, const char *);
 
@@ -37,20 +37,19 @@ struct pattern {
 static SLIST_HEAD(phead, pattern) phead;
 
 static void
-addpattern(const char *pattern, size_t patlen)
+addpattern(const char *pattern)
 {
        struct pattern *pnode;
-       char *tmp;
+       char *tmp, beg[] = "^";
        int bol, eol;
-       size_t len;
-
-       if (!patlen)
-               return;
+       size_t len, patlen;
 
        /* a null BRE/ERE matches every line */
-       if (!Fflag)
+       if (!Fflag) {
                if (pattern[0] == '\0')
-                       pattern = "^";
+                       pattern = beg;
+       }
+       patlen = strlen(pattern);
 
        if (!Fflag && xflag) {
                tmp = enmalloc(Error, patlen + 3);
@@ -93,7 +92,7 @@ addpatternfile(FILE *fp)
        while ((len = getline(&buf, &size, fp)) > 0) {
                if (len > 0 && buf[len - 1] == '\n')
                        buf[len - 1] = '\0';
-               addpattern(buf, (size_t)len);
+               addpattern(buf);
        }
        if (ferror(fp))
                enprintf(Error, "read error:");
-- 
2.45.4


Reply via email to