Problem: Session with multiple tabpages sets 'winminheight' to 0.
Solution: Only save 'winminheight' and 'winminwidth' once (zeertzjq).
related: vim/vim#8119
related: neovim/neovim#40493closes: vim/vim#20673294dec827d
Problem: Crash when reading truncated spellfile (MarkLee131)
Solution: Set sl_sofo to TRUE in set_sofo() once sl_sal has been
converted to the soundfold layout.
Supported by AI.
closes: vim/vim#20660488a3eed12
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: filetype: SSH keys and related filetypes not recognized
Solution: Detect sshpublickey, sshknownhosts sshauthorizedkeys and
sshallowedsigners filetypes, add syntax scripts for those
filetypes (Fionn Fitzmaurice)
This adds syntax highlighting for SSH public keys, as well as related
filetypes derived from this (SSH authorized keys, SSH known hosts and
SSH allowed signers).
Also add filetype detection based on the path and name.
closes: vim/vim#206356e66ebc0fd
Co-authored-by: Fionn Fitzmaurice <git@fionn.computer>
Problem: Mapped typed keys didn't interrupt completion in
complete_check() (Yikai Zhao)
Solution: Also interrupt when in_compl_func and not replaying a register.
(glepnir)
closes: vim/vim#5547closes: vim/vim#2064337d85f5f1a
Problem: A crafted swap file can cause an out-of-bounds write during
recovery when the same block is referenced twice with
different pe_page_count values (cipher-creator)
Solution: Check hp->bh_page_count against page_count after mf_get() and
clamp page_count to the actual block size.
closes: vim/vim#2064543939cf9eb
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: With PHP omni-completion, a crafted file can potentially
execute arbitrary commands when completing a class member.
Solution: Quote the class name before inserting it into the search()
pattern run via win_execute().
43afc581a3
Tests only. The bug is not ported yet.
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: [security]: With C omni-completion, a crafted tags file can execute
arbitrary Ex commands when completing a struct/union member
(cipher-creator)
Solution: Escape the type field before inserting it into the :vimgrep
pattern so it cannot close the pattern and start a new command
(Hirohito Higashi).
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-mf92-v4xw-j45x6b611b0d15
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Problem: The "%" command and bracket/text-object motions can skip the
matching paren or bracket on a line with quotes and a trailing
backslash.
Solution: Use the quote state at the search start when an odd-quote line
is continued with a backslash, instead of always treating the
search as starting in quotes (Barrett Ruth).
closes: vim/vim#20631c44a6561cc
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Problem: ":filetype detect" is a valid command but not offered by
command-line completion.
Solution: Add "detect" to the completion candidates (glepnir)
closes: vim/vim#20625984f29860e
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: filetype: supertux info pattern is relative to current
directory (after 9.2.0716).
Solution: Add `*/` to the start of the pattern (zeertzjq)
closes: vim/vim#20629c30ee2efa9
Problem:
cmdwin (the `:q` cmdline buffer) has various limitations which require
special-casing all over the codebase.
Besides complicating the code, it also breaks async plugins if they try
to create buffers/windows after some work is done, if the user happens
to open cmdwin at the wrong the moment:
Lua callback: …/guh.nvim/lua/guh/util.lua:531:
E11: Invalid in command-line window; <CR> executes, CTRL-C quits
stack traceback:
[C]: in function 'nvim_buf_delete'
…/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526>
Solution:
Just say no to "inception". Reimplement cmdwin as a normal buffer+window.
All of the cmdwin contortions (in both core, and innocent plugins) exist
literally only to support "inception": recursive
cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute,
`:input()`, etc. So we just won't support that (though I have
a potential plan for that later, which I call "modal parking lot").
The benefit is that plugins, and core, no longer have to care about
cmdwin.
BONUS:
- mouse-drag on vertical separators works (it only worked for
horizontal/statusline before)
- inccommand-in-cmdwin now works correctly, for free (thus don't need
#40077).
POTENTIAL FOLLOWUPS
- Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos.
- Unify `BUFLOCK_OK` / `LOCK_OK` ?
DESIGN:
- Eliminate lots of C globals, `EX_CMDWIN`, etc.
- `text_locked()` no longer reports true for cmdwin.
- cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe',
'buftype=nofile'. Invariants come from those options rather than
special cases throughout the codebase.
- `nv_record` for q:/q//q? calls Lua
`nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN`
/ cmdline-reader detour.
- `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls
`vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so
the in-flight cmdline cancels. Reader state is not serialized; instead
the captured `(type, line, col)` is replayed via
`nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms.
- On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the
window and re-feeds the cmdline.
BREAKING CHANGES:
- Expression-register cmdline (`<C-R>=` from insert-mode) no longer
supports cmdwin. Same applies to `input()` / `inputlist()` (already
covered by `text_locked`).
- Usage of cmdwin in macros/mappings will probably break (assuming they
ever worked).
Problem: [security]: A crafted spell file with non-collapsing SAL rules
can make soundfold() write one byte past the end of the
MAXWLEN result buffer. This is the same class of
out-of-bounds write as GHSA-q8mh-6qm3-25g4 (fixed in 9.2.0698
for the SOFO branch), found while auditing the surrounding
code.
Solution: Bound the single-byte SAL result writes and the terminating
NUL to MAXWLEN - 1, matching the SOFO branch.
The single-byte branch of spell_soundfold_sal() guarded its writes with
"reslen < MAXWLEN", allowing reslen to reach MAXWLEN (254). The trailing
"res[reslen] = NUL" then wrote at index 254 of the 254-byte stack buffer
res[MAXWLEN], an off-by-one out-of-bounds write. Input is case-folded to
about 253 characters, so a 253-character argument together with a SAL map
that does not collapse (collapse_result false) reaches the boundary.
Related to previous issue
[GHSA-q8mh-6qm3-25g4](https://github.com/vim/vim/security/advisories/GHSA-q8mh-6qm3-25g4)
(9.2.0698)
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-m3hf-xcm3-xhm2d22ff1c955
This is N/A as Nvim doesn't have spell_soundfold_sal() which is only
used in the !has_mbyte code path.
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: tests: strange indent in Test_autocmd_dup_arg()
(after v9.2.0708)
Solution: Indent using the settings in the modeline.
closes: vim/vim#2061905df981c35
Problem: :syn sync without an argument also lists every defined cluster
Solution: Fix control flow in syn_cmd_list() so that only the syncing
items are printed when this function gets called by :syn sync.
(dmitmel)
closes: vim/vim#20614f2954c821e
Problem: Leak in do_autocmd in error case (Cheng)
Solution: goto err_exit in the error case and clean up, make the double
++once an actual error
closes: vim/vim#2060698f5171ef6
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: When the cursor line has concealed text before the start of the
completion, the insert-mode completion popup is drawn at the wrong
screen column and the cursor no longer lines up with the completed
text.
Solution: Record the concealed width before the cursor on its screen line in
a new `win_T` field while `win_line()` draws it, subtract it in
`pum_display()` to place the menu over the visible text, and redraw
the cursor line so `win_line()` corrects the cursor too.
closes: vim/vim#20539d167c50de4
Co-authored-by: Barrett Ruth <br@barrettruth.com>
Problem: With 'winfixbuf' set in the current window, :windo and :tabdo
create an extra split window, even though they only visit
existing windows/tabpages and don't change the current
window's buffer (Collin Kennedy)
Solution: Skip the 'winfixbuf' escape in ex_listdo() for :windo and
:tabdo (ShivaPriyanShanmuga)
fixes: vim/vim#14301closes: vim/vim#206005767d80b37
Problem: ':delete #' silently fails to update "# and clobbers "0.
Solution: Treat "# like "/, writable only with :let and setreg().
closes: vim/vim#205927aeab74687
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Problem: [security]: Out-of-bounds write with soundfold()
(cipher-creator)
Solution: Add an abort condition to the for loop to validate the buffer
size.
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-q8mh-6qm3-25g4
Supported by AI
497f931f85
This is N/A as it only changes the !has_mbyte code path.
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: The "%" command can be very slow on a long line that contains
many slashes, for example a line of base64 data.
Solution: When looking for a line comment, scan the line only once while
skipping over strings, instead of rescanning from the start for
every slash. Move check_linecomment() to cindent.c so it can
reuse the file-local skip_string().
related: vim/vim#20491
fixes: vim/vim#20557
closes: vim/vim#205759f9af034ad
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: ':registers #' does not display the value of the '#' register.
Solution: Filter the '#' :registers output on a '#' arg instead of '%'
(Doug Kearns).
closes: vim/vim#205890cafe56b74
Co-authored-by: Doug Kearns <dougkearns@gmail.com>
Problem: ":filetype plugin<Tab>" gives "pluginindent" because a
sub option before the cursor is treated as already given.
Solution: only skip plugin and indent when followed by white space.
(glepnir)
closes: vim/vim#20594fe65f23aca
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: Wrong dot-repeat when calling complete() while filtering
Ctrl-N completion.
Solution: Also check compl_started for whether completion is active.
(zeertzjq)
related: neovim/neovim#40346
closes: vim/vim#2059537a7e4944f
Problem: Error when using "none" for GUI color is confusing.
Solution: Mention that the name should perhaps be "NONE". (closesvim/vim#1400)
5b9f57262f
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Problem: tests: Test_cd_from_non_existing_dir() fails on Solaris
Solution: Skip the test on Solaris (Vladimír Marek).
Test_cd_from_non_existing_dir() depends on deleting the current working
directory. Solaris does not allow that, so skip the test there.
closes: vim/vim#20563b464c36bf9
Co-authored-by: Vladimír Marek <vlmarek13@gmail.com>
Problem: tests: Test_recover_corrupted_swap_file() cannot handle
symlinks
Solution: Use writefile(readblob()) instead (Vladimír Marek)
Test_recover_corrupted_swap_file1() copies prebuilt corrupt swap samples
before recovering them. In an out-of-source-tree build those sample
files may be symlinks into the source tree. filecopy() preserves
symlinks, so the copied target may remain a symlink. Recovery opens
swap files with O_NOFOLLOW, so that copied symlink cannot be opened.
Read the sample as a blob and write it back so the recovery target is a
real swap file.
closes: vim/vim#2056188cbd00312
Co-authored-by: Vladimír Marek <vlmarek13@gmail.com>
Problem: On MS-Windows it is not possible to switch to a buffer by name
with ":b" (including via command-line completion) when the
buffer name contains '%'.
Solution: Do not escape '%' and '#' for the ":buffer" command on
MS-Windows. Since ":buffer" has no EX_XFILE these are not
expanded, and escaping them as "\%"/"\#" makes buffer name
matching fail when '%'/'#' is in 'isfname' (the backslash is
treated as a path separator).
fixes: vim/vim#20529closes: vim/vim#205481a96e07bf6
Co-authored-by: Hirohito Higashi <h.east.727@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem: Crash with TextPut autocmd when pasting in normal mode in a
terminal buffer.
Solution: Skip the TextPut autocmds when reg and insert are both NULL
and regname is not '.' (Foxe Chen).
closes: vim/vim#204072e7833bde9
Co-authored-by: Foxe Chen <chen.foxe@gmail.com>
Problem: [security]: s:NetrwLocalRmFile() escapes only the backslash in
the file name before passing it to :execute, so a name
containing "|" injects arbitrary Ex commands when the file is
deleted (cipher-creator)
Solution: Use fnameescape() to correctly escape the file name
(Yasuhiro Matsumoto).
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-vhh8-v6wx-hjjh
Supported by AI
55bc757a5d
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Problem: [security]: a crafted spell file with a self-referential
BY_INDEX node in the prefix tree can drive dump_prefixes()
past the end of its MAXWLEN-sized depth arrays on :spelldump
(cipher-creator)
Solution: only descend while depth < MAXWLEN - 1, as the sibling trie
walkers already do (Yasuhiro Matsumoto)
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-qm9w-fmpj-879h
Supported by AI
8325b193bb
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Problem: With 'longest', 'smartcase' is ignored when filtering matches:
"inp" offers only "InputEvent", and an uppercase pattern gives
different results for CTRL-N and CTRL-P.
Solution: 'longest' rewrites the leader with the common prefix, picking
up uppercase the user never typed. Judge case from the typed
text instead, and match the auto-inserted part of the leader
case-insensitively so CTRL-N and CTRL-P give the same result.
(glepnir)
related: neovim/neovim#40259
closes: vim/vim#2053350fe45aca7
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: [security]: a crafted spell file can drive tree_count_words()
past the end of its MAXWLEN-sized depth arrays; the descent
loop has no depth bound.
Solution: only descend while depth < MAXWLEN - 1, as the sibling trie
walkers already do; apply the same guard to sug_filltree().
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-wgh4-64f7-q3jq
Supported by AI.
a80874d9b8
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: filetype: tf files sometimes incorrectly recognized
(Christian Robinson)
Solution: Add support for g;filetype_tf variable to override detection,
re-write the filetype detection loop
closes: vim/vim#20510
Supported by AI
522a39a489
Co-authored-by: Christian Brabandt <cb@256bit.org>
Problem: When a candidate gets truncated to MATCH_MAX_LEN and ends up
the same length as the needle, the n == m shortcut would
return SCORE_MAX with positions 0..n-1, even if the strings
actually differ.
Solution: Only use the shortcut if the truncated strings are truly equal.
Otherwise, fall back to regular matching.
Example:
echo matchfuzzypos(['x' .. repeat('a',1024)], repeat('a',1024))
closes: vim/vim#204751437f47815
Co-authored-by: glepnir <glephunter@gmail.com>
Problem: Problem with initializing the length of range() lists
Solution: Set length explicitly when it shouldn't contain any items
range() may cause a wrong calculation of list length, which may later
then cause a segfault in list_find(). This is usually not a problem,
because range_list_materialize() calculates the length, when it
materializes the list.
In addition, in list_find() when the length of the range was wrongly
initialized, it may seem to be valid, so the check for list index
out-of-bounds will not be true, because it is called before the list is
actually materialized. And so we may eventually try to access a null
pointer, causing a segfault.
So this patch does 3 things:
- In f_range(), when we know that the list should be empty, explicitly
set the list->lv_len value to zero. This should happen, when
start is larger than end (in case the stride is positive) or
end is larger than start when the stride is negative.
This should fix the underlying issue properly. However,
- as a safety measure, let's check that the requested index is not
out of range one more time, after the list has been materialized
and return NULL in case it suddenly is.
- add a few more tests to verify the behaviour.
fixes: vim/vim#13557closes: vim/vim#13563
--------
Vim9 (non) materialize list is N/A.
Port only tests.
df63da98d8
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Tim Pope <tpope@github.com>
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
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>