diff --git a/glib/gspawn.c b/glib/gspawn.c index 0b9473022..c8e0ca806 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -1753,8 +1753,10 @@ fork_exec_with_fds (gboolean intermediate_child, gint status; const gchar *chosen_search_path; gchar *search_path_buffer = NULL; + gchar *search_path_buffer_heap = NULL; gsize search_path_buffer_len = 0; gchar **argv_buffer = NULL; + gchar **argv_buffer_heap = NULL; gsize argv_buffer_len = 0; #ifdef POSIX_SPAWN_AVAILABLE @@ -1848,7 +1850,17 @@ fork_exec_with_fds (gboolean intermediate_child, 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_buffer_len < 4000) + { + /* Prefer small stack allocations to avoid valgrind leak warnings + * in forked child. The 4000B cutoff is arbitrary. */ + search_path_buffer = g_alloca (search_path_buffer_len); + } + else + { + search_path_buffer_heap = g_malloc (search_path_buffer_len); + search_path_buffer = search_path_buffer_heap; + } } if (search_path || search_path_from_envp) @@ -1860,12 +1872,22 @@ fork_exec_with_fds (gboolean intermediate_child, * script_execute() has to be called later on, it can build a wrapper argv * array in this buffer. */ argv_buffer_len = g_strv_length (argv) + 2; - argv_buffer = g_new (gchar *, argv_buffer_len); + if (argv_buffer_len < 4000 / sizeof (gchar *)) + { + /* Prefer small stack allocations to avoid valgrind leak warnings + * in forked child. The 4000B cutoff is arbitrary. */ + argv_buffer = g_newa (gchar *, argv_buffer_len); + } + else + { + argv_buffer_heap = g_new (gchar *, argv_buffer_len); + argv_buffer = argv_buffer_heap; + } if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error)) { - g_free (search_path_buffer); - g_free (argv_buffer); + g_free (search_path_buffer_heap); + g_free (argv_buffer_heap); return FALSE; } @@ -2112,8 +2134,8 @@ fork_exec_with_fds (gboolean intermediate_child, close_and_invalidate (&child_err_report_pipe[0]); close_and_invalidate (&child_pid_report_pipe[0]); - g_free (search_path_buffer); - g_free (argv_buffer); + g_free (search_path_buffer_heap); + g_free (argv_buffer_heap); if (child_pid) *child_pid = pid; @@ -2147,8 +2169,8 @@ fork_exec_with_fds (gboolean intermediate_child, close_and_invalidate (&child_pid_report_pipe[0]); close_and_invalidate (&child_pid_report_pipe[1]); - g_free (search_path_buffer); - g_free (argv_buffer); + g_free (search_path_buffer_heap); + g_free (argv_buffer_heap); return FALSE; }