1111" 2025 Feb 06 by Vim Project: add support for lz4 (#16591)
1212" 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
1313" 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
14+ " 2025 Mar 02 by Vim Project: escape the filename before using :read
1415"
1516" Contains many ideas from Michael Toren's <tar.vim>
1617"
@@ -284,6 +285,8 @@ fun! tar#Read(fname,mode)
284285 set report = 10
285286 let tarfile = substitute (a: fname ,' tarfile:\(.\{-}\)::.*$' ,' \1' ,' ' )
286287 let fname = substitute (a: fname ,' tarfile:.\{-}::\(.*\)$' ,' \1' ,' ' )
288+ " be careful not to execute special crafted files
289+ let escape_file = fname- >fnameescape ()
287290
288291 " changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
289292 if ! exists (" *mkdir" )
@@ -361,13 +364,13 @@ fun! tar#Read(fname,mode)
361364
362365 if tarfile = ~# ' \.bz2$'
363366 exe " sil! r! bzip2 -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
364- exe " read " .fname
367+ exe " read " .escape_file
365368 elseif tarfile = ~# ' \.bz3$'
366369 exe " sil! r! bzip3 -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
367- exe " read " .fname
370+ exe " read " .escape_file
368371 elseif tarfile = ~# ' \.\(gz\)$'
369372 exe " sil! r! gzip -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
370- exe " read " .fname
373+ exe " read " .escape_file
371374 elseif tarfile = ~# ' \(\.tgz\|\.tbz\|\.txz\)'
372375 if has (" unix" ) && executable (" file" )
373376 let filekind= system (" file " .shellescape (tarfile,1 ))
@@ -376,40 +379,40 @@ fun! tar#Read(fname,mode)
376379 endif
377380 if filekind = ~ " bzip2"
378381 exe " sil! r! bzip2 -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
379- exe " read " .fname
382+ exe " read " .escape_file
380383 elseif filekind = ~ " bzip3"
381384 exe " sil! r! bzip3 -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
382- exe " read " .fname
385+ exe " read " .escape_file
383386 elseif filekind = ~ " XZ"
384387 exe " sil! r! xz -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
385- exe " read " .fname
388+ exe " read " .escape_file
386389 elseif filekind = ~ " Zstandard"
387390 exe " sil! r! zstd --decompress --stdout -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
388- exe " read " .fname
391+ exe " read " .escape_file
389392 else
390393 exe " sil! r! gzip -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
391- exe " read " .fname
394+ exe " read " .escape_file
392395 endif
393396
394397 elseif tarfile = ~# ' \.lrp$'
395398 exe " sil! r! cat -- " .shellescape (tarfile,1 )." | gzip -d -c - | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
396- exe " read " .fname
399+ exe " read " .escape_file
397400 elseif tarfile = ~# ' \.lzma$'
398401 exe " sil! r! lzma -d -c -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
399- exe " read " .fname
402+ exe " read " .escape_file
400403 elseif tarfile = ~# ' \.\(xz\|txz\)$'
401404 exe " sil! r! xz --decompress --stdout -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
402- exe " read " .fname
405+ exe " read " .escape_file
403406 elseif tarfile = ~# ' \.\(lz4\|tlz4\)$'
404407 exe " sil! r! lz4 --decompress --stdout -- " .shellescape (tarfile,1 )." | " .g: tar_cmd ." -" .g: tar_readoptions ." - " .tar_secure.shellescape (fname,1 ).decmp
405- exe " read " .fname
408+ exe " read " .escape_file
406409 else
407410 if tarfile = ~ ' ^\s*-'
408411 " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
409412 let tarfile = substitute (tarfile, ' -' , ' ./-' , ' ' )
410413 endif
411414 exe " silent r! " .g: tar_cmd ." -" .g: tar_readoptions .shellescape (tarfile,1 )." " .tar_secure.shellescape (fname,1 ).decmp
412- exe " read " .fname
415+ exe " read " .escape_file
413416 endif
414417
415418 redraw !
0 commit comments