Problem: Wrong cursor position when entering command line window
Solution: Add check_cursor() command to verify the cursor position
(Hirohito Higashi).
When opening the command-line window with CTRL-F after typing a command
that fills the screen width, the cursor was placed past the end of the
line. Add check_cursor() after setting State to MODE_NORMAL so the
cursor is adjusted to the last character.
Also fix the cmdwin prefix character (e.g. ':') being drawn on wrapped
continuation rows. Draw an empty space instead so that the text
alignment is preserved.
closes: #19964
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: channel: ch_listen() can bind to network interface
Solution: Only allow to use Unix domain sockets or localhost interface
(Zdenek Dohnal)
related: #19231
related: #19799
closes: #19973
Signed-off-by: Zdenek Dohnal <zdohnal@redhat.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: test_clientserver may fail on slower systems
Solution: Wait for argc() before checking argv() (James McCoy).
On slower systems, the argv() check may run before the server has
populated the arg list.
Add a wait for argc() to be 3 to be more tolerant of such systems
closes: #19974
Signed-off-by: James McCoy <jamessan@jamessan.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: test_excmd.vim leaves swapfiles behind
Solution: Close open buffer using :bw!
related: #19975
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: some functions can be run from the sandbox
Solution: Block them, so they are not accessible from a modeline
(q1uf3ng)
closes: #19975
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: q1uf3ng <q1uf3ng@protone.me>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: nfa_regmatch() allocates and frees two list buffers on every
call, causing unnecessary memory allocation overhead for
frequently used patterns.
Solution: Cache the list buffers in the regprog struct and reuse them
on subsequent top-level calls. Recursive calls still allocate
their own buffers. Free cached buffers in nfa_regfree()
(Yasuhiro Matsumoto).
Benchmark: 10K lines, `:%s` x50 iterations
| Pattern | Before | After | Improvement |
|---|---|---|---|
| `\<\(\w\+\%(ing\|tion\|ed\|ly\)\|\w\{3,}\)\>` (many matches) | 4.384s | 4.299s | -2% |
| `\(foo\|bar\|baz\)\{3,}\(qux\|quux\|corge\)\{2,}...` (no match, high nstate) | 16.927s | 3.015s | -82% |
closes: #19956
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Allow to configure max length for the summary line and fall back to gits
setting.
closes: #19905
Signed-off-by: Emilia <emilia@bewitching.dev>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Cannot handle mouseclicks in the tabline
Solution: Support %[FuncName] click regions in 'tabline', add "area" key
to the click info dict (Yasuhiro Matsumoto).
The previous implementation resolved and stored click regions only for
per-window statuslines; the tabline path in win_redr_custom() (wp==NULL)
parsed %[FuncName] but discarded the regions, and tabline clicks were
dispatched via TabPageIdxs[] which didn't know about them.
Add a global tabline_stl_click array populated from the tabline path,
refactor stl_click_handler() to take the regions directly, and dispatch
matching clicks from do_mouse() before falling through to tab selection.
The winid entry in the callback dict is 0 for tabline clicks.
related: #19841
closes: #19950
Supported by AI.
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: check_range_index_one() expects a long * but n1 is a
varnumber_T. Casting varnumber_T * to long * is undefined
behaviour and reads the wrong bytes on big-endian platforms
(John Paul Adrian Glaubitz)
Solution: Use a local long variable and pass that pointer to
check_range_index_one() (James McCoy)
fixes: #19798closes: #19952
Signed-off-by: James McCoy <jamessan@jamessan.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: libvterm: no terminal reflow support
Solution: Support for reflowing, sync libvterm to revision 843
(Cimbali)
fixes: #2865closes: #8365closes: #19863
Co-authored-by: Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
Signed-off-by: Cimbali <me@cimba.li>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: On GTK3 with client-side decorations the window opens with
wrong &columns/&lines, and each :tabnew/:tabclose cycle
shrinks the size further.
Solution: Measure and compensate for the CSD frame offset, discard
spurious configure events from tabline show/hide
(Gary Johnson).
closes: #19853
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Gary Johnson <garyjohn@spocom.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: popup: still opacity rendering issues
Solution: Fix remaining issues, see below
(Yasuhiro Matsumoto).
This PR fixes the following issues:
- Padding blend hole at wide char boundary: when a padding cell overlaps
the second half of a wide character, the right half's attr value is
unreliable. Use the left half's saved attr for blending instead.
- Wide char background split at popup boundary: when a wide character in
an upper popup straddles the edge of a lower opacity popup, both
halves got different background colors. Since terminals cannot render
different left/right background colors for a wide character, detect
the lower popup with popup_is_over_opacity() and use the non-popup
side's underlying attr for both halves.
- Wrong blend color with cterm-only highlights under 'termguicolors':
when a popup highlight has ctermbg but no guibg, bg_rgb is set to
CTERMCOLOR (not INVALCOLOR). hl_blend_attr() used this value as a real
RGB color, producing gray instead of the intended color. Use
COLOR_INVALID() to detect both INVALCOLOR and CTERMCOLOR, and fall back
to converting the cterm color number to RGB.
closes: #19943
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: spell_read_aff() uses sprintf() into a fixed-size stack buffer
without bounds checking. store_aff_word() uses STRCAT() to
append attacker-controlled strings into newword[MAXWLEN] without
checking remaining space. Both are reachable via :mkspell with
crafted .aff/.dic files (xinyi234)
Solution: Replace sprintf() with vim_snprintf() in spell_read_aff().
Replace STRCAT() with STRNCAT() with explicit remaining-space
calculation in store_aff_word().
closes: #19944
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Some patterns in tar and zip plugin tests not strict enough.
Solution: Use assert_equal() for lines that should match exactly. Match
a literal dot properly (zeertzjq).
closes: #19946
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: test_indent.vim leaves swapfiles behind
Solution: Close open buffer using :bw! instead of :close!
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Cannot handle mouseclicks in the statusline
Solution: Add the %[FuncName] statusline item to define clickable
regions with a callback function. (Yasuhiro Matsumoto)
closes: #19841
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
The regex for status line highlighting was too broad, `jjComment` lines
containing e.g. the letter 'A' followed by a space anywhere in the line
were highlighted.
related: #19879
Signed-off-by: Joël Stemmer <jstemmer@google.com>
Signed-off-by: Gregory Anders <greg@gpanders.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: runtime(tar): but with dotted path
Solution: Do not strip everything after the first dot
(Aaron Burrow)
tar#Extract was getting the extensionless basename by
stripping away everything starting with the leftmost
dot. So if a directory had a dot or the file had an
'extra' dot then the code did the wrong thing. For
example, if it was given:
/tmp/foo.bar/baz.tar.gz
Then it would treat /tmp/foo as the extensionless
basename, but it actually should have grabbed:
/tmp/foo.bar/baz
This patch fixes the issue by instead looking at the
rightmost dot(s).
This bug was discovered by ChatGPT 5.4. I wrote the
patch and tested vim.
closes: #19930
Signed-off-by: Aaron Burrow <burrows@fastmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: patch 9.2.0325: runtime(tar): bug in zstd handling
Solution: use correct --zstd argument, separated from other arguments,
rework testing framework (Aaron Burrow).
The tar.vim plugin allows vim to read and manipulate zstd archives,
but it had a bug that caused extraction attempts to fail.
Specifically, if the archive has a .tar.zst or .tzst extension, then
the code was generating invalid extraction commands that looked like
this:
tar --zstdpxf foo.tar.zst foo
When they should be like this:
tar --zstd -pxf foo.tar.zst foo
This patch changes the flag manipulation logic so that --zstd isn't
glued to pxf.
The labor for this change was divided between ChatGPT 5.4 and me.
ChatGPT 5.4 identified the issue (from a code scan?), and I wrote
the patch and tested vim.
related: #19930
Signed-off-by: Aaron Burrow <burrows@fastmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: 0x9b byte not unescaped in <Cmd> mapping (BenYip).
Solution: Translate K_CSI to CSI like what is done in vgetc().
(zeertzjq).
fixes: #19936closes: #19937
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: test_popupwin fails (after v9.2.0319)
Solution: Regenerate the dump file (Yasuhiro Matsumoto).
The reference dump for Test_popupwin_opacity_wide_2 was not updated
when patch 9.2.0319 changed the blending behavior for double-width
characters at popup padding boundaries. The covered half of a
double-width character now correctly shows a space instead of the
full character.
related: #19881
closes: #19934
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: MS-Windows: No OpenType font support
Solution: Allow specifying OpenType font features directly in 'guifont'
(Yasuhiro Matsumoto).
Allow specifying OpenType font features directly in 'guifont' using
the ':f' option (e.g., :set guifont=Cascadia_Code:h14:fss19=1:fcalt=0).
Each ':fXXXX=N' sets a single OpenType feature tag with a parameter
value. Multiple features can be specified by repeating the ':f' option.
This only takes effect when 'renderoptions' is set to use DirectWrite
(type:directx). Default features (calt, liga, clig, rlig, kern) are
preserved unless explicitly overridden.
closes: #19857
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: popup: rendering issues with partially transparent popups.
Solution: Redraw the area under the old popup position on move or
resize. Apply the background blend only to the covered half of
a double-width character. (Yasuhiro Matsumoto)
closes: #19881
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: [security]: The netbeans defineAnnoType command passes typeName, fg and bg
unsanitized to coloncmd(), allowing a malicious server to inject
arbitrary Ex commands via '|'. Similarly, specialKeys does not
validate key tokens before building a map command.
Solution: Validate typeName, fg and bg against an allowlist of safe
characters before passing them to coloncmd()
Github Advisory:
https://github.com/vim/vim/security/advisories/GHSA-mr87-rhgv-7pw6
Supported by AI
Signed-off-by: Christian Brabandt <cb@256bit.org>
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: #19904
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: channel: can bind to all network interfaces in ch_listen()
(after v9.2.0153)
Solution: Restrict to a valid hostname, do not allow to bind on all
network interfaces (Zdenek Dohnal).
This will prevent unintentional binding the process to public network
interfaces, and opening Vim to communication from outside network if
firewall allows it.
related: #19231
closes: #19799
Signed-off-by: Zdenek Dohnal <zdohnal@redhat.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>