From 7ff0fb3af53a32d0094cf4767bbd019b1cfe550e Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 27 Jan 2021 10:53:22 +0000 Subject: [PATCH] spawn: Don't set a search path if we don't want to search PATH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit do_exec() and g_execute() rely on being passed a NULL search path if we intend to avoid searching the PATH, but since the refactoring in commit 62ce66d4, this was never done. This resulted in some spawn calls searching the PATH when it was not intended. Spawn calls that go through the posix_spawn fast-path were unaffected. The deprecated gtester utility, as used in GTK 3, relies on the ability to run an executable from the current working directory by omitting the G_SPAWN_SEARCH_PATH flag. This *mostly* worked, because our fallback PATH ends with ".". However, if an executable of the same name existed in /usr/bin or /bin, it would run that instead of the intended test: in particular, GTK 3's build-time tests failed if ImageMagick happens to be installed, because gtester would accidentally run display(1) instead of testsuite/gdk/display. Fixes: 62ce66d4 "gspawn: Don’t use getenv() in async-signal-safe context" Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=977961 --- glib/gspawn.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/glib/gspawn.c b/glib/gspawn.c index 9b503cf7b..032835b93 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -1835,7 +1835,7 @@ fork_exec_with_fds (gboolean intermediate_child, if (search_path && chosen_search_path == NULL) chosen_search_path = g_getenv ("PATH"); - if (chosen_search_path == NULL) + if ((search_path || search_path_from_envp) && chosen_search_path == NULL) { /* There is no 'PATH' in the environment. The default * * search path in libc is the current directory followed by @@ -1850,14 +1850,27 @@ fork_exec_with_fds (gboolean intermediate_child, chosen_search_path = "/bin:/usr/bin:."; } + if (search_path || search_path_from_envp) + g_assert (chosen_search_path != NULL); + else + g_assert (chosen_search_path == NULL); + /* Allocate a buffer which the fork()ed child can use to assemble potential * paths for the binary to exec(), combining the argv[0] and elements from * the chosen_search_path. This can’t be done in the child because malloc() * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`). * * Add 2 for the nul terminator and a leading `/`. */ - search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2; - search_path_buffer = g_malloc (search_path_buffer_len); + if (chosen_search_path != NULL) + { + search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2; + search_path_buffer = g_malloc (search_path_buffer_len); + } + + if (search_path || search_path_from_envp) + g_assert (search_path_buffer != NULL); + else + g_assert (search_path_buffer == NULL); /* And allocate a buffer which is 2 elements longer than @argv, so that if * script_execute() has to be called later on, it can build a wrapper argv