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
