From f1d743e501fac0eea6f535705f28d6ae0959c864 Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Thu, 30 Apr 2026 11:51:09 +0200 Subject: [PATCH 01/13] Solve symlinks before extraction to avoid possible traversals --- .../src/System/Formats/Tar/TarEntry.cs | 101 +++++++++++++++++- .../TarFile.ExtractToDirectory.File.Tests.cs | 80 ++++++++++++++ 2 files changed, 178 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index 4ae74325894d59..b487929e4e7488 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -336,7 +336,8 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b string? fileDestinationPath = GetFullDestinationPath( destinationDirectoryPath, Path.IsPathFullyQualified(name) ? name : Path.Join(destinationDirectoryPath, name)); - if (fileDestinationPath == null) + + if (fileDestinationPath is null || FilePathEscapesDirectory(destinationDirectoryPath, fileDestinationPath)) { throw new IOException(SR.Format(SR.TarExtractingResultsFileOutside, name, destinationDirectoryPath)); } @@ -357,7 +358,7 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b string? linkDestination = GetFullDestinationPath( destinationDirectoryPath, Path.IsPathFullyQualified(linkName) ? linkName : Path.Join(Path.GetDirectoryName(fileDestinationPath), linkName)); - if (linkDestination is null) + if (linkDestination is null || FilePathEscapesDirectory(destinationDirectoryPath, linkDestination)) { throw new IOException(SR.Format(SR.TarExtractingResultsLinkOutside, linkName, destinationDirectoryPath)); } @@ -372,7 +373,7 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b string? linkDestination = GetFullDestinationPath( destinationDirectoryPath, Path.Join(destinationDirectoryPath, linkName)); - if (linkDestination is null) + if (linkDestination is null || FilePathEscapesDirectory(destinationDirectoryPath, linkDestination)) { throw new IOException(SR.Format(SR.TarExtractingResultsLinkOutside, linkName, destinationDirectoryPath)); } @@ -383,6 +384,100 @@ internal Task ExtractRelativeToDirectoryAsync(string destinationDirectoryPath, b return (fileDestinationPath, linkTargetPath); } + // Check if the file destination path or the link target path escapes the destination directory, by walking through the relative path components and resolving symlinks at each step. + private static bool FilePathEscapesDirectory(string destinationDirectoryPath, string fileDestinationPath) + { + // Windows is case insensitive while Linux is case sensitive + // This ensures the comparison is consistent with how the OS would resolve the paths + StringComparison pathComparison = OperatingSystem.IsWindows() + ? StringComparison.OrdinalIgnoreCase + : StringComparison.Ordinal; + + string resolvedDest = ResolveFullPath(destinationDirectoryPath); + string destPrefix = resolvedDest.EndsWith(Path.DirectorySeparatorChar) + ? resolvedDest + : resolvedDest + Path.DirectorySeparatorChar; + + // Normalize file path (resolves .. and . but not symlinks) + string normalizedFile = Path.GetFullPath(fileDestinationPath); + + // Walk relative components, resolving symlinks at each step + string relative = normalizedFile.Substring(resolvedDest.Length) + .TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); + + string[] components = relative.Split([Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], + StringSplitOptions.RemoveEmptyEntries); + + string current = resolvedDest; + + foreach (string component in components) + { + current = Path.Combine(current, component); + + if (Path.Exists(current)) + { + string? resolved = ResolveSymlink(current); + if (resolved is null) + { + return true; + } + current = resolved; + } + + string normalizedCurrent = Path.GetFullPath(current); + if (!normalizedCurrent.StartsWith(destPrefix, pathComparison) && + !normalizedCurrent.Equals(resolvedDest, pathComparison)) + { + return true; + } + } + + return false; + } + + private static string? ResolveSymlink(string path) + { + FileSystemInfo? target = new FileInfo(path).ResolveLinkTarget(returnFinalTarget: false); + + if (target is null) + { + return Path.GetFullPath(path); + } + return Path.GetFullPath(target.FullName); + } + + // Resolves the full path of the specified path, resolving symlinks at each step. + // This is needed to mitigate malicious entries in the archive that could lead to writing files outside of the intended directory. + private static string ResolveFullPath(string path) + { + string fullPath = Path.GetFullPath(path); + string? root = Path.GetPathRoot(fullPath); + + if (root is null) + { + return fullPath; + } + + string[] components = fullPath.Substring(root.Length) + .Split([Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], StringSplitOptions.RemoveEmptyEntries); + string current = root; + foreach (string component in components) + { + current = Path.Combine(current, component); + if (Path.Exists(current)) + { + string? resolved = ResolveSymlink(current); + if (resolved is null) + { + return current; + } + current = resolved; + } + } + + return current; + } + // Returns the full destination path if the path is the destinationDirectory or a subpath. Otherwise, returns null. private static string? GetFullDestinationPath(string destinationDirectoryFullPath, string qualifiedPath) { 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 9ffbcc00792703..253b16e5b9d99c 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 @@ -368,5 +368,85 @@ public void LinkBeforeTarget() Assert.True(File.Exists(filePath), $"{filePath}' does not exist."); Assert.True(File.Exists(linkPath), $"{linkPath}' does not exist."); } + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void ExtractToDirectory_RejectsSymlinkDirectoryTraversal_WithNestedFile() + { + using TempDirectory root = new TempDirectory(); + string destDir = Path.Combine(root.Path, "dest"); + Directory.CreateDirectory(destDir); + + // Absolute path outside destDir + string linkTarget = "/tmp/outside"; + + string tarPath = Path.Combine(root.Path, "symlink_dir_traversal.tar"); + using (FileStream stream = new FileStream(tarPath, FileMode.Create, FileAccess.Write)) + using (TarWriter writer = new TarWriter(stream, leaveOpen: false)) + { + // symlink: "link" -> "/tmp/outside" + writer.WriteEntry(new PaxTarEntry(TarEntryType.SymbolicLink, "link") + { + LinkName = linkTarget + }); + + // file: "link/test.txt" with "hello" + byte[] content = Encoding.UTF8.GetBytes("hello"); + var fileEntry = new PaxTarEntry(TarEntryType.RegularFile, "link/test.txt") + { + DataStream = new MemoryStream(content, writable: false) + }; + + fileEntry.DataStream.Position = 0; + writer.WriteEntry(fileEntry); + } + + Assert.Throws(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + + // Nothing should be created in dest + string linkPath = Path.Combine(destDir, "link"); + string outsideFilePath = Path.Combine(destDir, "link", "test.txt"); + Assert.False(File.Exists(linkPath) || Directory.Exists(linkPath), "link should not have been created."); + Assert.False(File.Exists(outsideFilePath) || Directory.Exists(linkPath), "traversal link should not have been created."); + } + + + [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + public void ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNestedFile() + { + // dir a/ + // symlink a/b → . + // symlink a/b/c → . + // symlink a/b/c/d → .. / .. / outside + // file a/d/ pwned.txt escapes + + using TempDirectory root = new TempDirectory(); + string destDir = Path.Combine(root.Path, "dest"); + Directory.CreateDirectory(destDir); + + string tarPath = Path.Combine(root.Path, "chained_symlink_traversal.tar"); + using (FileStream stream = new FileStream(tarPath, FileMode.Create, FileAccess.Write)) + using (TarWriter writer = new TarWriter(stream, leaveOpen: false)) + { + writer.WriteEntry(new PaxTarEntry(TarEntryType.Directory, "a/")); + + writer.WriteEntry(new PaxTarEntry(TarEntryType.SymbolicLink, "a/b") { LinkName = "." }); + + writer.WriteEntry(new PaxTarEntry(TarEntryType.SymbolicLink, "a/b/c") { LinkName = "." }); + + writer.WriteEntry(new PaxTarEntry(TarEntryType.SymbolicLink, "a/b/c/d") { LinkName = "../../outside" }); + + var pwned = new PaxTarEntry(TarEntryType.RegularFile, "a/d/pwned.txt") + { + DataStream = new MemoryStream(Encoding.UTF8.GetBytes("pwned")) + }; + writer.WriteEntry(pwned); + } + + Assert.Throws(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + string outsideDir = Path.Combine(root.Path, "outside"); + Assert.False(Directory.Exists(outsideDir), "outside/ directory should not have been created."); + Assert.False(File.Exists(Path.Combine(outsideDir, "pwned.txt")), "pwned.txt should not have been written outside destination."); + + } } } From ad2953df62cf233eb64309f8e228c622c9b7248e Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Thu, 30 Apr 2026 12:39:11 +0200 Subject: [PATCH 02/13] solve copilot comments --- .../src/System/Formats/Tar/TarEntry.cs | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index b487929e4e7488..ad531fff083fff 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -63,6 +63,10 @@ internal TarEntry(TarEntry other, TarEntryFormat format) _header = new TarHeader(format, compatibleEntryType, other._header); } + // Match the limits used by ResolveLinkTarget(returnFinalTarget: true) + // See ResolveLinkTarget in File.cs for comment + private static int s_maxFollowedLinks = OperatingSystem.IsWindows() ? 63 : 40; + /// /// The checksum of all the fields in this entry. The value is non-zero either when the entry is read from an existing archive, or after the entry is written to a new archive. /// @@ -401,6 +405,12 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st // Normalize file path (resolves .. and . but not symlinks) string normalizedFile = Path.GetFullPath(fileDestinationPath); + // Ensure normalizedFile starts with resolvedDest before slicing + if (!normalizedFile.StartsWith(destPrefix, pathComparison)) + { + return true; + } + // Walk relative components, resolving symlinks at each step string relative = normalizedFile.Substring(resolvedDest.Length) .TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); @@ -437,13 +447,21 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st private static string? ResolveSymlink(string path) { - FileSystemInfo? target = new FileInfo(path).ResolveLinkTarget(returnFinalTarget: false); - - if (target is null) + string current = path; + int remaining = s_maxFollowedLinks; + while (remaining-- > 0) { - return Path.GetFullPath(path); + FileSystemInfo? target = new FileInfo(current).ResolveLinkTarget(returnFinalTarget: false); + + if (target is null) + { + break; + } + + current = target.FullName; } - return Path.GetFullPath(target.FullName); + + return Path.GetFullPath(current); } // Resolves the full path of the specified path, resolving symlinks at each step. From 06eb7695e80423bb7b2a4c780c8552b6db44068c Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Mon, 4 May 2026 11:17:44 +0200 Subject: [PATCH 03/13] allow UnauthorizedException to bubble out and update test assertion --- .../src/System/Formats/Tar/TarEntry.cs | 21 +++++-------------- .../TarFile.ExtractToDirectory.File.Tests.cs | 15 ++++++++++--- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index ad531fff083fff..e64810b9c44f62 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -63,10 +63,6 @@ internal TarEntry(TarEntry other, TarEntryFormat format) _header = new TarHeader(format, compatibleEntryType, other._header); } - // Match the limits used by ResolveLinkTarget(returnFinalTarget: true) - // See ResolveLinkTarget in File.cs for comment - private static int s_maxFollowedLinks = OperatingSystem.IsWindows() ? 63 : 40; - /// /// The checksum of all the fields in this entry. The value is non-zero either when the entry is read from an existing archive, or after the entry is written to a new archive. /// @@ -447,21 +443,14 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st private static string? ResolveSymlink(string path) { - string current = path; - int remaining = s_maxFollowedLinks; - while (remaining-- > 0) - { - FileSystemInfo? target = new FileInfo(current).ResolveLinkTarget(returnFinalTarget: false); + FileSystemInfo? target = new FileInfo(path).ResolveLinkTarget(returnFinalTarget: true); - if (target is null) - { - break; - } - - current = target.FullName; + if (target is null) + { + return Path.GetFullPath(path); } - return Path.GetFullPath(current); + return Path.GetFullPath(target.FullName); } // Resolves the full path of the specified path, resolving symlinks at each step. 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 253b16e5b9d99c..4cadee2afbb5f8 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 @@ -416,7 +416,7 @@ public void ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNeste // dir a/ // symlink a/b → . // symlink a/b/c → . - // symlink a/b/c/d → .. / .. / outside + // symlink a/b/c/d → ../../outside // file a/d/ pwned.txt escapes using TempDirectory root = new TempDirectory(); @@ -442,9 +442,18 @@ public void ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNeste writer.WriteEntry(pwned); } - Assert.Throws(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + 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)); + } + else + { + Assert.Throws(() => TarFile.ExtractToDirectory(tarPath, destDir, overwriteFiles: true)); + } + string outsideDir = Path.Combine(root.Path, "outside"); - Assert.False(Directory.Exists(outsideDir), "outside/ directory should not have been created."); + Assert.False(Directory.Exists(outsideDir), "outside/directory should not have been created."); Assert.False(File.Exists(Path.Combine(outsideDir, "pwned.txt")), "pwned.txt should not have been written outside destination."); } From 50179ce7b33a1ef318baad8ba1f1efff7fa1a633 Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Mon, 4 May 2026 14:03:15 +0200 Subject: [PATCH 04/13] fix ambiguous calls --- .../System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index e64810b9c44f62..2847046b4fd9f6 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -411,7 +411,7 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st string relative = normalizedFile.Substring(resolvedDest.Length) .TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); - string[] components = relative.Split([Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], + string[] components = relative.Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string current = resolvedDest; @@ -466,7 +466,7 @@ private static string ResolveFullPath(string path) } string[] components = fullPath.Substring(root.Length) - .Split([Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar], StringSplitOptions.RemoveEmptyEntries); + .Split(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries); string current = root; foreach (string component in components) { From 84d9ee37a3e1b98a463a525c15ecf133f7fe2296 Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Tue, 5 May 2026 13:51:13 +0200 Subject: [PATCH 05/13] address comments --- .../src/System/Formats/Tar/TarEntry.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs index 2847046b4fd9f6..64eea60618b83b 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarEntry.cs @@ -393,7 +393,7 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - string resolvedDest = ResolveFullPath(destinationDirectoryPath); + string resolvedDest = ResolvePhysicalPath(destinationDirectoryPath); string destPrefix = resolvedDest.EndsWith(Path.DirectorySeparatorChar) ? resolvedDest : resolvedDest + Path.DirectorySeparatorChar; @@ -401,12 +401,6 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st // Normalize file path (resolves .. and . but not symlinks) string normalizedFile = Path.GetFullPath(fileDestinationPath); - // Ensure normalizedFile starts with resolvedDest before slicing - if (!normalizedFile.StartsWith(destPrefix, pathComparison)) - { - return true; - } - // Walk relative components, resolving symlinks at each step string relative = normalizedFile.Substring(resolvedDest.Length) .TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); @@ -450,12 +444,12 @@ private static bool FilePathEscapesDirectory(string destinationDirectoryPath, st return Path.GetFullPath(path); } - return Path.GetFullPath(target.FullName); + return target.FullName; } // Resolves the full path of the specified path, resolving symlinks at each step. // This is needed to mitigate malicious entries in the archive that could lead to writing files outside of the intended directory. - private static string ResolveFullPath(string path) + private static string ResolvePhysicalPath(string path) { string fullPath = Path.GetFullPath(path); string? root = Path.GetPathRoot(fullPath); From bdf9959820a1555800fc0ed88de0db6ac436e5a8 Mon Sep 17 00:00:00 2001 From: alinpahontu2912 Date: Wed, 6 May 2026 09:51:43 +0200 Subject: [PATCH 06/13] add missing using --- .../tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs | 1 + 1 file changed, 1 insertion(+) 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 4cadee2afbb5f8..d6483b8444b1c6 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 @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Text; using Xunit; namespace System.Formats.Tar.Tests From ff140ff381ae05ce1965a122348409e60d59e388 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Mon, 11 May 2026 18:24:03 +0000 Subject: [PATCH 07/13] Merged PR 59958: [release/8.0] Fix NativeAOT possible out-of-bounds write for ByValTStr Fix NativeAOT possible out-of-bounds write for ByValTStr StringToByValAnsiString truncated the input string based on Unicode character count only, then called PInvokeMarshal.StringToAnsiString which computed the full ANSI/UTF-8 byte count and wrote it all to the fixed-size native buffer. Add an optional maxByteCount parameter to StringToAnsiString. When set, the byte length is clamped before performing the conversion. For ASCII-only strings, this truncates. For non-ASCII, on Unix, this results in an ArgumentException when the buffer is too small for the encoded bytes and on Windows, this truncates. This matches coreclr. 8.0 version of https://dnceng.visualstudio.com/internal/_git/dotnet-runtime/pullrequest/59956 --- .../Runtime/CompilerHelpers/InteropHelpers.cs | 4 +- .../Runtime/InteropServices/PInvokeMarshal.cs | 23 ++++++-- .../Marshal/StructureToPtrTests.cs | 53 +++++++++++++++++++ 3 files changed, 76 insertions(+), 4 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs index faacce2ea5d14b..9761b2c9362ce1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs @@ -45,7 +45,9 @@ internal static unsafe void StringToByValAnsiString(string str, byte* pNative, i fixed (char* pManaged = str) { - PInvokeMarshal.StringToAnsiString(pManaged, lenUnicode, pNative, /*terminateWithNull=*/true, bestFit, throwOnUnmappableChar); + PInvokeMarshal.StringToAnsiString(pManaged, lenUnicode, pNative, + /*terminateWithNull=*/true, bestFit, throwOnUnmappableChar, + nativeByteLength: charCount); } } else diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs index 61ed1dd6ec08d4..ef6c48c7bd5765 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/PInvokeMarshal.cs @@ -500,9 +500,14 @@ public static unsafe char AnsiCharToWideChar(byte nativeValue) } // c# string (UTF-16) to UTF-8 encoded byte array + // If specified, nativeByteLength represents the length of the output buffer and this function + // will not write more than that many bytes. If negative, this function writes as many bytes + // as needed to encode the string. internal static unsafe byte* StringToAnsiString(char* pManaged, int lenUnicode, byte* pNative, bool terminateWithNull, - bool bestFit, bool throwOnUnmappableChar) + bool bestFit, bool throwOnUnmappableChar, int nativeByteLength = -1) { + Debug.Assert(pNative != null || nativeByteLength == -1, "Native buffer should not be null when nativeByteLength is specified."); + bool allAscii = Ascii.IsValid(new ReadOnlySpan(pManaged, lenUnicode)); int length; @@ -515,6 +520,18 @@ public static unsafe char AnsiCharToWideChar(byte nativeValue) length = GetByteCount(pManaged, lenUnicode); } + // Clamp to nativeByteLength when caller provides a bounded output buffer (ByValTStr). + // For non-ASCII, ConvertWideCharToMultiByte will throw (Unix) or truncate (Windows) + // when the encoded bytes exceed the clamped length. This matches CoreCLR behavior. + if (nativeByteLength >= 0) + { + int maxBytesToWrite = terminateWithNull ? Math.Max(0, nativeByteLength - 1) : nativeByteLength; + if (length > maxBytesToWrite) + { + length = maxBytesToWrite; + } + } + if (pNative == null) { pNative = (byte*)Marshal.AllocCoTaskMem(checked(length + 1)); @@ -534,8 +551,8 @@ public static unsafe char AnsiCharToWideChar(byte nativeValue) throwOnUnmappableChar); } - // Zero terminate - if (terminateWithNull) + // Zero terminate if requested and the buffer is not specified to be size 0. + if (terminateWithNull && nativeByteLength != 0) *(pNative + length) = 0; return pNative; diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs index 59cefc137cef81..4a906e0fc6be1a 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs @@ -363,5 +363,58 @@ public struct InnerStruct public InnerStruct s; public byte b; } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct StructWithByValString + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)] + public string? Name; + } + + [Fact] + [PlatformSpecific(TestPlatforms.AnyUnix)] + public void StructureToPtr_ByValTStr_MultiByte_Overflow() + { + // ByValTStr uses UTF-8 on Unix. € is 3 bytes, so the string exceeds the specified SizeConst + var payload = new StructWithByValString { Name = "€€€" }; + + int size = Marshal.SizeOf(); + IntPtr buffer = Marshal.AllocHGlobal(size + 1); + byte sentinelValue = 0xFF; + try + { + Marshal.WriteByte(buffer, size, sentinelValue); + Assert.Throws(() => Marshal.StructureToPtr(payload, buffer, false)); + Assert.Equal(sentinelValue, Marshal.ReadByte(buffer, size)); + } + finally + { + Marshal.FreeHGlobal(buffer); + } + } + + [Fact] + public void StructureToPtr_ByValTStr_Ascii_TruncatesLongString() + { + var payload = new StructWithByValString { Name = "abcdef" }; + + int size = Marshal.SizeOf(); + IntPtr buffer = Marshal.AllocHGlobal(size + 1); + byte sentinelValue = 0xFF; + try + { + Marshal.WriteByte(buffer, size, sentinelValue); + Marshal.StructureToPtr(payload, buffer, false); + Assert.Equal((byte)'a', Marshal.ReadByte(buffer, 0)); + Assert.Equal((byte)'b', Marshal.ReadByte(buffer, 1)); + Assert.Equal((byte)'c', Marshal.ReadByte(buffer, 2)); + Assert.Equal((byte)0, Marshal.ReadByte(buffer, 3)); + Assert.Equal(sentinelValue, Marshal.ReadByte(buffer, size)); + } + finally + { + Marshal.FreeHGlobal(buffer); + } + } } } From 20950fcc06554656cf1fb4806f19ebd7166790cb Mon Sep 17 00:00:00 2001 From: vseanreesermsft <78103370+vseanreesermsft@users.noreply.github.com> Date: Wed, 3 Jun 2026 03:01:10 -0700 Subject: [PATCH 08/13] Update branding to 8.0.29 (#128914) --- eng/Versions.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 1429f85ac92bba..6a3b58bfe0951e 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,11 +1,11 @@ - 8.0.28 + 8.0.29 8 0 - 28 + 29 8.0.100 7.0.20 6.0.36 From b4ca168ffc70baa3d7866248d400851862d30725 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:08:07 +0200 Subject: [PATCH 09/13] [release/8.0] Update dependencies from dotnet/cecil (#126004) This pull request updates the following dependencies [marker]: <> (Begin:b8bd0c20-0b80-4fdf-a782-08db9e4038dc) ## From https://github.com/dotnet/cecil - **Subscription**: [b8bd0c20-0b80-4fdf-a782-08db9e4038dc](https://maestro.dot.net/subscriptions?search=b8bd0c20-0b80-4fdf-a782-08db9e4038dc) - **Build**: [20260531.3](https://dev.azure.com/dnceng/internal/_build/results?buildId=2988776) ([316549](https://maestro.dot.net/channel/3073/github:dotnet:cecil/build/316549)) - **Date Produced**: June 1, 2026 5:44:58 AM UTC - **Commit**: [fca1a685c57d208f52fd7e7ba48e2059e3bf0c34](https://github.com/dotnet/cecil/commit/fca1a685c57d208f52fd7e7ba48e2059e3bf0c34) - **Branch**: [release/8.0](https://github.com/dotnet/cecil/tree/release/8.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [0.11.4-alpha.26158.1 to 0.11.4-alpha.26281.3][4] - Microsoft.DotNet.Cecil [4]: https://github.com/dotnet/cecil/compare/dc12f3e6cc...fca1a685c5 [DependencyUpdate]: <> (End) [marker]: <> (End:b8bd0c20-0b80-4fdf-a782-08db9e4038dc) --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Petr Onderka --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 822c3cb1cc0fd8..89138cffe8bd20 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -86,9 +86,9 @@ 02fe27cd6a9b001c8feb7938e6ef4b3799745759 - + https://github.com/dotnet/cecil - dc12f3e6ccb3fd7b76c0d5ee3365e6b58d796de0 + fca1a685c57d208f52fd7e7ba48e2059e3bf0c34 diff --git a/eng/Versions.props b/eng/Versions.props index 6a3b58bfe0951e..e2cc5ae9cdd147 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -227,7 +227,7 @@ 8.0.0-rc.1.23406.6 - 0.11.4-alpha.26158.1 + 0.11.4-alpha.26281.3 8.0.0-rc.1.23406.6 From 370e26877cddc901f662ecd7a880c790b200a821 Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Wed, 10 Jun 2026 13:25:26 +0200 Subject: [PATCH 10/13] Marked failing tests as ActiveIssue --- .../tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs | 2 ++ .../Runtime/InteropServices/Marshal/StructureToPtrTests.cs | 1 + 2 files changed, 3 insertions(+) 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 d6483b8444b1c6..97a3facc6185eb 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 @@ -209,6 +209,7 @@ public void Extract_AllSegmentsOfPath() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void ExtractArchiveWithEntriesThatStartWithSlashDotPrefix() { using TempDirectory root = new TempDirectory(); @@ -412,6 +413,7 @@ public void ExtractToDirectory_RejectsSymlinkDirectoryTraversal_WithNestedFile() [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX | TestPlatforms.Windows)] public void ExtractToDirectory_RejectsChainedSymlinkDirectoryTraversal_WithNestedFile() { // dir a/ diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs index 4a906e0fc6be1a..f553f2945888a0 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs @@ -373,6 +373,7 @@ public struct StructWithByValString [Fact] [PlatformSpecific(TestPlatforms.AnyUnix)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129228")] public void StructureToPtr_ByValTStr_MultiByte_Overflow() { // ByValTStr uses UTF-8 on Unix. € is 3 bytes, so the string exceeds the specified SizeConst From c5d2de949537dbb01e38f3235f3d9bf1eeacb191 Mon Sep 17 00:00:00 2001 From: Petr Onderka Date: Wed, 10 Jun 2026 17:55:26 +0200 Subject: [PATCH 11/13] Marked more failing tests as ActiveIssue --- .../tests/TarFile/TarFile.ExtractToDirectory.File.Tests.cs | 6 ++++++ .../TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs | 7 +++++++ .../TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs | 6 ++++++ .../TarFile.ExtractToDirectoryAsync.Stream.Tests.cs | 7 +++++++ 4 files changed, 26 insertions(+) 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 97a3facc6185eb..4e8a5b8e89a811 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 @@ -46,6 +46,7 @@ public void NonExistentDirectory_Throws() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void SetsLastModifiedTimeOnExtractedFiles() { using TempDirectory root = new TempDirectory(); @@ -73,6 +74,7 @@ public void SetsLastModifiedTimeOnExtractedFiles() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void SetsLastModifiedTimeOnExtractedDirectories() { using TempDirectory root = new TempDirectory(); @@ -235,6 +237,7 @@ public void ExtractArchiveWithEntriesThatStartWithSlashDotPrefix() [Theory] [InlineData(true)] [InlineData(false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void UnixFileModes(bool overwrite) { using TempDirectory source = new TempDirectory(); @@ -303,6 +306,7 @@ public void UnixFileModes(bool overwrite) [Theory] [InlineData(true)] [InlineData(false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void UnixFileModes_RestrictiveParentDir(bool overwrite) { using TempDirectory source = new TempDirectory(); @@ -343,6 +347,7 @@ public void UnixFileModes_RestrictiveParentDir(bool overwrite) } [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void LinkBeforeTarget() { using TempDirectory source = new TempDirectory(); @@ -372,6 +377,7 @@ public void LinkBeforeTarget() } [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void ExtractToDirectory_RejectsSymlinkDirectoryTraversal_WithNestedFile() { using TempDirectory root = new TempDirectory(); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index 8bd60b6f3b4a53..03ec5658b0caa6 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -76,6 +76,7 @@ public void ExtractEntry_ManySubfolderSegments_NoPrecedingDirectoryEntries() [Theory] [InlineData(TarEntryType.SymbolicLink)] [InlineData(TarEntryType.HardLink)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_LinkEntry_TargetOutsideDirectory(TarEntryType entryType) { using MemoryStream archive = new MemoryStream(); @@ -98,21 +99,25 @@ public void Extract_LinkEntry_TargetOutsideDirectory(TarEntryType entryType) [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_SymbolicLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, null); [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_HardLinkEntry_TargetInsideDirectory(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, null); [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_SymbolicLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.SymbolicLink, format, new string('a', 99)); [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_HardLinkEntry_TargetInsideDirectory_LongBaseDir(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType.HardLink, format, new string('a', 99)); // This test would not pass for the V7 and Ustar formats in some OSs like MacCatalyst, tvOSSimulator and OSX, because the TempDirectory gets created in @@ -152,6 +157,7 @@ private void Extract_LinkEntry_TargetInsideDirectory_Internal(TarEntryType entry [InlineData(512)] [InlineData(512 + 1)] [InlineData(512 + 512 - 1)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries(int contentSize) { byte[] fileContents = new byte[contentSize]; @@ -208,6 +214,7 @@ public void PaxNameCollision_DedupInExtendedAttributes() [Theory] [MemberData(nameof(GetTestTarFormats))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public void UnseekableStreams_RoundTrip(TestTarFormat testFormat) { using TempDirectory root = new(); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs index 42b0eef65eef87..efc8bbea35c5d9 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.File.Tests.cs @@ -57,6 +57,7 @@ public async Task NonExistentDirectory_Throws_Async() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task SetsLastModifiedTimeOnExtractedFiles() { using TempDirectory root = new TempDirectory(); @@ -84,6 +85,7 @@ public async Task SetsLastModifiedTimeOnExtractedFiles() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task SetsLastModifiedTimeOnExtractedDirectories() { using TempDirectory root = new TempDirectory(); @@ -236,6 +238,7 @@ public async Task Extract_AllSegmentsOfPath_Async() } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task ExtractArchiveWithEntriesThatStartWithSlashDotPrefix_Async() { using (TempDirectory root = new TempDirectory()) @@ -264,6 +267,7 @@ public async Task ExtractArchiveWithEntriesThatStartWithSlashDotPrefix_Async() [Theory] [InlineData(true)] [InlineData(false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task UnixFileModes_Async(bool overwrite) { using TempDirectory source = new TempDirectory(); @@ -330,6 +334,7 @@ public async Task UnixFileModes_Async(bool overwrite) } [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task UnixFileModes_RestrictiveParentDir_Async() { using TempDirectory source = new TempDirectory(); @@ -363,6 +368,7 @@ public async Task UnixFileModes_RestrictiveParentDir_Async() } [ConditionalFact(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task LinkBeforeTargetAsync() { using TempDirectory source = new TempDirectory(); diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs index 4a163767e94043..3801481ca111d1 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs @@ -136,6 +136,7 @@ public async Task ExtractEntry_PodmanImageTarWithRelativeSymlinksPointingInExtra [Theory] [InlineData(TarEntryType.SymbolicLink)] [InlineData(TarEntryType.HardLink)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task Extract_LinkEntry_TargetOutsideDirectory_Async(TarEntryType entryType) { await using (MemoryStream archive = new MemoryStream()) @@ -160,21 +161,25 @@ public async Task Extract_LinkEntry_TargetOutsideDirectory_Async(TarEntryType en [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public Task Extract_SymbolicLinkEntry_TargetInsideDirectory_Async(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEntryType.SymbolicLink, format, null); [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public Task Extract_HardLinkEntry_TargetInsideDirectory_Async(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEntryType.HardLink, format, null); [ConditionalTheory(typeof(MountHelper), nameof(MountHelper.CanCreateSymbolicLinks))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public Task Extract_SymbolicLinkEntry_TargetInsideDirectory_LongBaseDir_Async(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEntryType.SymbolicLink, format, new string('a', 99)); [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsHardLinkCreation))] [InlineData(TarEntryFormat.Pax)] [InlineData(TarEntryFormat.Gnu)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public Task Extract_HardLinkEntry_TargetInsideDirectory_LongBaseDir_Async(TarEntryFormat format) => Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEntryType.HardLink, format, new string('a', 99)); // This test would not pass for the V7 and Ustar formats in some OSs like MacCatalyst, tvOSSimulator and OSX, because the TempDirectory gets created in @@ -217,6 +222,7 @@ private async Task Extract_LinkEntry_TargetInsideDirectory_Internal_Async(TarEnt [InlineData(512)] [InlineData(512 + 1)] [InlineData(512 + 512 - 1)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task Extract_UnseekableStream_BlockAlignmentPadding_DoesNotAffectNextEntries_Async(int contentSize) { byte[] fileContents = new byte[contentSize]; @@ -273,6 +279,7 @@ public async Task PaxNameCollision_DedupInExtendedAttributesAsync() [Theory] [MemberData(nameof(GetTestTarFormats))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/129227", TestPlatforms.OSX)] public async Task UnseekableStreams_RoundTrip_Async(TestTarFormat testFormat) { using TempDirectory root = new(); From 738e6ff2770f71f1268f88a5bcbcf73d117b63f9 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:41:33 +0200 Subject: [PATCH 12/13] [release/8.0] Update dependencies from dotnet/arcade (#126394) This pull request updates the following dependencies [marker]: <> (Begin:27d7515f-61f3-43b1-8bf0-e99f74c2f310) ## From https://github.com/dotnet/arcade - **Subscription**: [27d7515f-61f3-43b1-8bf0-e99f74c2f310](https://maestro.dot.net/subscriptions?search=27d7515f-61f3-43b1-8bf0-e99f74c2f310) - **Build**: [20260528.3](https://dev.azure.com/dnceng/internal/_build/results?buildId=2986525) ([316242](https://maestro.dot.net/channel/3885/github:dotnet:arcade/build/316242)) - **Date Produced**: May 28, 2026 9:35:33 PM UTC - **Commit**: [4b95fb1a9307265eb75f62d4937be50e6786e94e](https://github.com/dotnet/arcade/commit/4b95fb1a9307265eb75f62d4937be50e6786e94e) - **Branch**: [release/8.0](https://github.com/dotnet/arcade/tree/release/8.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [8.0.0-beta.26224.3 to 8.0.0-beta.26278.3][3] - Microsoft.DotNet.Arcade.Sdk - Microsoft.DotNet.Build.Tasks.Archives - Microsoft.DotNet.Build.Tasks.Feed - Microsoft.DotNet.Build.Tasks.Installers - Microsoft.DotNet.Build.Tasks.Packaging - Microsoft.DotNet.Build.Tasks.TargetFramework - Microsoft.DotNet.Build.Tasks.Templating - Microsoft.DotNet.Build.Tasks.Workloads - Microsoft.DotNet.CodeAnalysis - Microsoft.DotNet.GenAPI - Microsoft.DotNet.GenFacades - Microsoft.DotNet.Helix.Sdk - Microsoft.DotNet.PackageTesting - Microsoft.DotNet.RemoteExecutor - Microsoft.DotNet.SharedFramework.Sdk - Microsoft.DotNet.VersionTools.Tasks - Microsoft.DotNet.XUnitExtensions - From [2.5.1-beta.26224.3 to 2.5.1-beta.26278.3][3] - Microsoft.DotNet.XUnitConsoleRunner [3]: https://github.com/dotnet/arcade/compare/d9af20b993...4b95fb1a93 [DependencyUpdate]: <> (End) [marker]: <> (End:27d7515f-61f3-43b1-8bf0-e99f74c2f310) --------- Co-authored-by: dotnet-maestro[bot] Co-authored-by: Petr Onderka --- eng/Version.Details.xml | 72 ++++++++++++++++++++--------------------- eng/Versions.props | 30 ++++++++--------- global.json | 6 ++-- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 89138cffe8bd20..1ca77b8cb9bcdb 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -112,9 +112,9 @@ - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e @@ -122,69 +122,69 @@ 73f0850939d96131c28cf6ea6ee5aacb4da0083a - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e https://github.com/dotnet/runtime-assets @@ -335,9 +335,9 @@ https://github.com/dotnet/xharness 28f5ed3a089ff1a179f523da0c910348e9010414 - + https://github.com/dotnet/arcade - d9af20b993c474033098fe0851c2d71b4ecf434b + 4b95fb1a9307265eb75f62d4937be50e6786e94e https://dev.azure.com/dnceng/internal/_git/dotnet-optimization diff --git a/eng/Versions.props b/eng/Versions.props index e2cc5ae9cdd147..cda70c639e8bee 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -88,21 +88,21 @@ 8.0.100 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 2.5.1-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 - 8.0.0-beta.26224.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 2.5.1-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 + 8.0.0-beta.26278.3 6.0.0-preview.1.102 diff --git a/global.json b/global.json index 8493e87c9f4890..06f51ca4fd3c7d 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "8.0.126" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.26224.3", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.26224.3", - "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.26224.3", + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.26278.3", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.26278.3", + "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.26278.3", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "8.0.0-rc.1.23406.6" From 4e7e8e5f2adb09ed6fce32ca18f8f8b26443b20a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Thu, 11 Jun 2026 17:42:18 +0200 Subject: [PATCH 13/13] [release/8.0] Update dependencies from dotnet/emsdk (#128223) This pull request updates the following dependencies [marker]: <> (Begin:4ebef09c-22a4-4345-9e95-08db9f47cad7) ## From https://github.com/dotnet/emsdk - **Subscription**: [4ebef09c-22a4-4345-9e95-08db9f47cad7](https://maestro.dot.net/subscriptions?search=4ebef09c-22a4-4345-9e95-08db9f47cad7) - **Build**: [20260603.5](https://dev.azure.com/dnceng/internal/_build/results?buildId=2991414) ([317142](https://maestro.dot.net/channel/3073/github:dotnet:emsdk/build/317142)) - **Date Produced**: June 3, 2026 7:10:41 PM UTC - **Commit**: [ac9f8092f4f527cb3ace4aac03f8d1dbadc39983](https://github.com/dotnet/emsdk/commit/ac9f8092f4f527cb3ace4aac03f8d1dbadc39983) - **Branch**: [release/8.0](https://github.com/dotnet/emsdk/tree/release/8.0) [DependencyUpdate]: <> (Begin) - **Dependency Updates**: - From [8.0.28-servicing.26258.2 to 8.0.29-servicing.26303.5][3] - Microsoft.SourceBuild.Intermediate.emsdk - From [8.0.28 to 8.0.29][3] - Microsoft.NET.Workload.Emscripten.Current.Manifest-8.0.100 [3]: https://github.com/dotnet/emsdk/compare/35ebe6f3e6...ac9f8092f4 [DependencyUpdate]: <> (End) [marker]: <> (End:4ebef09c-22a4-4345-9e95-08db9f47cad7) --------- Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 2 +- eng/Version.Details.xml | 8 ++++---- eng/Versions.props | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/NuGet.config b/NuGet.config index a61fb8523e1d8f..8d731f02bb5a1b 100644 --- a/NuGet.config +++ b/NuGet.config @@ -9,7 +9,7 @@ - + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1ca77b8cb9bcdb..ed12617c02e2c3 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -91,13 +91,13 @@ fca1a685c57d208f52fd7e7ba48e2059e3bf0c34 - + https://github.com/dotnet/emsdk - 35ebe6f3e6953f878ed92f637ad8d7f27202f7a6 + ac9f8092f4f527cb3ace4aac03f8d1dbadc39983 - + https://github.com/dotnet/emsdk - 35ebe6f3e6953f878ed92f637ad8d7f27202f7a6 + ac9f8092f4f527cb3ace4aac03f8d1dbadc39983 diff --git a/eng/Versions.props b/eng/Versions.props index cda70c639e8bee..85be789a5832eb 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -253,7 +253,7 @@ Note: when the name is updated, make sure to update dependency name in eng/pipelines/common/xplat-setup.yml like - DarcDependenciesChanged.Microsoft_NET_Workload_Emscripten_Current_Manifest-8_0_100_Transport --> - 8.0.28 + 8.0.29 $(MicrosoftNETWorkloadEmscriptenCurrentManifest80100Version)