Problem: statusline: buffer overflow with item groups
Solution: Fix the issues (see below) (Sébastien Hoffmann)
Fix various buffer overflow bugs (examples assume MAXPATHL==4096):
- truncated item groups where minwid>maxwid:
vim --clean +"set ls=2 stl=%<%{%repeat('x',4096-11)%}%50.5(12🙂345%)"
leads to fillchars spilling over the end of the group/buffer while trying to
compensate for truncating at a multicell character because minwid<=maxwid is assumed
- left-aligned item groups with multi-byte fillchar:
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%<%{%repeat('x',4096-3)%}%-2(X%)"
wrongly leads to padding at the end of the statusline and `p-out==4097`
because the bounds check assumes a 1-byte fillchar
- right-aligned item groups with 1-byte fillchar:
vim --clean +"set ls=2 stl=%<%{%repeat('x',4096-4)%}%4(XY%)"
leads to "YX" instead of "XY" at the end of the statusline
because `memmove` is done before adjusting the offset
- right-aligned item groups with multi-byte fillchar:
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%5(X%)"
leads to "∙∙∙∙<e2>", i.e. the fillchar is being written over the group contents
and eventually being overwritten itself at the second byte with the final NUL,
because the padding counter assumes a 1-byte fillchar; to crash vim,
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%<%{%repeat('x',4096-149)%}%50(X%)"
related: neovim/neovim#40219
closes: vim/vim#20522d249884340
Co-authored-by: Sébastien Hoffmann <contact@shoffmann.dev>
Problem: Composing chars are no longer accepted in end-id abbreviation
(after 9.2.0629).
Solution: Unescape all chars using vim_unescape_csi() instead of using
mb_unescape() on individual chars, so that mb_ptr2len() and
MB_PTR_ADV() can still be used.
closes: vim/vim#2051423a84d28a8
Problem: 0x80 and 0x9b byte not unescaped when checking for valid abbr
(Mao-Yining)
Solution: Use mb_unescape() (zeertzjq).
fixes: vim/vim#20506closes: vim/vim#205081958c991a8
(AI-assisted)
Problem:
Zig build failing since 966e7a98f5:
FAILED ...r/work/neovim/neovim/test/functional/editor/xxd_spec.lua @ 22: xxd handles long lines in revert mode
Expected values to be equal.
Expected:
0
Actual:
134
stack traceback:
...r/work/neovim/neovim/test/functional/editor/xxd_spec.lua:26: in function <...r/work/neovim/neovim/test/functional/editor/xxd_spec.lua:22>
`huntype` parses the address column by repeatedly left-shifting
`want_off` (a signed `long`) by 4 bits per hex digit. After 16 hex
digits the value occupies all 64 bits; the next shift moves a non-zero
bit into the sign bit -- signed overflow, i.e. undefined behavior.
This happens on the Zig build because it enables UBSAN. The bug was
pre-existing, but 966e7a98f5 added a test that exercises it.
Solution
Shift through `unsigned long` and cast back to `long`, making the
overflow well-defined wrap-around.
Problem:
All (tested by me) terminals (xterm, st, ghostty, vte, foot, wezterm, konsole) do support `\x1b[0 q` as "reset cursor to default", but at least konsole and wezterm only understands `\x1b[0 q` as "reset to default", but have different behaviour on `\x1b[ q` (konsole sets "steady block", and wezterm does nothing (do not change cursor shape).
Solution:
Use `\x1b[0 q` would be more widely compatible "reset" sequence than `\x1b[ q`
P.S. actually, `xterm`, `ghostty` and `st` (with default config.h) sets "steady block" for both sequence, but still here `[0` behaves the same as `[`
vim-patch:9.2.0626: Vim9: illegal characters allowed in dict key names with dot notation
vim-patch:9.2.0630: popup images: kitty images output in GUI mode
vim-patch:7bc4491ad CI: Bump the github-actions group across 1 directory with 3 updates
vim-patch:9.2.0634: GTK4: no minimum resize limit
vim-patch:ad8d21b14 runtime(syntax-tests): Rename test files on demand
vim-patch:8.1.2076: crash when trying to put a terminal in a popup window
vim-patch:8.2.1090: may use NULL pointer when skipping over name
vim-patch:8.2.1755: Vim9: crash when using invalid heredoc marker
vim-patch:8.2.1854: Vim9: crash when throwing exception for NULL string
vim-patch:8.2.1884: compiler warning for uninitialized variable
vim-patch:8.2.1924: Vim9: crash when indexing dict with NULL key
vim-patch:8.2.2292: Vim: expr test fails
vim-patch:8.2.3340: accessing uninitialized pointer
vim-patch:8.2.3359: Vim9: error for type when variable is not set
vim-patch:8.2.3396: when libcall() fails invalid pointer may be used
vim-patch:8.2.4000: Coverity warns for checking for NULL pointer after using it
vim-patch:8.2.4269: Coverity warns for using a NULL pointer
vim-patch:8.2.4539: when comparing special v:none and v:null are handled the same
vim-patch:8.2.4822: setting ufunc to NULL twice
vim-patch:9.0.1095: using freed memory when declaration fails
vim-patch:9.0.1375: crash when getting member of obj of unknown class
Problem: Keys valid in CTRL-X mode are never mapped while insert
completion is active, so <C-N> and <C-P> cannot be remapped
for completion started by complete().
Solution: Do not disable mappings in CTRL_X_EVAL mode. In this mode a
mapping cannot interfere with selecting the completion
method, which is what the no-mapping rule exists for.
related: vim/vim#6440
related: vim/vim#16880
closes: vim/vim#20489076585e6ad
Co-authored-by: Thomas M Kehrenberg <tmke8@posteo.net>
Problem: Deciding whether a group is in a "contains"/cluster list scans
the list and expands clusters on every check, which is slow for
syntaxes with large lists (e.g. plugins such as netrw).
Solution: Resolve each list once into a sorted, cluster-expanded set of
group IDs and use a binary search; cache it per syntax block and
drop the cache when syntax definitions change (Hirohito Higashi).
closes: vim/vim#2049048fbae4378
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Problem: The "%" command jumps to parens and braces inside comments,
unlike the "=" operator (cindent), which ignores them.
Solution: When 'comments' defines C-style comments and "%" is not in
'cpoptions', skip matching parens inside such comments, except
when the cursor is inside a comment so a match there can still
be found.
fixes: vim/vim#20329
related: vim/vim#20111
closes: vim/vim#20491b8a109dcfb
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: gq (and other filters) on an empty buffer fail with
"E20: Mark not set": when the filter produces no output,
do_filter() still subtracts the line count from '[ and '],
pushing '] to line 0.
Solution: when the filter produces no output, put '[ and '] on a valid
line instead of subtracting past line 1 (glepnir).
related: neovim/neovim#30593
closes: vim/vim#19061aefbca2977
Problem:
Various out-of-bounds writes inherited from vim (examples assume MAXPATHL==4096):
- truncated item groups where minwid>maxwid:
nvim --clean +"set stl=%<%{%repeat('x',4096-11)%}%50.5(12🙂345%)"
leads to fillchars spilling over the end of the group/buffer while trying to
compensate for truncating at a multicell character because minwid<=maxwid is assumed
- left-aligned item groups with multi-byte fillchar:
nvim --clean +"set fillchars+=stl:∙ stl=%<%{%repeat('x',4096-3)%}%-2(X%)"
wrongly leads to padding at the end of the statusline and `out_p-out==4097`
because the bounds check assumes a 1-byte fillchar
- right-aligned item groups with 1-byte fillchar:
nvim --clean +"set stl=%<%{%repeat('x',4096-4)%}%4(XY%)"
leads to "YX" instead of "XY" at the end of the statusline
because `memmove` is done before adjusting the offset
- right-aligned item groups with multi-byte fillchar:
nvim --clean +"set fillchars+=stl:∙ stl=%5(X%)"
leads to "∙∙∙∙<e2>", i.e. the fillchar is being written over the group contents
and eventually being overwritten itself at the second byte with the final NUL,
because the padding counter assumes a 1-byte fillchar; to crash Neovim,
nvim --clean +"set fillchars+=stl:∙ stl=%<%{%repeat('x',4096-149)%}%50(X%)"
Solution:
Clearer variable names and no recycling of variables for different purposes.
Problem: Clicking on a "below" virtual line interacts with the line
it is attached to for decor/drawing purposes, rather than
the line the extmark is placed at.
Solution: Account for "below" virtual lines when computing mouse line number.
Problem: Vim9: null value tests not sufficient
Solution: Add a more comprehensive test for null values
(Yegappan Lakshmanan)
closes: vim/vim#14701da9d345b3d
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
vim-patch:9.1.0053: MS-Windows: Key event test still fails
vim-patch:9.1.0057: MS-Windows: Key event test still fails
vim-patch:9.2.0540: tests: Test_mswin_event_mouse is flaky
vim-patch:9.2.0590: GTK4: drawing area loses focus shape on popup menu open
vim-patch:9.2.0595: MS-Windows: Wrong buffer size calculation for gvimext
vim-patch:9.2.0599: popup: title set with popup_setoptions() is not shown
vim-patch:057db5f7e CI: Bump actions/checkout in the github-actions group across 1 directory
vim-patch:48f2e78c8 runtime(doc): Add gtk4-slow doc tag
vim-patch:9e4042b2b translation(it): Update Italian man page
vim-patch:9.2.0604: tests: Test_mswin_event_mouse() is still flaky
vim-patch:9.2.0607: GTK4: inputdialog() does not work as expected
vim-patch:9.2.0613: tests: test_xxd_color2() checks for dash but uses sh
vim-patch:9.2.0616: GTK4: use-after-free on clipboard read timeout
vim-patch:9.2.0617: GvimExt: does not support different runtime dirs
vim-patch:9.2.0618: use-after-free in popup_getoptions() on dict_add() failure
vim-patch:9.2.0619: integer overflow in popup image size validation
vim-patch:0abffbff2 CI: Remove Cirrus CI and Coverity Scan
vim-patch:8.2.2583: Vim9: cannot compare result of getenv() with null
vim-patch:8.2.4087: cannot test items from an autoload script easily
vim-patch:8.2.4534: Vim9: "is" operator with empty string and null returns true
vim-patch:9.0.1674: help for builtin functions is not sorted properly
vim-patch:9.0.1727: minor problems with the teapot
vim-patch:9.0.1796: Vim9 problems with null_objects
vim-patch:9.0.1914: Vim9: few issues when accessing object members
vim-patch:9.0.2001: Vim9: segfault with islocked()
vim-patch:9.1.0385: Vim9: crash with null_class and null_object
vim-patch:9.1.0391: Vim9: could improve testing
vim-patch:9.1.0620: Vim9: segfauls with null objects
vim-patch:9.1.1865: tests: do not notice lines containing only a tab
vim-patch:9.1.2029: tests: the test_vim9_class.vim testfile is too long
vim-patch:9.2.0195: CI: test-suite gets killed for taking too long
Problem:
The 'autoread' option only checks for file changes reactively — on
FocusGained, :checktime, CmdlineEnter, etc. — by polling timestamps.
External changes are not detected until the user interacts with Neovim.
Solution:
Add a core module (runtime/lua/nvim/autoread.lua) enabled from
runtime/plugin/autoread.lua that watches each buffer's file using
vim._watch.watch() (libuv fs_event). On change detection it calls
:checktime, which invokes the existing buf_check_timestamp() logic
for reload/prompt handling. Watchers are managed via autocmds tied
to buffer lifecycle events and respect the 'autoread' option (global
and buffer-local).
Problem:
stdpath() may return a DOS 8.3 "shortened" filename, because Windows
truncates long usernames into `6ch~N` names in `TEMP/TMP` env vars.
We don't want to "leak" them into Nvim.
Solution:
For "run", pass `true` to `vim_FullName` to expand 8.3 filenames.
For "cache", call `os_realpath` to expand 8.3 filenames.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem: possible integer overflow in spellfile tree bounds check
Solution: Rewrite the overflow check (Devon Krik)
The check 'startidx + len >= maxidx' uses signed int addition and can
overflow when startidx approaches INT_MAX. After overflow the wrapped
result bypasses the guard, allowing the subsequent loop to write
idxs[startidx + i] out of bounds on the heap.
Replace the addition with a safe subtractive check that maintains the
original >= semantics: len >= maxidx - startidx cannot overflow because
both operands are valid indices within [0, maxidx].
This fixes CWE-190 (Integer Overflow) leading to CWE-122 (Heap-based
Buffer Overflow).
closes: vim/vim#20483276920e138
Co-authored-by: Devon Kirk <hyder365@users.noreply.github.com>
Problem: 'autoindent' not stripped with virtualedit=onemore (after
9.2.0510).
Solution: Restore the decrement of cursor column when it's on NUL.
fixes: neovim/neovim#40183closes: vim/vim#204764b13277edd
Problem:
`foldcolumn` is empty for virtual lines above the start of a nested
fold.
Solution:
For virtual lines, compute the outer fold level and display it by
reusing the logic from `fill_foldcolumn`.
Problem:
Since 5181984d, `nvim_exec_autocmds({buf=…})` temporarily sets the
`buf`-window as current-window, and its statusline renders as
a "current-window statusline", regardless of the user's actual
current-window.
Solution:
Mark the statusline for redraw in `aucmd_restbuf()`, so it is redrawn
correctly after the event.
Co-authored-by: Luuk van Baal <luukvbaal@gmail.com>
Problem:
* 'shellcmdflag' states that its default value is set according to the
value of 'shell', but this behavior is not yet implemented on Windows.
The same applies to 'shellpipe', 'shellredir', and 'shellxquote'.
* On Windows, Git is often installed in paths containing spaces, and we
still do not correctly resolve the sh executable name as described in
'shell'.
* On Windows, the default value of 'shellslash' is always `false`,
which causes Unix-like shells to interpret `\` in paths returned by
some functions as escape charaters.
Solution:
Use a simple rule table to detect common shells (e.g. `cmd`,
`powershell`, shells whose names contain `csh` or `sh`) and apply
best-effort defaults, while leaving more complex scenarios to user
configuration.
Problem:
stdpath() may return a DOS 8.3 "shortened" filename, because Windows
truncates some long usernames into `6ch~N` names. Then features such
as `nvim_get_runtime_file` fail to find the file.
Analysis:
When expanding an 8.3 filename path like `C:/Users/ADMINI~1/AppData/*`,
we treat `~` as a special character and first check whether a directory
named `ADMINI~1` exists under `Users`. Since no such directory actually
exists, the expansion fails.
Solution:
Treat `~` as a literal character in `do_path_expand`. Since the `~/`
case is already handled in `gen_expand_wildcards`, any remaining `~` is
just a literal character and will later be escaped to `\~` by
`file_pat_to_reg_pat` if needed.
Now that wasmtime has introduced LTS releases (and tree-sitter tracks
them), we no longer need to pin the version exactly but can rely on
any major.minor version being compatible. This avoids having to edit
the CMake file on every patch bump.
Problem: docs say {str} is capped at 256 and longer returns an empty list.
Solution: it's 1024, and {str} plus each candidate are just truncated to
that, not rejected; fix the text.
closes: vim/vim#20453595d0a77e4
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: A '}' inside a // line comment changes the indentation of the
following line inside an enum or struct (rendcrx).
Solution: Stop scanning the line once a line comment is reached, so a brace
inside the comment is no longer mistaken for an unmatched brace.
fixes: vim/vim#20455closes: vim/vim#204589dd86dff9b
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: Extmark has support for horizontal scrolling and truncating, but not wrapping.
Solution: Extend virt_lines_overflow flags to support "wrap" and "auto" based on proposed changes in #18282.
Problem: In command-line completion with a popup menu ('wildoptions'
contains "pum"), the info popup shown next to the menu could
not be scrolled, unlike the Insert mode completion info popup
which scrolls with the mouse wheel.
Solution: When the mouse pointer is on top of the info popup, scroll it
with the mouse wheel in command-line mode as well, without
closing the completion popup menu.
closes: vim/vim#20146closes: vim/vim#2041896dbab257a
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: A needle that only matches past char 1024 gives an INT_MIN + 1
score with unset positions, e.g.
matchfuzzypos([repeat('a',1024)..'z'], 'az').
Solution: Drop the candidate when match_positions() returns SCORE_MIN.
closes: vim/vim#2043552003f7fc1
Problem:
The comma form of 'winborder' is split with copy_option_part(),
whose skip_to_option_part() eats spaces after a comma, and empty
fields are rejected.
Solution:
Split the comma form literally on ',', keeping empty fields and
single-space fields.
This was originally used because we needed a lua interpreter to run the
standalone _busted_ lua application (except we used fuckery behind the
scenes to fake its binary dependencies with our own binary
dependencies). Now we longer do that, we instead run `test.harness` as a
standard nvim -l script. as this mode is no longer used in tests it
risks going to bitrot anyway.
NB: -ll mode still had some theoretical benefits like quicker
initialization and more "native" printing behavior, etc.
But we can incrementally work on "nvim -l" mode instead
of maintaining a separate special thing.
Problem: in 'qf_free_items', 'qf_ptr' and 'qf_start' are set to NULL
twice. this looks like a leftover from a previous refactor.
Solution: remove the first instance of both duplicates.
Problem: srolljump=-100 only scrolls half a page going up, but works
fine going down. update_topline() always falls back to
scroll_cursor_halfway() when the cursor is far above topline.
Solution: Only center when sj is smaller than half the window. Otherwise
call scroll_cursor_top like the downward path does (glepnir).
fixes: vim/vim#1527closes: vim/vim#20366a4a60c0fdb
Problem: Redundant newlines and "Press any key" prompt with ext_messages
for Visual filter command.
Solution: Remove newlines and prompt with ext_messages.
Problem:
This doc on `vim.lsp.completion.get()`:
--- Used by the default LSP |omnicompletion| provider |vim.lsp.omnifunc()|, thus |i_CTRL-X_CTRL-O|
--- invokes this in LSP-enabled buffers. Use CTRL-Y to select an item from the completion menu.
--- |complete_CTRL-Y|
...makes two wrong claims:
1. "Used by the default LSP omnicompletion provider vim.lsp.omnifunc()"
- `_omnifunc` does not call `M.get()`, it calls the internal `trigger()` directly.
2. "thus |i_CTRL-X_CTRL-O| invokes this in LSP-enabled buffers"
- The two paths use different client sets:
- `M.get()` reads `buf_handles[bufnr].clients` (clients
explicitly registered via `vim.lsp.completion.enable(true, ...)`).
- `_omnifunc` reads `lsp.get_clients({method='textDocument/completion'})` (every
completion client, regardless of `enable()`).
Solution:
Update docs.
Co-authored-by: Koichi Shiraishi <zchee.io@gmail.com>
Co-authored-by: y9san9 / Alex Sokol <y9san9@gmail.com>
Co-authored-by: adv0r <>
vim-patch:9.0.0887: cannot easily try out what codes various keys produce
vim-patch:9.0.0889: keycode check script has a few flaws
vim-patch:9.0.0955: libvterm does not support the XTQMODKEYS request
vim-patch:9.2.0556: GTK4: scrollbars not shown and do not respond to clicks
vim-patch:9.2.0563: GTK3/Wayland: crash with right mouse-button in tabline
vim-patch:9.2.0564: GTK4: tabline does not respond to mouse clicks
vim-patch:0e8cf80ca CI: Bump github/codeql-action
vim-patch:9.2.0569: out-of-bounds access in libvterm CSI 8 t resize
vim-patch:9.2.0570: GTK4: mouse wheel scrolling does not work correctly
vim-patch:9.2.0571: Vim9: memory leak in compile_nested_function() on failure
vim-patch:905312e0e NSIS: Fix 32-bit context menu
vim-patch:9.2.0574: tests: missing test for v9.2.0572
vim-patch:9.2.0577: GTK4: window resizing issues
vim-patch:9.2.0578: GTK4: :unmenu does not remove entries from the menubar
vim-patch:9.2.0580: xxd: binary output is not colored with -R
vim-patch:b7d07d3e8 translation(it): Update Italian xxd man page
vim-patch:9.2.0584: GTK4: missing UI features
vim-patch:9.2.0587: GTK4: left scrollbar overlaps drawarea
vim-patch:9.2.0588: GTK4: drawing area loses focus after closing a menubar popover
Problem:
Edit a file with a drive-letter path, then re-edit it without the drive letter
and colon. This cause `path_fnamencmp` to loop infinitely as `len` never
reaches 0, while `c1` and `c2` are already NUL.
Commit e18a578 accidentally used || before `(p_fic`, commit 4bcee96 fixed that,
but also moved the NUL check into a grouped condition. The bug remained hidden
because there weren't any cases where strings had different lengths and c1 and
c2 could both reach NUL. `c:/foo` vs `/foo` happens to be such a case, which is
why the infinite loop finally showed up.
Solution:
Break the loop when either `c1` or `c2` is NUL.
Problem: After maximizing and deleting the quickfix buffer, window
height is wrong (tertium)
Solution: Reset the winfixheight option when a quickfix buffer is
deleted from a window (Yegappan Lakshmanan)
fixes: vim/vim#3378closes: vim/vim#2040307f055f579
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>