From 056304ef5bb121e43482783f2a3388d37330050c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 6 Apr 2026 21:43:28 +0800 Subject: [PATCH] vim-patch:9.2.0306: runtime(tar): some issues with lz4 support (#38826) 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: vim/vim#19925 https://github.com/vim/vim/commit/78954f86c2027c766d9e2b5f7904b5fb4041d250 Co-authored-by: Aaron Burrow --- runtime/autoload/tar.vim | 11 ++++-- test/old/testdir/test_plugin_tar.vim | 54 ++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim index 774623c107..b2187a7ebc 100644 --- a/runtime/autoload/tar.vim +++ b/runtime/autoload/tar.vim @@ -19,6 +19,7 @@ " 2025 Jul 13 by Vim Project: warn with path traversal attacks " 2026 Feb 06 by Vim Project: consider 'nowrapscan' (#19333) " 2026 Feb 07 by Vim Project: make the path traversal detection more robust (#19341) +" 2026 Apr 06 by Vim Project: fix bugs with lz4 support (#19925) " " Contains many ideas from Michael Toren's " @@ -703,7 +704,9 @@ fun! tar#Extract() endif elseif filereadable(tarbase.".tlz4") - let extractcmd= substitute(extractcmd,"-","-I lz4","") + if has("linux") + let extractcmd= substitute(extractcmd,"-","-I lz4 -","") + endif call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname)) if v:shell_error != 0 call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: failed!") @@ -712,8 +715,10 @@ fun! tar#Extract() endif elseif filereadable(tarbase.".tar.lz4") - let extractcmd= substitute(extractcmd,"-","-I lz4","") - call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname)) + if has("linux") + let extractcmd= substitute(extractcmd,"-","-I lz4 -","") + endif + call system(extractcmd." ".shellescape(tarbase).".tar.lz4 ".shellescape(fname)) if v:shell_error != 0 call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 {fname}: failed!") else diff --git a/test/old/testdir/test_plugin_tar.vim b/test/old/testdir/test_plugin_tar.vim index 3bc3db6053..719487bda4 100644 --- a/test/old/testdir/test_plugin_tar.vim +++ b/test/old/testdir/test_plugin_tar.vim @@ -150,3 +150,57 @@ func Test_tar_path_traversal_with_nowrapscan() bw! endfunc + +func Test_tar_lz4_extract() + CheckExecutable lz4 + + call delete('X.txt') + call delete('Xarchive.tar') + call delete('Xarchive.tar.lz4') + call writefile(['hello'], 'X.txt') + call system('tar -cf Xarchive.tar X.txt') + call assert_equal(0, v:shell_error) + + call system('lz4 -z Xarchive.tar Xarchive.tar.lz4') + call assert_equal(0, v:shell_error) + + call delete('X.txt') + call delete('Xarchive.tar') + defer delete('Xarchive.tar.lz4') + + e Xarchive.tar.lz4 + call assert_match('X.txt', getline(5)) + :5 + normal x + call assert_true(filereadable('X.txt')) + call assert_equal(['hello'], readfile('X.txt')) + call delete('X.txt') + bw! +endfunc + +func Test_tlz4_extract() + CheckExecutable lz4 + + call delete('X.txt') + call delete('Xarchive.tar') + call delete('Xarchive.tlz4') + call writefile(['goodbye'], 'X.txt') + call system('tar -cf Xarchive.tar X.txt') + call assert_equal(0, v:shell_error) + + call system('lz4 -z Xarchive.tar Xarchive.tlz4') + call assert_equal(0, v:shell_error) + + call delete('X.txt') + call delete('Xarchive.tar') + defer delete('Xarchive.tlz4') + + e Xarchive.tlz4 + call assert_match('X.txt', getline(5)) + :5 + normal x + call assert_true(filereadable('X.txt')) + call assert_equal(['goodbye'], readfile('X.txt')) + call delete('X.txt') + bw! +endfunc