Use the full path for noshebang'd scripts

If you make a script called `foo` somewhere in $PATH, and did not give
it a shebang, this would end up calling

    sh foo

instead of

    sh /usr/bin/foo

which might not match up.

Especially if the path is e.g. `--version` or `-` that would end up
being misinterpreted *by sh*.

So instead we simply pass the actual_cmd to sh, because we need it
anyway to get it to fail to execute before.
This commit is contained in:
Fabian Homborg 2021-12-02 21:10:57 +01:00
parent 0c76b571c7
commit 3700247b55
3 changed files with 19 additions and 1 deletions

View file

@ -150,6 +150,7 @@ bool is_thompson_shell_script(const char *path) {
// This function never returns, so we take certain liberties with constness.
auto envv = const_cast<char **>(cenvv);
auto argv = const_cast<char **>(cargv);
auto cmd2 = const_cast<char *>(actual_cmd);
execve(actual_cmd, argv, envv);
err = errno;
@ -169,6 +170,9 @@ bool is_thompson_shell_script(const char *path) {
char interp[] = _PATH_BSHELL;
argv2[0] = interp;
std::copy_n(argv, 1 + nargs, &argv2[1]); // +1 to copy terminating nullptr
// The command to call should use the full path,
// not what we would pass as argv0.
argv2[1] = cmd2;
execve(_PATH_BSHELL, argv2, envv);
}
}

View file

@ -350,7 +350,11 @@ maybe_t<pid_t> posix_spawner_t::spawn(const char *cmd, char *const argv[], char
std::vector<char *> argv2;
char interp[] = _PATH_BSHELL;
argv2.push_back(interp);
for (size_t i = 0; argv[i] != nullptr; i++) {
// The command to call should use the full path,
// not what we would pass as argv0.
std::string cmd2 = cmd;
argv2.push_back(&cmd2[0]);
for (size_t i = 1; argv[i] != nullptr; i++) {
argv2.push_back(argv[i]);
}
argv2.push_back(nullptr);

View file

@ -80,3 +80,13 @@ runfile
#CHECK: 126
#CHECKERR: exec: {{.*}}
echo 'echo foo' >./-
sleep 0.1
chmod +x ./-
set PATH ./ $PATH
sleep 0.1
-
#CHECK: foo
echo $status
#CHECK: 0