aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/autoload/zip.vim6
-rw-r--r--test/old/testdir/samples/poc.zipbin0 -> 306 bytes
-rw-r--r--test/old/testdir/test_plugin_zip.vim23
3 files changed, 29 insertions, 0 deletions
diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim
index a8ea6a3fab..305b823e7b 100644
--- a/runtime/autoload/zip.vim
+++ b/runtime/autoload/zip.vim
@@ -14,6 +14,7 @@
" 2024 Aug 05 by Vim Project: clean-up and make it work with shellslash on Windows
" 2024 Aug 18 by Vim Project: correctly handle special globbing chars
" 2024 Aug 21 by Vim Project: simplify condition to detect MS-Windows
+" 2025 Mar 11 by Vim Project: handle filenames with leading '-' correctly
" License: Vim License (see vim's :help license)
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
@@ -342,6 +343,11 @@ fun! zip#Extract()
return
endif
let target = fname->substitute('\[', '[[]', 'g')
+ " unzip 6.0 does not support -- to denote end-of-arguments
+ " unzip 6.1 (2010) apparently supports, it, but hasn't been released
+ " so the workaround is to use glob '[-]' so that it won't be considered an argument
+ " else, it would be possible to use 'unzip -o <file.zip> '-d/tmp' to extract the whole archive
+ let target = target->substitute('^-', '[&]', '')
if &shell =~ 'cmd' && has("win32")
let target = target
\ ->substitute('[?*]', '[&]', 'g')
diff --git a/test/old/testdir/samples/poc.zip b/test/old/testdir/samples/poc.zip
new file mode 100644
index 0000000000..8b2b44b96a
--- /dev/null
+++ b/test/old/testdir/samples/poc.zip
Binary files differ
diff --git a/test/old/testdir/test_plugin_zip.vim b/test/old/testdir/test_plugin_zip.vim
index a817d8371e..ba0a6778bc 100644
--- a/test/old/testdir/test_plugin_zip.vim
+++ b/test/old/testdir/test_plugin_zip.vim
@@ -235,3 +235,26 @@ func Test_zip_glob_fname()
bw
endfunc
+
+func Test_zip_fname_leading_hyphen()
+ CheckNotMSWindows
+
+ "## copy sample zip file
+ if !filecopy("samples/poc.zip", "X.zip")
+ call assert_report("Can't copy samples/poc.zip")
+ return
+ endif
+ defer delete("X.zip")
+ defer delete('-d', 'rf')
+ defer delete('/tmp/pwned', 'rf')
+
+ e X.zip
+
+ :1
+ let fname = '-d/tmp'
+ call search('\V' .. fname)
+ normal x
+ call assert_true(filereadable('-d/tmp'))
+ call assert_false(filereadable('/tmp/pwned'))
+ bw
+endfunc