From b062cf19f4a185afd2d86ccf8a85d77bba6f93e6 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Thu, 20 Mar 2025 17:27:39 +0100 Subject: [PATCH 1/2] memory-util: make mempcpy_typesafe nestable --- src/basic/memory-util.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/basic/memory-util.h b/src/basic/memory-util.h index 04de0ab1c1..0a035ef087 100644 --- a/src/basic/memory-util.h +++ b/src/basic/memory-util.h @@ -35,13 +35,16 @@ static inline void* mempcpy_safe(void *dst, const void *src, size_t n) { return mempcpy(dst, src, n); } -#define mempcpy_typesafe(dst, src, n) \ +#define _mempcpy_typesafe(dst, src, n, sz) \ ({ \ - size_t _sz_; \ - assert_se(MUL_SAFE(&_sz_, sizeof((dst)[0]), n)); \ - (typeof((dst)[0])*) mempcpy_safe(dst, src, _sz_); \ + size_t sz; \ + assert_se(MUL_SAFE(&sz, sizeof((dst)[0]), n)); \ + (typeof((dst)[0])*) mempcpy_safe(dst, src, sz); \ }) +#define mempcpy_typesafe(dst, src, n) \ + _mempcpy_typesafe(dst, src, n, UNIQ_T(sz, UNIQ)) + /* Normal memcmp() requires s1 and s2 to be nonnull. We do nothing if n is 0. */ static inline int memcmp_safe(const void *s1, const void *s2, size_t n) { if (n == 0) From d2e49d9389f390740ce5a1f48e944bb55036bbfe Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Thu, 20 Mar 2025 17:01:19 +0100 Subject: [PATCH 2/2] edit-util: don't leave custom editor args around if we shall fall back Also, let's complain loudly if the editor acquired from envvar is not present. Fixes #36796 --- src/shared/edit-util.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/shared/edit-util.c b/src/shared/edit-util.c index e37609c2e1..d08faed661 100644 --- a/src/shared/edit-util.c +++ b/src/shared/edit-util.c @@ -236,8 +236,7 @@ static int create_edit_temp_file(EditFile *e, const char *contents, size_t conte } static int run_editor_child(const EditFileContext *context) { - _cleanup_strv_free_ char **args = NULL; - const char *editor; + _cleanup_strv_free_ char **args = NULL, **editor = NULL; int r; assert(context); @@ -247,15 +246,14 @@ static int run_editor_child(const EditFileContext *context) { * If neither SYSTEMD_EDITOR nor EDITOR nor VISUAL are present, we try to execute * well known editors. */ FOREACH_STRING(e, "SYSTEMD_EDITOR", "EDITOR", "VISUAL") { - editor = empty_to_null(getenv(e)); - if (editor) - break; - } + const char *m = empty_to_null(getenv(e)); + if (m) { + editor = strv_split(m, WHITESPACE); + if (!editor) + return log_oom(); - if (editor) { - args = strv_split(editor, WHITESPACE); - if (!args) - return log_oom(); + break; + } } if (context->n_files == 1 && context->files[0].line > 1) { @@ -271,8 +269,18 @@ static int run_editor_child(const EditFileContext *context) { return log_oom(); } - if (editor) - execvp(args[0], (char* const*) args); + size_t editor_n = strv_length(editor); + if (editor_n > 0) { + /* Strings are owned by 'editor' and 'args' */ + _cleanup_free_ char **cmdline = new(char*, editor_n + strv_length(args) + 1); + if (!cmdline) + return log_oom(); + + *mempcpy_typesafe(mempcpy_typesafe(cmdline, editor, editor_n), args, strv_length(args)) = NULL; + + execvp(cmdline[0], cmdline); + log_warning_errno(errno, "Specified editor '%s' not available, trying fallbacks: %m", editor[0]); + } bool prepended = false; FOREACH_STRING(name, "editor", "nano", "vim", "vi") {