about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/process/execvp.c42
-rw-r--r--src/process/fexecve.c5
2 files changed, 29 insertions, 18 deletions
diff --git a/src/process/execvp.c b/src/process/execvp.c
index d799ddae..b2da44b9 100644
--- a/src/process/execvp.c
+++ b/src/process/execvp.c
@@ -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;
 }
diff --git a/src/process/fexecve.c b/src/process/fexecve.c
index 3098645d..5939181a 100644
--- a/src/process/fexecve.c
+++ b/src/process/fexecve.c
@@ -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;
 }