From 3b29fd2e75e9a3c8d6ad2b3b090a83d2197cafd7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:44:20 +0000 Subject: [PATCH 1/4] Initial plan From 2f8326910f961300279a22e4d7ad5a25b652edc9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:53:28 +0000 Subject: [PATCH 2/4] Add missing error handling in SafeFileHandle.GetFileTypeCore on Windows Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/4f6aad61-177e-46ba-af07-c0835e31e477 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../Win32/SafeHandles/SafeFileHandle.Windows.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs index 393154799ce2f4..5e99be778d7a57 100644 --- a/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.Windows.cs @@ -334,6 +334,18 @@ internal FileHandleType GetFileTypeCore() Debug.Assert(Path is null || _fileOptions != UninitializedOptions, "When Path is set, _fileOptions are also provided."); int kernelFileType = Interop.Kernel32.GetFileType(this); + // GetFileType returns FILE_TYPE_UNKNOWN both when the type is unknown and when an error occurs. + // Check GetLastError to distinguish the two cases. + if (kernelFileType == Interop.Kernel32.FileTypes.FILE_TYPE_UNKNOWN) + { + int error = Marshal.GetLastPInvokeError(); + if (error != Interop.Errors.ERROR_SUCCESS) + { + throw Win32Marshal.GetExceptionForWin32Error(error, Path); + } + return FileHandleType.Unknown; + } + return kernelFileType switch { Interop.Kernel32.FileTypes.FILE_TYPE_CHAR => FileHandleType.CharacterDevice, From 275074d3baddc3d5c8155b935582f43298932c7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 22:03:34 +0000 Subject: [PATCH 3/4] Add cross-platform test for SafeFileHandle.Type with an invalid handle Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/18b0964e-a520-4329-add2-d02761a087ec Co-authored-by: adamsitnik <6011991+adamsitnik@users.noreply.github.com> --- .../SafeFileHandle/GetFileType.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs index 086d9e850ec6c4..b965bdcb5ea265 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs @@ -86,5 +86,24 @@ public void GetFileType_CachesResult() Assert.Equal(firstCall, secondCall); Assert.Equal(FileHandleType.RegularFile, firstCall); } + + [Fact] + public void GetFileType_InvalidHandle_Throws() + { + string path = GetTestFilePath(); + File.WriteAllText(path, "test"); + + SafeFileHandle original = File.OpenHandle(path, FileMode.Open, FileAccess.Read); + IntPtr nativeHandle = original.DangerousGetHandle(); + + // Wrap the same native handle value without taking ownership. + using SafeFileHandle copy = new SafeFileHandle(nativeHandle, ownsHandle: false); + + // Dispose the original, which closes the underlying OS handle. + original.Dispose(); + + // Accessing Type on the copy should throw because the underlying handle is now invalid. + AssertExtensions.ThrowsAny(() => copy.Type); + } } } From c8d2aa70ad3051b58d40fd5e7ec7b9fb5ccb33b9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 7 Apr 2026 22:31:39 +0000 Subject: [PATCH 4/4] Remove unreliable GetFileType_InvalidHandle_Throws test Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/3a0338b4-3054-4780-aa40-a53037e9e9d8 Co-authored-by: jkotas <6668460+jkotas@users.noreply.github.com> --- .../SafeFileHandle/GetFileType.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs index b965bdcb5ea265..086d9e850ec6c4 100644 --- a/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs +++ b/src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/SafeFileHandle/GetFileType.cs @@ -86,24 +86,5 @@ public void GetFileType_CachesResult() Assert.Equal(firstCall, secondCall); Assert.Equal(FileHandleType.RegularFile, firstCall); } - - [Fact] - public void GetFileType_InvalidHandle_Throws() - { - string path = GetTestFilePath(); - File.WriteAllText(path, "test"); - - SafeFileHandle original = File.OpenHandle(path, FileMode.Open, FileAccess.Read); - IntPtr nativeHandle = original.DangerousGetHandle(); - - // Wrap the same native handle value without taking ownership. - using SafeFileHandle copy = new SafeFileHandle(nativeHandle, ownsHandle: false); - - // Dispose the original, which closes the underlying OS handle. - original.Dispose(); - - // Accessing Type on the copy should throw because the underlying handle is now invalid. - AssertExtensions.ThrowsAny(() => copy.Type); - } } }