diff --git a/Filelist b/Filelist index c1487af574..f2797efe2f 100644 --- a/Filelist +++ b/Filelist @@ -223,6 +223,7 @@ SRC_ALL = \ src/testdir/samples/*.html \ src/testdir/samples/*.txt \ src/testdir/samples/*.vim \ + src/testdir/samples/poc.zip \ src/testdir/samples/test000 \ src/testdir/samples/test.zip \ src/testdir/samples/test_undo.txt.undo \ diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim index 4a53fc5f28..dae4ddeb99 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, @@ -343,6 +344,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 '-d/tmp' to extract the whole archive + let target = target->substitute('^-', '[&]', '') if &shell =~ 'cmd' && has("win32") let target = target \ ->substitute('[?*]', '[&]', 'g') diff --git a/src/testdir/samples/poc.zip b/src/testdir/samples/poc.zip new file mode 100644 index 0000000000..8b2b44b96a Binary files /dev/null and b/src/testdir/samples/poc.zip differ diff --git a/src/testdir/test_plugin_zip.vim b/src/testdir/test_plugin_zip.vim index e831f26345..2050b4ce10 100644 --- a/src/testdir/test_plugin_zip.vim +++ b/src/testdir/test_plugin_zip.vim @@ -235,3 +235,26 @@ def Test_zip_glob_fname() bw enddef + +def Test_zip_fname_leading_hyphen() + CheckNotMSWindows + + ### copy sample zip file + if !filecopy("samples/poc.zip", "X.zip") + 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 + var fname = '-d/tmp' + search('\V' .. fname) + normal x + assert_true(filereadable('-d/tmp')) + assert_false(filereadable('/tmp/pwned')) + bw +enddef diff --git a/src/version.c b/src/version.c index 65332f5e9a..265081a835 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1198, /**/ 1197, /**/