From 2df2e72e0a3c5e44587a52698772d607101085c5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 7 Apr 2026 14:49:05 +0800 Subject: [PATCH] fix(undo): undefined behavior with empty entry in 'undodir' (#38849) Problem: Undefined behavior when 'undodir' contains empty entry. Solution: Don't try to remove trailing slashes from empty path. Also don't remove a colon on Windows while at it. --- src/nvim/undo.c | 12 +++++------- test/functional/editor/undo_spec.lua | 12 ++++++++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/nvim/undo.c b/src/nvim/undo.c index d6d443b0d8..766346ba1c 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -711,10 +711,8 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) dir_name[dir_len] = NUL; // Remove trailing pathseps from directory name - char *p = &dir_name[dir_len - 1]; - while (dir_len > 1 && vim_ispathsep(*p)) { - *p-- = NUL; - dir_len--; + while (dir_len > 1 && vim_ispathsep_nocolon(dir_name[dir_len - 1])) { + dir_name[--dir_len] = NUL; } bool has_directory = os_isdir(dir_name); @@ -733,9 +731,9 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading) if (has_directory) { if (munged_name.data == NULL) { munged_name = cbuf_to_string(ffname, ffname_len); - for (char *c = munged_name.data; *c != NUL; MB_PTR_ADV(c)) { - if (vim_ispathsep(*c)) { - *c = '%'; + for (char *p = munged_name.data; *p != NUL; MB_PTR_ADV(p)) { + if (vim_ispathsep(*p)) { + *p = '%'; } } } diff --git a/test/functional/editor/undo_spec.lua b/test/functional/editor/undo_spec.lua index 2d4b79cc8c..f079f92146 100644 --- a/test/functional/editor/undo_spec.lua +++ b/test/functional/editor/undo_spec.lua @@ -225,3 +225,15 @@ describe(':undo! command', function() ) end) end) + +describe("opening file when 'undofile' is on", function() + before_each(function() + clear({ args = { '--cmd', 'set undofile' } }) + end) + + it("does not crash when 'undodir' contains empty entry", function() + command('set undodir=,.') + command('edit test/functional/fixtures/bigfile.txt') + n.assert_alive() + end) +end)