patch 9.2.1045: runtime(netrw): raises E46 when changing directory fails
Commit:
https://github.com/vim/vim/commit/2f72e4c72f98a5760e2c783ab07f9865e91217a8
Author: Qiming zhao <
che...@gmail.com>
Date: Mon Sep 7 21:18:44 2026 +0000
patch 9.2.1045: runtime(netrw): raises E46 when changing directory fails
Problem: Netrw raises E46 when changing directory fails.
Solution: Remove unused assignments to the read-only directory argument
and cover both error-handling branches with a regression test
(Qiming zhao).
When :lcd fails with E472, s:NetrwLcd() assigns to a:newdir instead of
returning -1. The fallback assignment also refers to dirname, which is
undefined on this path. Neither assignment can update the caller's
directory variable. Keep the existing option restoration and failure
return while removing the invalid assignments.
Supported by AI.
closes: #21226
Signed-off-by: Qiming zhao <
che...@gmail.com>
Signed-off-by: Christian Brabandt <
c...@256bit.org>
diff --git a/runtime/pack/dist/opt/netrw/autoload/netrw.vim b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
index d8a1c8aad..284b3daf6 100644
--- a/runtime/pack/dist/opt/netrw/autoload/netrw.vim
+++ b/runtime/pack/dist/opt/netrw/autoload/netrw.vim
@@ -1,7 +1,7 @@
" Creator: Charles E Campbell
" Previous Maintainer: Luca Saccarola <
github...@aleeas.com>
" Maintainer: This runtime file is looking for a new maintainer.
-" Last Change: 2026 Aug 21
+" Last Change: 2026 Sep 07
" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
@@ -9300,12 +9300,9 @@ function s:NetrwLcd(newdir)
if err472
call netrw#msg#Notify('ERROR', printf('unable to change directory to <%s> (permissions?)', a:newdir))
- if exists("w:netrw_prvdir")
- let a:newdir= w:netrw_prvdir
- else
+ if !exists("w:netrw_prvdir")
call s:NetrwOptionsRestore("w:")
exe "setl ".g:netrw_bufsettings
- let a:newdir= dirname
endif
return -1
endif
diff --git a/src/testdir/test_plugin_netrw.vim b/src/testdir/test_plugin_netrw.vim
index 22d317156..76a1eee43 100644
--- a/src/testdir/test_plugin_netrw.vim
+++ b/src/testdir/test_plugin_netrw.vim
@@ -133,6 +133,10 @@ function Test_NetrwFile(fname) abort
return s:NetrwFile(a:fname)
endfunction
+function Test_NetrwLcd(newdir) abort
+ return s:NetrwLcd(a:newdir)
+endfunction
+
" Test hostname validation
function Test_NetrwValidateHostname(hostname) abort
return s:NetrwValidateHostname(a:hostname)
@@ -313,6 +317,44 @@ func s:combine
endfunction
+func Test_netrw_lcd_failure()
+ CheckUnix
+ CheckNotRoot
+ let dirname = getcwd() .. '/Xnetrw_noaccess'
+ call mkdir(dirname)
+ call assert_true(setfperm(dirname, 'r--------'))
+ try
+ for prevdir in [1, 0]
+ new
+ try
+ let cwd = getcwd()
+ if prevdir
+ let w:netrw_prvdir = cwd
+ else
+ unlet! w:netrw_prvdir
+ endif
+ setlocal modifiable noreadonly number
+ let msg = execute('call assert_equal(-1, Test_NetrwLcd(dirname))')
+ call assert_match('unable to change directory to <' .. dirname .. '>', msg)
+ call assert_equal(cwd, getcwd())
+ if prevdir
+ call assert_equal(cwd, w:netrw_prvdir)
+ call assert_true(&l:modifiable)
+ else
+ call assert_false(&l:modifiable)
+ call assert_true(&l:readonly)
+ call assert_false(&l:number)
+ endif
+ finally
+ bwipe!
+ endtry
+ endfor
+ finally
+ call setfperm(dirname, 'rwx------')
+ call delete(dirname, 'd')
+ endtry
+endfunc
+
func Test_netrw_parse_remote_simple()
let result = TestNetrwCaptureRemotePath('scp://user@localhost:2222/test.txt')
call assert_equal(result.method, 'scp')
diff --git a/src/version.c b/src/version.c
index de23cc0a7..38c62e14c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1045,
/**/
1044,
/**/