From f444dc586b16c104a82d201d3a7caca68affe51b Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 14 Nov 2023 11:15:02 +0000 Subject: win32: only search PATH for compressor mingw_fork_compressor() uses CreateProcess() to run the compressor program. This will often be an instance of BusyBox, but since the xv and lzma applets in BusyBox don't support compression it can be an external program. It was intended that the external program should be found using PATH. However, CreateProcess() looks in various other places before trying PATH. In particular, it first looks in the directory of the current executable, then in the current directory of the process. This can result in the wrong xz.exe or lzma.exe being found. Perform an explicit PATH search and force CreateProcess() to use the result. This change only affects the search for a compressor. The same problem also affects other uses of our popen(3) emulation. These may be addressed in future. Costs 64-80 bytes. (GitHub issue #376) --- include/mingw.h | 3 ++- networking/wget.c | 2 +- win32/popen.c | 30 ++++++++++++++++++------------ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/include/mingw.h b/include/mingw.h index f6f0bf262..eab756184 100644 --- a/include/mingw.h +++ b/include/mingw.h @@ -136,7 +136,8 @@ int mingw_rename(const char*, const char*); #define rename mingw_rename FILE *mingw_popen(const char *cmd, const char *mode); -int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid); +int mingw_popen_fd(const char *exe, const char *cmd, const char *mode, + int fd0, pid_t *pid); int mingw_pclose(FILE *fd); pid_t mingw_fork_compressor(int fd, const char *compressor, const char *mode); #undef popen diff --git a/networking/wget.c b/networking/wget.c index e0c66edba..f9e463f6c 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -844,7 +844,7 @@ static void spawn_ssl_client(const char *host, int network_fd, int flags) (void *)_get_osfhandle(network_fd), servername, flags & TLSLOOP_EXIT_ON_LOCAL_EOF ? " -e" : ""); - if ( (fd1=mingw_popen_fd(cmd, "b", -1, NULL)) == -1 ) { + if ( (fd1=mingw_popen_fd(NULL, cmd, "b", -1, NULL)) == -1 ) { bb_perror_msg_and_die("can't execute ssl_client"); } diff --git a/win32/popen.c b/win32/popen.c index 2208aa6bb..79433a27b 100644 --- a/win32/popen.c +++ b/win32/popen.c @@ -11,8 +11,8 @@ typedef struct { static pipe_data *pipes = NULL; static int num_pipes = 0; -static int mingw_popen_internal(pipe_data *p, const char *cmd, - const char *mode, int fd0, pid_t *pid); +static int mingw_popen_internal(pipe_data *p, const char *exe, + const char *cmd, const char *mode, int fd0, pid_t *pid); static int mingw_pipe(pipe_data *p, int bidi) { @@ -162,7 +162,7 @@ FILE *mingw_popen(const char *cmd, const char *mode) *t = '\0'; /* Create the pipe */ - if ((fd=mingw_popen_internal(p, cmd_buff, mode, -1, NULL)) != -1) { + if ((fd=mingw_popen_internal(p, NULL, cmd_buff, mode, -1, NULL)) != -1) { fptr = _fdopen(fd, *mode == 'r' ? "rb" : "wb"); } @@ -182,8 +182,8 @@ FILE *mingw_popen(const char *cmd, const char *mode) * - the pid of the command is returned in the variable pid, which * can be NULL if the pid is not required. */ -static int mingw_popen_internal(pipe_data *p, const char *cmd, - const char *mode, int fd0, pid_t *pid) +static int mingw_popen_internal(pipe_data *p, const char *exe, + const char *cmd, const char *mode, int fd0, pid_t *pid) { pipe_data pd; STARTUPINFO siStartInfo; @@ -245,8 +245,8 @@ static int mingw_popen_internal(pipe_data *p, const char *cmd, siStartInfo.wShowWindow = SW_HIDE; siStartInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; - success = CreateProcess(NULL, - (LPTSTR)cmd, /* command line */ + success = CreateProcess((LPCSTR)exe, + (LPSTR)cmd, /* command line */ NULL, /* process security attributes */ NULL, /* primary thread security attributes */ TRUE, /* handles are inherited */ @@ -280,9 +280,10 @@ finito: return fd; } -int mingw_popen_fd(const char *cmd, const char *mode, int fd0, pid_t *pid) +int mingw_popen_fd(const char *exe, const char *cmd, const char *mode, + int fd0, pid_t *pid) { - return mingw_popen_internal(NULL, cmd, mode, fd0, pid); + return mingw_popen_internal(NULL, exe, cmd, mode, fd0, pid); } int mingw_pclose(FILE *fp) @@ -310,7 +311,7 @@ int mingw_pclose(FILE *fp) * file; with mode "r" and a decompressor in open_transformer. */ pid_t mingw_fork_compressor(int fd, const char *compressor, const char *mode) { - char *cmd; + char *cmd, *exe = NULL; int fd1; pid_t pid; @@ -322,20 +323,25 @@ pid_t mingw_fork_compressor(int fd, const char *compressor, const char *mode) && !(mode[0] == 'w' && index_in_strings("lzma\0xz\0", compressor) >= 0) # endif ) { + // shared format string cmd = xasprintf("%s --busybox %s -cf -", bb_busybox_exec_path, compressor); } else { - // share format string + // Look up compressor on PATH + exe = find_first_executable(compressor); + if (exe == NULL) + bb_perror_msg_and_die("can't execute '%s'", compressor); cmd = xasprintf("%s --busybox %s -cf -" + 13, compressor); } #else cmd = xasprintf("%s -cf -", compressor); #endif - if ((fd1 = mingw_popen_fd(cmd, mode, fd, &pid)) == -1) + if ((fd1 = mingw_popen_fd(exe, cmd, mode, fd, &pid)) == -1) bb_perror_msg_and_die("can't execute '%s'", compressor); free(cmd); + free(exe); xmove_fd(fd1, fd); return pid; } -- cgit v1.2.3-55-g6feb