From 7332ed892677723e0c62259ca7eff02f8cefcc27 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 02:02:37 +0000 Subject: [PATCH] Accept UnauthorizedAccessException or IOException in Tar chained-symlink test on Windows The ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNestedFile test intermittently fails on Windows (~0.25%) because the colliding directory creation during a rejected traversal can surface as IOException instead of UnauthorizedAccessException depending on extraction ordering. Both exceptions mean the traversal was rejected; the post-extraction assertions still verify nothing escaped the destination. Refs #130177 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TarFile/TarFile.ExtractToDirectory.File.Tests.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs index d8d4e46d005da1..04e1c0088c1012 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs @@ -544,8 +544,13 @@ public void ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNeste if (OperatingSystem.IsWindows()) { - // Windows only creates file symlinks and trying to process a directory symlink will throw UnauthorizedAccessException instead of IOException - Assert.Throws(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + // Windows only creates file symlinks. Processing the chained directory symlink usually + // surfaces as UnauthorizedAccessException, but depending on the order in which the entries + // are extracted the colliding directory creation can instead surface as IOException + // ("a file or directory with the same name already exists"). Either way the traversal is + // rejected before anything escapes the destination, which the assertions below verify. + Exception ex = Assert.ThrowsAny(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + Assert.True(ex is UnauthorizedAccessException or IOException, $"Unexpected exception type: {ex.GetType()}"); } else {