grep: Don't modify constant strings - sbase - suckless unix tools
 (HTM) git clone git://git.suckless.org/sbase
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit ae7bfda8f6f1b3f1951e8e69b8910d5171bf6236
 (DIR) parent 87f4755cd09eecdab7c750a347143cc6fb3b262d
 (HTM) Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
       Date:   Wed,  5 Nov 2025 09:59:44 +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@inz.fi>
       
       Diffstat:
         M grep.c                              |      28 +++++++++-------------------
       
       1 file changed, 9 insertions(+), 19 deletions(-)
       ---
 (DIR) diff --git 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,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 ? "(" : "\\(",
       @@ -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:");