summaryrefslogtreecommitdiffstatshomepage
AgeCommit message (Collapse)AuthorFiles
2026-04-25ci: ensure full sanitizer logs are shown in CI #39361HEADmasterJustin M. Keyes1
Problem: When ASAN detects an error in a child process, the process may be killed by test teardown before ASAN finishes writing its log file. This results in truncated logs with no stack trace. Also, the sanitizer log content was only written to stdout (which the test runner may not display) and not included in the test_assert error message. Solution: - Poll (up to 2s) for the ASAN "SUMMARY" line before reading, so the crashing process has time to finish writing. - Include full log content in the test_assert error message, so it appears in CI output regardless of stdout handling. - Warn when the log appears truncated (no SUMMARY line found).
2026-04-25fix(channel): stack-buffer-overflow with exit during connection (#39387)zeertzjq3
Problem: When Nvim exits while connecting to a socket it leads to stack-buffer-overflow. Solution: Associate the handle with the Stream and use the Stream's internal_close_cb to update the "closed" status.
2026-04-25fix(build): add `_core/time.lua` to gettext #39384Olivia Kinnear1
2026-04-25test: add finally() to meta file (#39388)zeertzjq1
2026-04-24fix(lsp): handle self-mapped methods in supports_method #39383nightlyTristan Knight2
Problem: The LSP client incorrectly checks for server capabilities when determining support for self-mapped methods (e.g., 'shutdown'), which do not have corresponding capabilities in the server's response. This leads to false negatives when checking if such methods are supported. This was handled correctly for dynamic registrations, but not for static. Methods such as 'shutdown', do not have a related server capability and should be assumed to be supported. Solution: Update the `supports_method` logic to always return true for self-mapped methods.
2026-04-24feat(tui): restore 'ttyfast' to control tty requests #38699Kyle11
Problem: When running nvim on a remote machine over SSH, if there is high ping, then bg detection may not complete in time. This results in a warning every time nvim is started. #38648 Solution: Restore 'ttyfast' option and allow it to control whether or not bg detection is performed. Because this is during startup and before any user config or commands, we use the environment variable `NVIM_NOTTYFAST` to allow disabling `ttyfast` during initialization.
2026-04-24fix(api): leak preview callback LuaRef in nvim_create_user_command #39357Barrett Ruth2
Problem: Invalid `nvim_create_user_command` calls can leak the `preview` callback reference after Neovim has taken ownership of it. 1. build with {a,l}san 2. run: ```sh <path/to/nvim> --headless -u NONE --clean +'lua for i = 1, 100 do pcall(vim.api.nvim_create_user_command, "some very epic stuff" .. i, {}, -- NOTE: this is INVALID (not a function or string) { preview = function() end }) end vim.cmd("qa!") ' +qa ``` 3. see: ``` 100 lua references were leaked! ``` Solution: Clear `preview_luaref` in `err:`.
2026-04-24fix(api): LuaRef leak in nvim_set_keymap on LHS too long (>=66 bytes) #39351Barrett Ruth2
Problem: `nvim_set_keymap` leaks the `callback` `LuaRef` when the LHS is too long. Solution: Make `set_maparg_lhs_rhs` transfer `rhs_lua` to `MapArguments` up front so the caller always owns the ref.
2026-04-24fix(path): normalize path slashes on Windows #37729tao41
Problem: On Windows, path separators may become inconsistent for various reasons, which makes normalization quite painful. Solution: Normalize paths to `/` at the entry boundaries and always use it internally, converting back only in rare cases where `\` is really needed (e.g. cmd.exe/bat scripts?). This is the first commit in a series of incremental steps. Note: * some funcs won't respect shellslash. e.g. `expand/fnamemodify` * some funcs still respect shellslash, but will be updated in a follow PR. e.g. `ex_pwd/f_chdir/f_getcwd` * uv's built-in funcs always return `\`. e.g. `uv.cwd/uv.exepath` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-04-24feat(api): nvim_echo(percent=nil) means "unknown" progress #39029Peter Cardenas8
Problem: No way to signal "unknown" or "indeterminate" progress percentage. Solution: Treat percent=nil as "indeterminate" percent.
2026-04-24test: curbuf initialized in describe-block #39365glepnir1
Problem: curbuf was initialized at describe-block load time before any Nvim session existed. Solution: Replace with 0 directly at call sites.
2026-04-24fix(lsp): more info in error msg, deduplicate test #39359Justin M. Keyes2
2026-04-24fix(trust): always use "/" slashes in filepaths #39355Justin M. Keyes5
Problem: We should not use "\" (backslashes) except where absolutely required. See references in https://github.com/neovim/neovim/pull/37729 Solution: There is no reason to use "\" slashes in the trust db, so don't.
2026-04-24vim-patch:9.2.0390: filetype: some Beancount files are not recognized (#39360)zeertzjq2
Problem: filetype: some Beancount files are not recognized Solution: Detect *.bean files as beancount filetype (Bruno Belanyi) closes: vim/vim#20037 https://github.com/vim/vim/commit/521eac1877355d408c8c57bc31947cc86f31f41d Co-authored-by: Bruno Belanyi <bruno@belanyi.fr>
2026-04-23fix(options): repair stale UI state after `:set all&` #39026Barrett Ruth3
Problem: `set all&` resets option values directly and leaves UI-derived state stale for `guicursor`, `laststatus`, and `showtabline`. Solution: Repair some of the stale UI state in the bulk reset path by reparsing `guicursor`, refreshing statusline state, and recomputing tabline/window rows.
2026-04-23feat(excmd): add :uptime command #39331Olivia Kinnear11
Problem Nvim marks its v:starttime, but there is no user-friendly way to get Nvim's uptime. Solution Add :uptime (based loosely on uptime(1)).
2026-04-23refactor(test): deduplicate trust tests #39354Justin M. Keyes2
2026-04-23fix(lsp): handle null id in JSON-RPC responses #38340atusy2
Problem: LSP spec allows response message to have a null request-id. This may happen when for example client sends unparseable request. https://github.com/microsoft/language-server-protocol/issues/196 Solution: Guard the server response branches against id=vim.NIL (json null), and handle error responses with null id by logging a warning and dispatching on error. Problem: CI (ubuntu asan, ubuntu tsan, windows) reports `uv_loop_close() hang?` from the two new null-id response tests. The leaked handle is the server-side accepted TCP socket created inside `server:listen` callback. The tests closed only the listener but not the accepted socket, so libuv could not finish shutting down the loop and each test session took ~2s extra to exit. Solution: Hoist the accepted socket to the outer `exec_lua` scope and close it at teardown before closing the listener. The close runs synchronously inside `exec_lua`, so the loop has time to dispose the handle before the session exits. * test(lsp): close accepted socket on read-loop exit/error Match the precedent in the handler test ("handler can return false as response") and the shared `_create_tcp_server` helper in `test/functional/plugin/lsp/testutil.lua`: close the accepted socket from inside the `create_read_loop` exit/error callbacks. The teardown close added in the previous commit remains as belt-and-suspenders, so the socket is disposed whether the server goes away first or the client does.
2026-04-23fix(trust): hash unchanged empty buffers as empty files #39027Barrett Ruth3
Problem: `vim.secure.trust()` hashes an unchanged empty buffer as a newline, so trusting an empty file by buffer never works. Solution: Hash unchanged empty-buffers `''` so buffer-based trust matches the on-disk empty file.
2026-04-23fix(lua): don't strip debuginfo in precompile module #39191phanium5
Problem: debug.getinfo on bytecode module/func don't give you detail source info. Solution: - Use `loadstring`+`string.dump` to replace LUAC_PRG(`luac`/`luajit -b`) - `string.dump(…,false)` to generate non-strip version bytecode - `loadstring(…,fname)` to specify the full source name BEFORE: $ nvim --clean +'=debug.getinfo(vim.fn.maparg("]<Space>", "n", 0, 1).callback, "Sl")' --headless +q { currentline = -1, lastlinedefined = 456, linedefined = 452, short_src = "?", source = "=?", what = "Lua" } AFTER: $ nvim --clean +'=debug.getinfo(vim.fn.maparg("]<Space>", "n", 0, 1).callback, "Sl")' --headless +q { currentline = -1, lastlinedefined = 456, linedefined = 452, short_src = "/home/xx/b/neovim/runtime/lua/vim/_core/defaults.lua", source = "@/home/xx/b/neovim/runtime/lua/vim/_core/defaults.lua", what = "Lua" }
2026-04-23fix(lsp): malformed edit if apply_text_edits() is called twice #34954geril072
Problem: Use vim.lsp.util.apply_text_edits to re-apply the same textedit causes an incorrect edit, because apply_text_edits silently modifies the parameter. Solution: - Avoid changing `text_edit._index`. - Document this fun feature. Helped-by: Riley Bruins <ribru17@hotmail.com> Helped-by: Yi Ming <ofseed@foxmail.com> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
2026-04-23fix(pack): only use tags that strictly comply with semver spec #39342Evgeni Chasnovski3
Problem: Using `version=vim.version.range(...)` in plugin specification is meant to use semver-like tags. Whether a tag is semver-like was decided by a plain `vim.version.parse` which is not strict by default. This allowed treating tags like `nvim-0.6` (which is usually reserved for the latest revision compatible with Nvim<=0.6 version) like semver tags and resulted in confusing behavior (preferring `nvim-0.6` tag over `v0.2.2`, for example). Solution: Use `vim.version.range(x, { strict = true })` to decide if the tag name is semver-like or not. This allows tags like both `v1.2.3` and `1.2.3` while being consistent in what Nvim thinks is a semver string. This is technically not a breaking change since it was documented that only tags like `v<major>.<minor>.<patch>` will be recognized as semver.
2026-04-23Merge pull request #39339 from bfredl/reunificationbfredl2
fix(build.zig): reunify parser install path
2026-04-23fix(build.zig): reunify parser install pathbfredl2
Both for tests and for system wide install, $PREFIX/lib/nvim/parser is a valid path for tree-sitter parsers. This also brings the build.zig behavior in line with how we set up the paths in CMakeLists.txt
2026-04-23fix(lsp): callHierarchy/outgoingCalls ranges are relative to caller, not ↵Ashley Hauck2
callee #39336 Problem: The fromRanges field of the result of callHierarchy/outgoingCalls is documented as being relative to the caller. Using vim.lsp.buf.outgoing_calls() opened the qflist with an entry with the callee's filename, but the caller's line number. Solution: Open the qflist with the callers file (the bufnr from the request), rather than the callees (the uri from the resulting CallHierarchyItem)
2026-04-23fix(lsp): filter code_action diagnostics to the cursor #38988Barrett Ruth2
Problem: Cursor-position `vim.lsp.buf.code_action()` requests include all diagnostics on the current line, so unrelated same-line diagnostics affect the returned actions. Solution: Filter same-line diagnostics to the cursor position for cursor-position requests.
2026-04-23fix(terminal): memory leak in pending TermRequest StringBuilder #39333Barrett Ruth2
Problem: Destroying a terminal with pending `TermRequest` events leaks memory. Solution: Make `emit_termrequest` the sole owner of its `pending_send` allocation.
2026-04-23vim-patch:partial:9.2.0315: missing bound-checks (#39334)zeertzjq4
Problem: missing bound-checks Solution: Add defensive guards against potential buffer overflow (Yasuhiro Matsumoto) Add bounds checking and integer overflow guards across multiple files as a defensive measure. While these code paths are unlikely to be exploitable in practice, the guards prevent undefined behavior in edge cases. - libvterm/vterm.c: use heap tmpbuffer instead of stack buffer in vsprintf() fallback path - channel.c: validate len in channel_consume() before mch_memmove() - spell.c: use long instead of int for addlen to avoid signed overflow in size_t subtraction - alloc.c: add SIZE_MAX overflow check in ga_grow_inner() before itemsize multiplication - list.c: add overflow check before count * sizeof(listitem_T) - popupwin.c: add overflow check before width * height allocation - insexpand.c: add overflow check before compl_num_bests multiplication - regexp_bt.c: replace sprintf() with vim_snprintf() in regprop() - spellfile.c: use SIZE_MAX instead of LONG_MAX for allocation overflow check closes: vim/vim#19904 https://github.com/vim/vim/commit/8d23fcb603d8f8938ce0023086326a5db6780ea2 Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-04-23Merge pull request #37882 from zeertzjq/vim-a2d87bazeertzjq5
vim-patch: netrw updates
2026-04-23vim-patch:9.2.0383: [security]: runtime(netrw): shell-injection via sftp: ↵zeertzjq3
and file: URLs Problem: runtime(netrw): shell-injection via sftp: and file: URLs (Joshua Rogers) Solution: Escape temporary file names, harden filename suffix regex, drop unused g:netrw_tmpfile_escape variable Supported by AI https://github.com/vim/vim/commit/405e2fb6d54d5653523809e2853d99d1c000a5fc Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-04-23vim-patch:9.2.0367: runtime(netrw): ~ note expanded on MS Windowszeertzjq2
Problem: runtime(netrw): ~ note expanded on MS Windows (Tom Vamvanij) Solution: Expand ~ on MS Windows (Yasuhiro Matsumoto) On Windows, ":Explore ~" did nothing because the tilde expansion was gated to Unix/Cygwin only. Additionally, substitute() interprets backslashes in the replacement string specially (e.g. \U as a case modifier), which would corrupt $HOME values like C:\Users\name even if the branch were taken. Include has("win32") in the guard, anchor the pattern to the start of the string, and escape backslashes, ampersands and tildes in $HOME before substituting. fixes: vim/vim#20003 closes: vim/vim#20014 https://github.com/vim/vim/commit/723c0acf2535c87a5b7be0284e7379e071a1d610 Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-04-23vim-patch:21c0cd2: runtime(netrw): add missing escape() callszeertzjq1
https://github.com/vim/vim/commit/21c0cd29f808e32a7c159889c6dcf7a6fbf189f7 Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-04-23vim-patch:9.2.0302: runtime(netrw): RFC2396 decoding double escaping spaceszeertzjq2
Problem: runtime(netrw): RFC2396 decoding double escaping spaces (lilydjwg, after 3e60f03d942d6bb0f7eac) Solution: Remove escape() call, since we are using fnameescape() anyhow fixes: vim/vim#19913 https://github.com/vim/vim/commit/ab4ebb62ee2cbe5e25fb1746ac5dbe63a9d50260 Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-04-23vim-patch:9.2.0281: tests: Test_netrw_FileUrlEdit.. fails on Windowszeertzjq1
Problem: tests: Test_netrw_FileUrlEdit.. fails on Windows (after 3e60f03d942d6bb0f7) Solution: Skip the test on Windows (Yasuhiro Matsumoto). The Test_netrw_FileUrlEdit_pipe_injection() test fails on Windows with E303 because '|' is not a valid filename character on Windows. Since the pipe character cannot appear in a Windows filename, the command injection vector this test guards against does not apply on Windows. closes: vim/vim#19890 https://github.com/vim/vim/commit/c91081d0e5d7b4cf5b467b0a622a3c74ef99a08f Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2026-04-23vim-patch:3e60f03: runtime(netrw): use fnameescape() with FileUrlEdit()zeertzjq2
https://github.com/vim/vim/commit/3e60f03d942d6bb0f7eac61b149e83615518cec0 Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-04-23vim-patch:9.2.0089: netrw: does not take port into account in hostname ↵zeertzjq2
validation Problem: netrw: does not take port into account in hostname validation (after v9.2.0073) Solution: Update hostname validation check and test for an optional port number (Miguel Barro) closes: vim/vim#19533 https://github.com/vim/vim/commit/a6198523fb28a50d96945458792cdb4787d3cdda Co-authored-by: Miguel Barro <miguel.barro@live.com>
2026-04-23vim-patch:9.2.0073: [security]: possible command injection using netrwzeertzjq3
Problem: [security]: Insufficient validation of hostname and port in netrw URIs allows command injection via shell metacharacters (ehdgks0627, un3xploitable). Solution: Implement stricter RFC1123 hostname and IP validation. Use shellescape() for the provided hostname and port. Github Advisory: https://github.com/vim/vim/security/advisories/GHSA-m3xh-9434-g336 https://github.com/vim/vim/commit/79348dbbc09332130f4c86045e1541d68514fcc1 Co-authored-by: Christian Brabandt <cb@256bit.org>
2026-04-23vim-patch:9.2.0037: netrw: need better tests for absolute pathszeertzjq2
Problem: netrw: need better tests for absolute paths Solution: Use absolutepath(), instead of regex test (Miguel Barro). closes: vim/vim#19477 https://github.com/vim/vim/commit/bd1dc5b1a652e9f2ba45e3695ea2d83e81992c88 Cherry-pick a typo fix from latest Vim. Co-authored-by: Miguel Barro <miguel.barro@live.com>
2026-04-23vim-patch:a2d87ba: runtime(netrw): Use right file system commands ↵zeertzjq3
initialization for Windows closes: vim/vim#19287 fixes: vim/vim#12290 https://github.com/vim/vim/commit/a2d87ba615f15956116f43f7c70f1b315d679cb4 Co-authored-by: Miguel Barro <miguel.barro@live.com>
2026-04-22vim-patch:9.2.0388: strange indent in update_topline() (#39324)zeertzjq1
Problem: strange indent in update_topline() Solution: Fix the indentation (zeertzjq) closes: vim/vim#20033 https://github.com/vim/vim/commit/f194676c936d9f3a8479a72afbbe9f244039e27e
2026-04-22ci: drop cirrus #39321Justin M. Keyes11
Problem: cirrus will shutdown soon, and we are running out of minutes anyway, which causes ci failures. Solution: Drop cirrus config.
2026-04-22feat(treesitter): expand selection to sibling node #38938altermo5
Problem: Can't expand treesitter-incremental-selection to the next and previous sibling nodes. Solution: Pressing `]N` in visual mode will expand the selection to the next sibling node, and `[N` will do the same with the previous node.
2026-04-22feat(:restart): v:starttime, v:exitreason #39282Justin M. Keyes16
Problem: - The `ZR` feature makes it more obvious that we need some sort of flag so that an `ExitPre` / `QuitPre` / `VimLeave` handler can handle restarts differently than a normal exit. For example, it's common that users want `:mksession` on restart, but perhaps not on a normal exit. - Nvim has no way to report its "uptime". Solution: - Introduce `v:starttime` - Introduce `v:exitreason`
2026-04-22feat(eval): treat Lua string as "blob" in writefile() #39098Barrett Ruth3
Problem: vim.fn.writefile() treats Lua strings as Vimscript strings instead of a "binary clean" string. Solution: Treat Lua-originated strings as blob data.
2026-04-22fix(shada): bdelete'd buffers not stored in oldfiles #39070glepnir2
Problem: b98eefd added `!b_p_bl` to `ignore_buf()`, which also skips bdelete'd buffers since bdelete unsets `b_p_bl`. Solution: Check `b_p_initialized` together with `b_p_bl` so that bdelete'd buffers (which have b_p_initialized=false) are not filtered out. Keep `b_p_bl` check only in `shada_get_buflist()`.
2026-04-22perf(lsp): clear table by table.clear() #39222Yi Ming5
benchmark: https://gist.github.com/ofseed/6224529d77c016c36f7ab2f977059848 local rounds = tonumber(arg[1]) or 1000 local count = tonumber(arg[2]) or 1000 -- Load the table.clear function. local clear = require("table.clear") local function fill(t, n) for i = 1, n do t[i] = i end end local function bench_reassign(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} collectgarbage("collect") fill(t, n_items) end return os.clock() - start end local function bench_reassign_no_gc(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do t = {} fill(t, n_items) end return os.clock() - start end local function bench_clear(n_rounds, n_items) local t = {} local start = os.clock() for _ = 1, n_rounds do clear(t) fill(t, n_items) end return os.clock() - start end -- Warm up LuaJIT before the real benchmark. do local t = {} for _ = 1, 2000 do clear(t) fill(t, count) end end collectgarbage("collect") local reassign_time = bench_reassign(rounds, count) collectgarbage("collect") local reassign_no_gc_time = bench_reassign_no_gc(rounds, count) collectgarbage("collect") local clear_time = bench_clear(rounds, count) print(string.format("rounds=%d count=%d", rounds, count)) print(string.format("t = {} + GC : %.6f s", reassign_time)) print(string.format("t = {} : %.6f s", reassign_no_gc_time)) print(string.format("table.clear : %.6f s", clear_time)) print(string.format("vs + GC : %.2fx", reassign_time / clear_time)) print(string.format("vs no GC : %.2fx", reassign_no_gc_time / clear_time)) benchmark result: rounds=1000 count=1000 t = {} + GC : 0.022469 s t = {} : 0.002570 s table.clear : 0.000387 s vs + GC : 58.06x vs no GC : 6.64x `count` is how many items the table has, and `round` is how many rounds we fill the table, clear, and then refill it. `table = {}` is clear the table by resigning a new empty one, because this script does not run persistently like nvim so GC is not triggered, so I added another extreme control group that manually triggers GC.
2026-04-22fix(cmdline): avoid 'incsearch' recursion after redraw #39303luukvbaal4
Problem: A vim.ui_attach() callback that redraws to show a 'verbose' regex message during 'incsearch' results in recusive redrawing. Solution: Check that curwin was redrawn instead of just any window when determining if 'incsearch' highlighting was cleared.
2026-04-22docs(quickfix): quickfix window location #39300luukvbaal1
Problem: Documentation for quickfix window location is outdated (since 6256adde). Solution: Update quickfix.txt.
2026-04-22fix(options): default 'titlestring' shows CWD #39233Nick Krichevsky6
Problem: In the default 'titlestring', if the containing directory is the CWD, it renders as "." Solution: Add `:p` to the titlestring.
2026-04-22build(deps): bump tree-sitter-c to v0.24.2Christian Clason2