Fix execvpe ENOEXEC behavior.
The special case for absolute paths wasn't handling ENOEXEC.
Also add more extensive tests for execvpe.
Also switch to manually doing the fork in ExecTestHelper::Run because
ASSERT_EXIT doesn't actually return, meaning we were only running the
first part of each test.
Bug: http://b/31073104
Change-Id: I7a4640afc6d290c51ba2e66fc1b9bb6b0fc174f7
diff --git a/libc/bionic/exec.cpp b/libc/bionic/exec.cpp
index c1e73a5..354f931 100644
--- a/libc/bionic/exec.cpp
+++ b/libc/bionic/exec.cpp
@@ -95,15 +95,15 @@
return execvpe(name, argv, environ);
}
-static int __exec_as_script(char* buf, char* const* argv, char* const* envp) {
- size_t arg_count = 0;
+static int __exec_as_script(const char* buf, char* const* argv, char* const* envp) {
+ size_t arg_count = 1;
while (argv[arg_count] != nullptr) ++arg_count;
- char* script_argv[arg_count + 2];
- script_argv[0] = const_cast<char*>("sh");
+ const char* script_argv[arg_count + 2];
+ script_argv[0] = "sh";
script_argv[1] = buf;
- bcopy(argv + 1, script_argv + 2, arg_count * sizeof(char*));
- return execve(_PATH_BSHELL, script_argv, envp);
+ memcpy(script_argv + 2, argv + 1, arg_count * sizeof(char*));
+ return execve(_PATH_BSHELL, const_cast<char**>(script_argv), envp);
}
int execvpe(const char* name, char* const* argv, char* const* envp) {
@@ -114,7 +114,9 @@
}
// If it's an absolute or relative path name, it's easy.
- if (strchr(name, '/')) return execve(name, argv, envp);
+ if (strchr(name, '/') && execve(name, argv, envp) == -1) {
+ return __exec_as_script(name, argv, envp);
+ }
// Get the path we're searching.
const char* path = getenv("PATH");