[hackers] [sbase] grep: Don't modify constant strings || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Wed, 5 Nov 2025 14:07:23 +0100 (CET)

commit ae7bfda8f6f1b3f1951e8e69b8910d5171bf6236
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.net>
AuthorDate: Wed Nov 5 09:59:44 2025 +0100
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.net>
CommitDate: Wed Nov 5 14:07:14 2025 +0100

    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
    
    Co-authored-by: Santtu Lakkala <inz_AT_inz.fi>

diff --git a/grep.c b/grep.c
index 1c97807..5520422 100644
--- a/grep.c
+++ b/grep.c
_AT_@ -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 *);
 
_AT_@ -37,37 +37,27 @@ 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;
         int bol, eol;
- size_t len;
+ size_t len, patlen;
 
- if (!patlen)
- return;
-
- /* a null BRE/ERE matches every line */
- if (!Fflag)
- if (pattern[0] == '\0')
- pattern = "^";
+ patlen = strlen(pattern);
+ bol = pattern[0] == '^';
+ eol = patlen > 0 && pattern[patlen - 1] == '$')
 
         if (!Fflag && xflag) {
                 tmp = enmalloc(Error, patlen + 3);
                 snprintf(tmp, patlen + 3, "%s%s%s",
- pattern[0] == '^' ? "" : "^",
+ bol ? "" : "^",
                          pattern,
- pattern[patlen - 1] == '$' ? "" : "$");
+ eol ? "" : "$");
         } else if (!Fflag && wflag) {
                 len = patlen + 5 + (Eflag ? 2 : 4);
                 tmp = enmalloc(Error, len);
 
- bol = eol = 0;
- if (pattern[0] == '^')
- bol = 1;
- if (pattern[patlen - 1] == '$')
- eol = 1;
-
                 snprintf(tmp, len, "%s\\<%s%.*s%s\\>%s",
                          bol ? "^" : "",
                          Eflag ? "(" : "\\(",
_AT_@ -93,7 +83,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:");
Received on Wed Nov 05 2025 - 14:07:23 CET

This archive was generated by hypermail 2.3.0 : Wed Nov 05 2025 - 14:12:37 CET