From 3cae4cee81d55bc2bdba77fbf098f93aeb379dc0 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Sat, 2 May 2020 11:02:32 -0600 Subject: [PATCH] Shell: Check for invalid #! in commands --- Shell/main.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/Shell/main.cpp b/Shell/main.cpp index f59dcf18504..5a1cbdf5789 100644 --- a/Shell/main.cpp +++ b/Shell/main.cpp @@ -28,6 +28,7 @@ #include "Parser.h" #include #include +#include #include #include #include @@ -580,7 +581,7 @@ static bool handle_builtin(int argc, const char** argv, int& retval) class FileDescriptionCollector { public: - FileDescriptionCollector() { } + FileDescriptionCollector() {} ~FileDescriptionCollector() { collect(); } void collect() @@ -906,7 +907,17 @@ static int run_command(const String& cmd) int rc = execvp(argv[0], const_cast(argv.data())); if (rc < 0) { if (errno == ENOENT) { - fprintf(stderr, "%s: Command not found.\n", argv[0]); + int shebang_fd = open(argv[0], O_RDONLY); + auto close_argv = ScopeGuard([shebang_fd]() { if (shebang_fd >= 0) close(shebang_fd); }); + char shebang[256] {}; + ssize_t num_read = -1; + if ((shebang_fd >= 0) && ((num_read = read(shebang_fd, shebang, sizeof(shebang))) >= 2) && (StringView(shebang).starts_with("#!"))) { + StringView shebang_path_view(&shebang[2], num_read - 2); + Optional newline_pos = shebang_path_view.find_first_of("\n\r"); + shebang[newline_pos.has_value() ? newline_pos.value() : num_read] = '\0'; + fprintf(stderr, "%s: Invalid interpreter \"%s\": %s\n", argv[0], &shebang[2], strerror(ENOENT)); + } else + fprintf(stderr, "%s: Command not found.\n", argv[0]); } else { struct stat st; if (stat(argv[0], &st) == 0 && S_ISDIR(st.st_mode)) { @@ -915,7 +926,7 @@ static int run_command(const String& cmd) } fprintf(stderr, "execvp(%s): %s\n", argv[0], strerror(errno)); } - _exit(1); + _exit(126); } ASSERT_NOT_REACHED(); }