Bug #22340
closedWin32: File.stat succeeds on symbolic-link loops on Windows
Description
On Windows, File.stat succeeds on a self-referential symbolic link instead of raising Errno::ELOOP, and File.exist? returns true. Opening the same link raises Errno::ELOOP.
I noticed this while adding symbolic-link tests to FileUtils, whose Windows CI reported the unexpected File.exist? result.
Reproduction¶
require 'tmpdir'
Dir.mktmpdir do |dir|
Dir.chdir(dir) do
File.symlink('a', 'a')
p File.readlink('a') # => "a"
p File.exist?('a') # => true; expected false
p File.stat('a') # succeeds; expected Errno::ELOOP
File.open('a') # raises Errno::ELOOP
ensure
File.unlink('a') if File.symlink?('a')
end
end
File.lstat('a') should continue to succeed and identify the entry as a symbolic link.
Cause¶
In winnt_stat, failure to open the resolved path falls back to stat_by_find unless open_error matches one of the listed errors. The symbolic-link-following implementation introduced in f5b96e594c769cf309b70fd7736caaf90372a3b6 retained this fallback, which was intended to handle sharing violations for files such as pagefile.sys.
ERROR_CANT_RESOLVE_FILENAME is not listed, so a symbolic-link loop also reaches the fallback, which retrieves information about the link itself and reports success.