From ecd1b0d916bbbe002af9624f152c062a891e4633 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Sat, 4 Jul 2026 00:59:05 +0200 Subject: FreeBSD: fixed crashes with `EC` or `EQq` * GSpawn ends up calling posix_spawnp() which passes down a small 4kb stack to the child process until it exec()s. This stack could be overflowed easily on code paths where the path is not already absolute and when many shared libraries are involved. * The crashes could therefore only be observed on Gtk builds and in UNIX shell emulation mode (0,128ED). Sample test case: gsciteco -e '0,128ED @EC"ls"' Theoretically a relative $SHELL variable could have also triggered it. * I assume that the bug will be fixed in libc at least by the time of FreeBSD 16. * As a workaround we resolve relative program paths before passing them to g_spawn_async_with_pipes(). --- src/spawn.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'src') diff --git a/src/spawn.c b/src/spawn.c index 716bafa..b17ee58 100644 --- a/src/spawn.c +++ b/src/spawn.c @@ -22,6 +22,7 @@ #include #include +#include #include @@ -295,6 +296,25 @@ teco_state_execute_done(teco_machine_main_t *ctx, teco_string_t str, GError **er if (!argv) goto gerror; +#if defined(__FreeBSD__) && __FreeBSD__ < 16 + /* + * FIXME: g_spawn_async_with_pipes() will internally call + * posix_spawnp() which uses a tiny 4kb stack which can + * easily result in memory corruption if the path does not + * contain '/', ie. must be resolved against $PATH. + * See also https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=295991 + * As a workaround, only pass down absolute paths. + */ + gchar *program = g_find_program_in_path(argv[0]); + if (!program) { + g_set_error(error, TECO_ERROR, TECO_ERROR_FAILED, + "Program \"%s\" not found", argv[0]); + goto gerror; + } + g_free(argv[0]); + argv[0] = program; +#endif /* __FreeBSD__ < 16 */ + envp = teco_qreg_table_get_environ(&teco_qreg_table_globals, error); if (!envp) goto gerror; -- cgit v1.2.3