patch 9.2.0326: runtime(tar): but with dotted path

Commit: 
https://github.com/vim/vim/commit/4a1bcc67b4b6fc2dfe564ab4faca490f8afac857
Author: Aaron Burrow <[email protected]>
Date:   Thu Apr 9 19:11:16 2026 +0000

    patch 9.2.0326: runtime(tar): but with dotted path
    
    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 <[email protected]>
    Signed-off-by: Christian Brabandt <[email protected]>

diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim
index b068bd181..722a0ab68 100644
--- a/runtime/autoload/tar.vim
+++ b/runtime/autoload/tar.vim
@@ -22,6 +22,7 @@
 "   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)
 "   2026 Apr 09 by Vim Project: fix bugs with zstd support (#19930)
+"   2026 Apr 09 by Vim Project: fix bug with dotted filename (#19930)
 "
 "      Contains many ideas from Michael Toren's <tar.vim>
 "
@@ -612,117 +613,120 @@ fun! tar#Extract()
    return
   endif
 
+  let extractcmd= s:WinPath(g:tar_extractcmd)
   let tarball = expand("%")
-  let tarbase = substitute(tarball,'\..*$','','')
+  if !filereadable(tarball)
+   let &report= repkeep
+   return
+  endif
 
-  let extractcmd= s:WinPath(g:tar_extractcmd)
-  if filereadable(tarbase.".tar")
-   call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
+  if tarball =~# "\.tar$"
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ". fname
    endif
 
-  elseif filereadable(tarbase.".tgz")
+  elseif tarball =~# "\.tgz$"
    let extractcmd= substitute(extractcmd,"-","-z","")
-   call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tgz {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.gz")
+  elseif tarball =~# "\.tar\.gz$"
    let extractcmd= substitute(extractcmd,"-","-z","")
-   call system(extractcmd." ".shellescape(tarbase).".tar.gz 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.gz 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tbz")
+  elseif tarball =~# "\.tbz$"
    let extractcmd= substitute(extractcmd,"-","-j","")
-   call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tbz {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.bz2")
+  elseif tarball =~# "\.tar\.bz2$"
    let extractcmd= substitute(extractcmd,"-","-j","")
-   call system(extractcmd." ".shellescape(tarbase).".tar.bz2 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz2 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.bz3")
+  elseif tarball =~# "\.tar\.bz3$"
    let extractcmd= substitute(extractcmd,"-","-j","")
-   call system(extractcmd." ".shellescape(tarbase).".tar.bz3 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.bz3 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".txz")
+  elseif tarball =~# "\.txz$"
    let extractcmd= substitute(extractcmd,"-","-J","")
-   call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.txz {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.xz")
+  elseif tarball =~# "\.tar\.xz$"
    let extractcmd= substitute(extractcmd,"-","-J","")
-   call system(extractcmd." ".shellescape(tarbase).".tar.xz 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.xz 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tzst")
+  elseif tarball =~# "\.tzst$"
    let extractcmd= substitute(extractcmd,"-","--zstd -","")
-   call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tzst {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.zst")
+  elseif tarball =~# "\.tar\.zst$"
    let extractcmd= substitute(extractcmd,"-","--zstd -","")
-   call system(extractcmd." ".shellescape(tarbase).".tar.zst 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.zst 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tlz4")
+  elseif tarball =~# "\.tlz4$"
    if has("linux")
     let extractcmd= substitute(extractcmd,"-","-I lz4 -","")
    endif
-   call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tlz4 {fname}: 
failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
 
-  elseif filereadable(tarbase.".tar.lz4")
+  elseif tarball =~# "\.tar\.lz4$"
    if has("linux")
     let extractcmd= substitute(extractcmd,"-","-I lz4 -","")
    endif
-   call system(extractcmd." ".shellescape(tarbase).".tar.lz4 
".shellescape(fname))
+   call system(extractcmd." ".shellescape(tarball)." ".shellescape(fname))
    if v:shell_error != 0
-    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarbase}.tar.lz4 
{fname}: failed!")
+    call s:Msg('tar#Extract', 'error', $"{extractcmd} {tarball} {fname}: 
failed!")
    else
     echo "***note*** successfully extracted ".fname
    endif
diff --git a/src/testdir/test_plugin_tar.vim b/src/testdir/test_plugin_tar.vim
index 28cf709f8..bde79052d 100644
--- a/src/testdir/test_plugin_tar.vim
+++ b/src/testdir/test_plugin_tar.vim
@@ -263,3 +263,53 @@ def g:Test_extraction()
     bw!
   endfor
 enddef
+
+def g:Test_extract_with_dotted_dir()
+  delete('X.txt')
+  writefile(['when they kiss they spit white noise'], 'X.txt')
+
+  var dirname = tempname()
+  mkdir(dirname, 'R')
+  dirname = dirname .. '/foo.bar'
+  mkdir(dirname, 'R')
+  var tarpath = dirname .. '/Xarchive.tar.gz'
+  system('tar -czf ' .. tarpath .. ' X.txt')
+  assert_true(filereadable(tarpath))
+  assert_equal(0, v:shell_error)
+
+  delete('X.txt')
+  defer delete(tarpath)
+
+  execute 'e ' .. tarpath
+  assert_match('X.txt', getline(5))
+  :5
+  normal x
+  assert_true(filereadable('X.txt'))
+  assert_equal(['when they kiss they spit white noise'], readfile('X.txt'))
+  delete('X.txt')
+  bw!
+enddef
+
+def g:Test_extract_with_dotted_filename()
+  delete('X.txt')
+  writefile(['holiday inn'], 'X.txt')
+
+  var dirname = tempname()
+  mkdir(dirname, 'R')
+  var tarpath = dirname .. '/Xarchive.foo.tar.gz'
+  system('tar -czf ' .. tarpath .. ' X.txt')
+  assert_true(filereadable(tarpath))
+  assert_equal(0, v:shell_error)
+
+  delete('X.txt')
+  defer delete(tarpath)
+
+  execute 'e ' .. tarpath
+  assert_match('X.txt', getline(5))
+  :5
+  normal x
+  assert_true(filereadable('X.txt'))
+  assert_equal(['holiday inn'], readfile('X.txt'))
+  delete('X.txt')
+  bw!
+enddef
diff --git a/src/version.c b/src/version.c
index 5fc6428c2..70bca3689 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    326,
 /**/
     325,
 /**/

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion visit 
https://groups.google.com/d/msgid/vim_dev/E1wAv4n-00C7BH-HD%40256bit.org.

Raspunde prin e-mail lui