diff --git a/src/exec.cpp b/src/exec.cpp index ff84cb698..6268ad199 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -92,6 +92,12 @@ static bool is_thompson_shell_payload(const char *p, size_t n) { /// such as Actually Portable Executable. /// N.B.: this is called after fork, it must not allocate heap memory. bool is_thompson_shell_script(const char *path) { + // Paths ending in ".fish" are never considered Thompson shell scripts. + if (const char *lastdot = strrchr(path, '.')) { + if (0 == strcmp(lastdot, ".fish")) { + return false; + } + } int e = errno; bool res = false; int fd = open_cloexec(path, O_RDONLY | O_NOCTTY); diff --git a/tests/checks/noshebang.fish b/tests/checks/noshebang.fish index c58111144..c5353fed1 100644 --- a/tests/checks/noshebang.fish +++ b/tests/checks/noshebang.fish @@ -32,6 +32,27 @@ runfile #CHECK: 0 #CHECK: 0 +# Never implicitly pass files ending with .fish to /bin/sh. +true >file.fish +chmod a+x file.fish +set -g fish_use_posix_spawn 0 +./file.fish +echo $status +set -g fish_use_posix_spawn 1 +./file.fish +echo $status +rm file.fish +#CHECK: 125 +#CHECKERR: Failed {{.*}} +#CHECKERR: exec: {{.*}} +#CHECKERR: {{.*}} + +#CHECK: 125 +#CHECKERR: Failed {{.*}} +#CHECKERR: exec: {{.*}} +#CHECKERR: {{.*}} + + # On to NUL bytes. # The heuristic is that there must be a line containing a lowercase letter before the first NUL byte. echo -n -e 'true\n\x00' >file