fix various bugs in path and error handling in execvp/fexecve
authorRich Felker <dalias@aerifal.cx>
Thu, 29 Sep 2011 04:48:04 +0000 (00:48 -0400)
committerRich Felker <dalias@aerifal.cx>
Thu, 29 Sep 2011 04:48:04 +0000 (00:48 -0400)
src/process/execvp.c
src/process/fexecve.c

index d799ddae248403fd6a41df818e7b6d957abfc60d..b2da44b92cc134918d510e7d7b06504014c1c902 100644 (file)
@@ -2,33 +2,41 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
-
-extern char **__environ;
+#include <limits.h>
 
 int execvp(const char *file, char *const argv[])
 {
        const char *p, *z, *path = getenv("PATH");
-       int l;
+       size_t l, k;
+
+       errno = ENOENT;
+       if (!*file) return -1;
 
        if (strchr(file, '/'))
-               return execve(file, argv, __environ);
+               return execv(file, argv);
 
-       /* FIXME: integer overflows */
        if (!path) path = "/usr/local/bin:/bin:/usr/bin";
-       l = strlen(file) + strlen(path) + 2;
+       k = strnlen(file, NAME_MAX+1);
+       if (k > NAME_MAX) {
+               errno = ENAMETOOLONG;
+               return -1;
+       }
+       l = strnlen(path, PATH_MAX-1)+1;
 
-       for(p=path; p && *p; p=z) {
-               char b[l];
+       for(p=path; ; p=z) {
+               char b[l+k+1];
                z = strchr(p, ':');
-               if (z) {
-                       memcpy(b, p, z-p);
-                       b[z++-p] = 0;
-               } else strcpy(b, p);
-               strcat(b, "/");
-               strcat(b, file);
-               if (!access(b, X_OK))
-                       return execve(b, argv, __environ);
+               if (!z) z = p+strlen(p);
+               if (z-p >= l) {
+                       if (!*z++) break;
+                       continue;
+               }
+               memcpy(b, p, z-p);
+               b[z-p] = '/';
+               memcpy(b+(z-p)+(z>p), file, k+1);
+               execv(b, argv);
+               if (errno != ENOENT) return -1;
+               if (!*z++) break;
        }
-       errno = ENOENT;
        return -1;
 }
index 3098645da5a7c8762d492d59cebc68afd17cc2ad..5939181a7e1adcfba2fb8e9681eb3e7823f3267c 100644 (file)
@@ -1,10 +1,13 @@
 #include <unistd.h>
 #include <stdio.h>
+#include <errno.h>
 
 int fexecve(int fd, char *const argv[], char *const envp[])
 {
        static const char proc[] = "/proc/self/fd/%d";
        char buf[sizeof proc + 3*sizeof(int)];
        snprintf(buf, sizeof buf, proc, fd);
-       return execve(buf, argv, envp);
+       execve(buf, argv, envp);
+       if (errno == ENOENT) errno = EBADF;
+       return -1;
 }