]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
script: Fix buffer over and under flows in script_buftoenv master
authorRoy Marples <roy@marples.name>
Mon, 22 Jun 2026 20:14:11 +0000 (21:14 +0100)
committerGitHub <noreply@github.com>
Mon, 22 Jun 2026 20:14:11 +0000 (21:14 +0100)
Enforce we have a buffer and it is terminated.
Rework code so that we no longer assert.

Reported by NVIDIA Project Vanessa

src/script.c

index 1edf0c22765e9e0042ec35c3230609d0f394a7e7..ca273e2be71d83c33b75b20baace5fcaa72269a5 100644 (file)
@@ -33,7 +33,6 @@
 #include <netinet/in.h>
 
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
 #include <arpa/inet.h>
-#include <assert.h>
 #include <ctype.h>
 #include <errno.h>
 #include <pwd.h>
 #include <ctype.h>
 #include <errno.h>
 #include <pwd.h>
@@ -165,20 +164,30 @@ script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len)
        char **env, **envp, *bufp, *endp;
        size_t nenv;
 
        char **env, **envp, *bufp, *endp;
        size_t nenv;
 
-       /* Count the terminated env strings.
-        * Assert that the terminations are correct. */
+       /* We should have something to process */
+       if (buf == NULL || len == 0) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       /* Ensure the buffer ends with NUL */
+       if (buf[len - 1] != '\0') {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       /* Count the NUL-terminated env strings */
        nenv = 0;
        endp = buf + len;
        for (bufp = buf; bufp < endp; bufp++) {
                if (*bufp == '\0') {
        nenv = 0;
        endp = buf + len;
        for (bufp = buf; bufp < endp; bufp++) {
                if (*bufp == '\0') {
-#ifndef NDEBUG
-                       if (bufp + 1 < endp)
-                               assert(*(bufp + 1) != '\0');
-#endif
+                       /* Skip consecutive NULs safely without crashing */
+                       while (bufp + 1 < endp && *(bufp + 1) == '\0') {
+                               bufp++;
+                       }
                        nenv++;
                }
        }
                        nenv++;
                }
        }
-       assert(*(bufp - 1) == '\0');
        if (nenv == 0)
                return NULL;
 
        if (nenv == 0)
                return NULL;
 
@@ -192,11 +201,23 @@ script_buftoenv(struct dhcpcd_ctx *ctx, char *buf, size_t len)
 
        bufp = buf;
        envp = ctx->script_env;
 
        bufp = buf;
        envp = ctx->script_env;
-       *envp++ = bufp++;
-       endp--; /* Avoid setting the last \0 to an invalid pointer */
-       for (; bufp < endp; bufp++) {
-               if (*bufp == '\0')
-                       *envp++ = bufp + 1;
+
+       /* If first char is NUL, skip leading empty strings if any,
+        * or handle them gracefully */
+       while (bufp < endp && *bufp == '\0')
+               bufp++;
+       if (bufp < endp)
+               *envp++ = bufp;
+
+       /* Walk and capture pointers to each environment variable */
+       for (; bufp < endp - 1; bufp++) {
+               if (*bufp == '\0') {
+                       /* Skip consecutive NULs */
+                       while (bufp < endp - 1 && *(bufp + 1) == '\0')
+                               bufp++;
+                       if (bufp + 1 < endp)
+                               *envp++ = bufp + 1;
+               }
        }
        *envp = NULL;
 
        }
        *envp = NULL;