Problem: runtime(tar): some issues with lz4 support
Solution: Fix bugs (see below) (Aaron Burrow)
The tar plugin allows users to extract files from tar archives that are
compressed with lz4. But, tar#Extract() builds malformed extraction commands
for lz4-compressed tar archives. This commit fixes three issues in that code.
The first affects archives with a .tlz4 extension and the other two affect
archives with .tar.lz4 extension (but one of these is symmetric to the issue
that .tlz4 archives had).
(1) When trying to extract .tlz4 archives the command created by
tar#Extract looked like this:
tar -I lz4pxf foo.tlz4 foo
This isn't right. It should be something like this:
tar -I lz4 -pxf foo.tlz4 foo
This was happening because tar.plugin is just substituting on the
first - in "tar -pxf". This works fine if we just add a simple flag for
extraction (eg, z for .tgz), but for lz4 we need to add "-I lz4".
I don't believe that there is an obvious good way to fix this without
reworking the way the command is generated. Probably we should collect
the command and flags separately and the flags should be stored in a
set. Then put everything together into a string just before issuing it
as an extraction command. Unfortunately, this might break things for users
because they have access to tar_extractcmd.
This patch just makes the substitution a little bit more clever so that it
does the right thing when substituting on a string like "tar -pxf".
(2) .tar.lz4 extractions had the same issue, which my patch fixes in
the same way.
(3) .tar.lz4 extractions had another issue. There was a space missing
in the command generated by tar#Extract. This meant that commands
looked like this (notice the lack of space between the archive and output
file names):
tar -I lz4pxf foo.tar.lz4foo
This patch just puts a space where it should be.
Finally, I should note that ChatGPT 5.4 initially identified this issue
in the code and generated the test cases. I reviewed the test cases,
wrote the patch, and actually ran vim against the tests (both with and
without the patch).
closes: #19925
Signed-off-by: Aaron Burrow <burrows@fastmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: When the terminal is very large, test for 9.2.0285 doesn't
trigger an ASAN error without the fix.
Solution: Use a window with fixed height (zeertzjq)
closes: #19924
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: zip plugin tests may match messages from previous test cases
when checking for warning message.
Solution: Clear messages at the start of these tests (zeertzjq).
closes: #19926
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: runtime(netrw): RFC2396 decoding double escaping spaces
(lilydjwg, after 3e60f03d94)
Solution: Remove escape() call, since we are using fnameescape() anyhow
fixes: #19913
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Vim9: void function return value inconsistent between
script and :def
Solution: Make void built-in functions like bufload() return void
consistently (Hirohito Higashi)
In Vim9 script, calling a void built-in function (e.g. bufload()) at the
script level did not set rettv to VAR_VOID, making it appear to return
0. Inside :def it correctly returned VAR_VOID and raised E1031. Set
rettv to VAR_VOID after calling a ret_void built-in function in Vim9
script so the behavior is consistent.
Also fix the documentation for bufload() and ch_logfile() to correctly
state that the return type is void.
closes: #19919
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: The vimball plugin needs some love
(syndicate)
Solution: Clean-up, refactor and update the plugin,
in particular, catch path traversal attacks
This change does the following
- Clean up Indentation and remove calls to Decho
- Increase minimum Vim version to 7.4 for mkdir()
- Use mkdir() consistently
- Update Metadata Header
- Remove check for fnameescape()
- Catch path traversal attacks
- Add vimball basic tests
- Remove mentioning of g:vimball_mkdir in documentation
closes: #19921
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: runtime(zip): may write using absolute paths
(syndicate)
Solution: Detect this case and abort on Unix, warn in the documentation
about possible issues
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: 'showcmd' shows wrong Visual block size with 'linebreak' after
end char (after 7.4.467).
Solution: Exclude 'linebreak' from end position. Also fix confusing test
function names.
closes: #19908
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: :packadd may lead to heap-buffer-overflow when all entries in
'runtimepath' have the same length (after 9.2.0291).
Solution: Check for comma after current entry properly (zeertzjq).
related: #19854
closes: #19911
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: E340 internal error when using method call on void value
(Peter Kenny)
Solution: Check for void value (Hirohito Higashi)
Using a method call on a void return value (e.g. "echo F()->empty()"
where F() returns void) caused an internal error E340. Now it properly
reports E1031 or E1186 depending on the context.
Changes:
- eval.c: check for void value before -> method call at runtime
- vim9expr.c: check for void type before -> method call at compile time
- vim9execute.c: check for void value in builtin function arguments and in
ISN_STORE
fixes: #19897closes: #19912
Signed-off-by: Hirohito Higashi <h.east.727@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: 'linebreak' may lead to wrong Visual block highlighting when
end char occupies multiple cells (after 7.4.467).
Solution: Exclude 'linebreak' from the ending column instead of setting
'virtualedit' temporarily (zeertzjq).
fixes: #19898closes: #19900
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: filetype: not all ObjectScript routines are recognized
Solution: Also detect "%RO" and "iris" patterns inside *.rtn files
(Hannah Kimura)
closes: #19873
Signed-off-by: Hannah Kimura <hannah.kimura@intersystems.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: :syn sync grouphere may go beyond end of line.
Solution: Start searching for the end of region at the end of match
instead of a possibly invalid position (zeertzjq).
closes: #19896
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: When a tabpanel expression returns a different number of lines on
successive evaluations, the computed row offset can become negative,
causing screen_fill() to receive an invalid start_row and crash
(after v9.1.1391).
Solution: Clamp the row argument in screen_fill_tailing_area() to zero,
add a safety check in screen_fill() for negative start_row
(Michał Majchrowicz)
Supported by AI
Co-authored-by: Michał Majchrowicz <mmajchrowicz@afine.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: Test_viminfo_len_overflow() fails
Solution: Catch E342 (Yasuhiro Matsumoto).
Test_viminfo_len_overflow tries to allocate ~4GB, which may throw E342
(out of memory) depending on the platform's memory allocation behavior.
This is an acceptable outcome since the test's purpose is to verify
that Vim does not crash on a crafted viminfo entry.
closes: #19891
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: Test_netrw_FileUrlEdit.. fails on Windows
(after 3e60f03d94)
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: #19890
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: libvterm CSI parser does not bounds-check argi against
CSI_ARGS_MAX, allowing excess ';'-separated arguments to
write past the end of the args array (sentinel404).
Solution: Drop excess arguments.
Supported by AI
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Reading a crafted viminfo file can cause a heap buffer
overflow because the length value from getdigits() is cast to
int, truncating large size_t values
Solution: Remove the (int) cast when calling alloc() (sentinel404)
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tabpanel: undefined behaviour with large tabpanelop columns
(Michał Majchrowicz)
Solution: Error out for too large column values
Co-authored-by: Michał Majchrowicz <mmajchrowicz@afine.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: test: trailing spaces used in tests
Solution: Rewrite tests to avoid trailing spaces (Paul Ollis).
Some tests currently rely on trailing whitespace at the end of lines,
escaped with '\'. I have demonstrated in another PR, such spaces can be
inadvertently removed and this is difficult to spot.
Note: there are more trailing spaces in a few more test files, see
testdir/test_codestyle.vim. Those are not yet removed.
closes: #19838
Signed-off-by: Paul Ollis <paul@cleversheep.org>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: unnecessary restrictions for defining dictionary function
names
Solution: Allow defining dict function with bracket key that is not a
valid identifier (thinca)
In Vim script, "function obj.func()" and "function obj['func']()" both
define a dictionary function. However, the bracket form required the
key to match function naming rules (eval_isnamec), so
"function obj['foo-bar']()" failed with E475.
Assigning and calling already work: "let obj['foo-bar'] = obj.func"
and "call obj['foo-bar']()" are valid. Only the definition was
incorrectly restricted.
Skip the identifier check when the name comes from fd_newkey (i.e. the
key was given in bracket notation). Dictionary keys may be any string.
Supported by AI
closes: #19833
Signed-off-by: thinca <thinca@gmail.com>
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Cannot disable kitty keyboard protocol in vim :terminal
Solution: Handle "CSI <u" sequence in libvterm (Julio B).
related: v9.0.0930
closes: #19837
Signed-off-by: Julio B <julio.bacel@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: hlset() cannot handle attributes with spaces
Solution: Handle attributes with spaces by quoting those
(Yasuhiro Matsumoto).
hlset(hlget('Normal')) fails with E416 when a highlight attribute value
contains spaces (e.g. font name "Monospace 10"). hlg_add_or_update()
builds a string like "font=Monospace 10" and passes it to do_highlight(),
whose parser splits on whitespace and treats "10" as a separate key
without "=".
Fix by quoting values with single quotes (e.g. font='Monospace 10')
when the value contains spaces and the attribute is a key=value pair.
do_highlight() already supports single-quoted values.
closes: #19843
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: invalid lnum when pasting text copied blockwise
(KillTheMule)
Solution: Subtract nr_lines from curwin->w_cursor.lnum when calling
changed_lines() in do_put() (Pierluigi Lenoci)
When doing a blockwise paste beyond the end of the buffer, new lines are
appended and nr_lines is incremented accordingly. However, the
changed_lines() call used curwin->w_cursor.lnum as the "lnume" argument
(the first line below the changed lines BEFORE the change), which is
incorrect because the cursor has already been moved past the newly
appended lines.
Fix by subtracting nr_lines from curwin->w_cursor.lnum, so that lnume
correctly reflects the state before the change, as documented in
changed_lines().
Add a listener test to verify the correct values are reported.
Port of neovim/neovim#12733.
fixes: #6660closes: #19844
Signed-off-by: Pierluigi Lenoci <pierluigi.lenoci@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: When a popup window overlapping a status line is closed or
hidden, the status line is not redrawn, leaving ghost
artifacts from the popup.
Solution: popup_free() and popup_hide() call
redraw_all_later(UPD_NOT_VALID) which marks window contents
for redraw but does not set w_redr_status. The diff-based path
in may_update_popup_mask() that normally sets w_redr_status
is skipped when redrawing_all_win is TRUE. Add status_redraw_all
calls to ensure status lines are properly redrawn
(Yasuhiro Matsumoto).
closes: #19830
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: The visual selection size is not displayed in the showcmd area
when entering visual mode from a script or mapping, because
char_avail() incorrectly reports input as pending. This causes
test failure on CI with the ASAN CI runner.
Solution: Replace char_avail() with explicit checks for an empty stuff
buffer, empty typeahead buffer, and not running a script
(zeertzjq).
related: #19801
closes: #19824
Co-authored-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: tests: Test_popup_opacity_vsplit() fails in a wide terminal
(after v9.2.0230)
Solution: Reduce terminal window size to 60, force termguicolors to make
the opacity visible; enable termguicolors so that the opacity
is visually apparent in the screen dump.
related: #19824
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: w_locked can be bypassed when recursively set if not restored
to its prior value.
Solution: Rather than save/restore everywhere, just make it a count,
like other locks (Sean Dewar)
Requires the previous commit, otherwise b_nwindows will be wrong in
tests, which causes a bunch of weird failures.
closes: #19728
Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: close_buffer() callers incorrectly handle b_nwindows,
especially after nasty autocmds, allowing it to go
out-of-sync. May lead to buffers that can't be unloaded, or
buffers that are prematurely freed whilst displayed.
Solution: Modify close_buffer() and review its callers; let them
decrement b_nwindows if it didn't unload the buffer. Remove
some now unneeded workarounds like 8.2.2354, 9.1.0143,
9.1.0764, which didn't always work (Sean Dewar)
close_buffer() now doesn't decrement b_nwindows when not unloading buf, or when
buf isn't w_buffer after autocmds (they would've already decremented it).
Callers are now expected to decrement b_nwindows if w_buffer is not NULL after
close_buffer(), and when still intending to switch buffers or close win, for two
reasons:
- close_buffer() autocmds may have switched buffers. The new w_buffer's
b_nwindows would also need decrementing.
- After close_buffer(), callers may opt to not switch w_buffer or close win.
b_nwindows would need to be incremented again. (unless w_buffer is NULL from
being unloaded; callers are already forced to find a new buffer then)
These were the main causes of b_nwindows bugs, as these cases could not be
reliably detected, and went largely unhandled.
NOTE: if close_buffer() autocmds switch buffers, close_buffer() is not called
for that new buffer before decrementing b_nwindows. This may skip side-effects
like from 'bufhidden', but I think it's mostly harmless, and was already
happening in other places.
Let's see how this goes... Other details: (I have lots to say!)
It's OK to pass a win to close_buffer() that isn't showing buf (used by
set_curbuf()). In that case, we skip some side-effects and don't decrement
b_nwindows, but may still unload buf if hidden.
buf_freeall() now returns whether it freed anything. Removes some repeated
checks in close_buffer().
Preserve close_buffer()'s behaviour when called by win_free_popup() after its
popup was already removed from the window list. This made win_valid_any_tab()
return FALSE, so we skip things that originally checked it in that case.
Add "set_context" to close_buffer() to preserve do_ecmd()'s behaviour of only
setting b_last_cursor and/or calling buflist_setfpos() when not splitting
(see 7.2.041: https://groups.google.com/g/vim_dev/c/ZGgNvaylNzI/m/WHxjhnuxqB0J)
Without this, Test_marks_cmd() fails from its ' mark differing. Don't use
oldwin though; it's not always the window with the closed buf, especially
after BufLeave autocmds in do_ecmd(). Also, only set context if win is really
displaying buf.
Don't bail in do_ecmd() if buf was deleted but curwin->w_buffer is NULL; that
leaves curwin open to a NULL buffer! Use lastbuf instead, like set_curbuf().
I don't think it's possible for buf to be deleted by close_buffer() anyway, as
b_locked was set (which I can't see a way to bypass, unlike b_locked_split).
Maybe such checks can be removed, but I'd rather not risk that here.
Don't set curwin to previouswin in set_curbuf(); shouldn't be needed, otherwise
may lead to curbuf != curwin->w_buffer if autocmds switch to a window showing
buf, as that skips enter_buffer()? Was introduced back in 7.3.557 to avoid
cases where autocmds switch windows, possibly leaving previouswin with a NULL
buffer. Since 7.4.2312 and 7.4.2328, close_buffer() and buf_freeall() already
handles this. I've added an assert() as a sanity check anyway.
In free_all_mem(), set b_nwindows to 0 before close_buffer() so buffers can be
wiped if still in a window before win_free_all(). Needed as close_buffer() now
skips unloading buffers that aren't hidden if win is NULL. If it's possible for
free_all_mem()'s :tabonly! and :only! to not close all windows before freeing,
then this issue was also previously possible if b_nwindows > 1.
related: #19728
Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: if close_buffer() in set_curbuf() unloads curbuf, NULL pointer
accesses may occur from enter_buffer() calling
end_visual_mode(), as curbuf is already abandoned and possibly
unloaded. Also, selection registers may not contain the
selection with clipboard+=autoselect(plus).
Solution: Move close_buffer()'s end_visual_mode() call to buf_freeall(), after
any autocmds that may restart it, but just before freeing anything
(Sean Dewar)
related: #19728
Signed-off-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: system() and systemlist() only accept a String, requiring
manual shell escaping for arguments with special characters.
Solution: Accept a List as the first argument and execute the command
bypassing the shell (Yasuhiro Matsumoto).
fixes: #19789closes: #19791
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: json_decode() accepted keywords case-insensitively, violating
RFC 7159. Both json_decode() and js_decode() silently accepted
lone surrogates, which are invalid Unicode.
Solution: Only allow lowercase keyword in json_decode(), reject lone
surrogates, improve encoding performance in write_string() and
blob byte serialization.
1. Fix surrogate pair range check (0xDFFF -> 0xDBFF) so only high
surrogates trigger pair decoding. Reject lone surrogates that do
not form a valid pair instead of producing invalid UTF-8.
2. Use case-sensitive matching for JSON keywords (true, false, null,
NaN, Infinity) in json_decode() per RFC 7159. js_decode() retains
case-insensitive behavior.
3. Replace double ga_append() calls for escape sequences with single
GA_CONCAT_LITERAL() calls, halving function call and buffer growth
check overhead.
4. Replace vim_snprintf_safelen() for blob byte encoding (0-255) with
direct digit conversion.
closes: #19807
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: popup: popups may not wrap as expected
(Enrico Maria De Angelis, after v9.1.0949)
Solution: don't shift popupwin left when 'wrap' is on and maxwidth is
set (Hirohito Higashi)
When a non-fixed popup with 'wrap' enabled and an explicit maxwidth was
placed near the right edge of the screen, the shift-left logic increased
maxwidth beyond the user-specified value, preventing text from wrapping.
Instead cap the shift amount so that maxwidth does not exceed w_maxwidth
when wrapping is enabled, letting text wrap as expected.
fixes: #19767closes: #19809
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: xxd: color output detection is broken
(Juergen Weigert)
Solution: Fix the issues (Hirohito Higashi)
- Disable auto color when output goes to a file (two-argument form)
- Check TERM variable: disable color when unset, empty or "dumb"
- Add color_forced flag to preserve -R always behavior
- Add tests for the new behavior
fixes: #19790closes: #19813
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: tests: Test_visual_block_hl_with_autosel() is flaky on ASAN CI
(after v9.2.0221)
Solution: Add a TermWait() call
related: #19784
Signed-off-by: Christian Brabandt <cb@256bit.org>
- Highlight keywords "function" and "namespace" with
the "Keyword" group ("shFunctionKey").
- Highlight function body delimiters "{" and "}" with the
"Delimiter" group ("shFunctionExprRegion").
- Highlight function body delimiters "(" and ")" with the
"Operator" group ("shFunctionSubShRegion").
- Also, follow one style in folding all supported variants
of function bodies for grouping commands too by enclosing
a delimited function body, e.g. "{" and "}", in a fold and
leaving its function header, e.g. "function f()", out of
it when the header is written on a separate line.
To restore previous colouring, add to "after/syntax/sh.vim":
------------------------------------------------------------
hi link shFunctionKey Function
hi link shFunctionExprRegion Function
hi link shFunctionSubShRegion Function
------------------------------------------------------------
fixes: https://github.com/vim/vim/pull/19638#issuecomment-4052635546closes: #19638
Signed-off-by: Aliaksei Budavei <0x000c70@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Changing the 'signcolumn' may cause flicker, because it uses
the P_RCLR flag for redrawing (Yggdroot)
Solution: Change 'signcolumn' to use P_RWIN instead of P_RCLR, matching
the behavior of 'number' and 'foldcolumn'
(Yasuhiro Matsumoto).
fixes: #19663closes: #19713
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: stack-overflow with deeply nested data in json_encode/decode()
(ZyX-I)
Solution: Add depth limit check using 'maxfuncdepth' to
json_encode_item() and json_decode_item() to avoid crash when
encoding/decoding deeply nested lists, dicts, or JSON arrays/objects,
fix typo in error name, add tests (Yasuhiro Matsumoto).
fixes: #588closes: #19808
Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>