From 1d400c283a1b25eb9910ebd1a49056d8c9e58860 Mon Sep 17 00:00:00 2001
From: Adeel Mujahid <3840695+am11@users.noreply.github.com>
Date: Thu, 20 Oct 2022 21:51:48 +0300
Subject: [PATCH 1/2] Trim file type bits from mode header (#77151)
* Trim file type bits from mode header
* Define and use ValidUnixFileModes
* Rev System.Formats.Tar.TestData version
* Move ValidUnixFileModes to shared helpers
---
.../src/System/Formats/Tar/TarEntry.cs | 6 ++++--
.../src/System/Formats/Tar/TarHelpers.cs | 14 ++++++++++++++
.../src/System/Formats/Tar/TarWriter.Unix.cs | 3 ++-
...TarFile.ExtractToDirectoryAsync.Stream.Tests.cs | 13 +++++++++++++
4 files changed, 33 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 a27df41f4c1c6..5c08ec75f74da 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
@@ -138,10 +138,12 @@ public string LinkName
/// The value in this field has no effect on Windows platforms.
public UnixFileMode Mode
{
- get => (UnixFileMode)_header._mode;
+ // Some paths do not use the setter, and we want to return valid UnixFileMode.
+ // This mask only keeps the least significant 12 bits.
+ get => (UnixFileMode)(_header._mode & (int)TarHelpers.ValidUnixFileModes);
set
{
- if ((int)value is < 0 or > 4095) // 4095 in decimal is 7777 in octal
+ if ((value & ~TarHelpers.ValidUnixFileModes) != 0) // throw on invalid UnixFileModes
{
throw new ArgumentOutOfRangeException(nameof(value));
}
diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs
index d5393b45ffc83..45cae1c275904 100644
--- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs
+++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHelpers.cs
@@ -21,6 +21,20 @@ internal static partial class TarHelpers
internal const int MaxBufferLength = 4096;
internal const long MaxSizeLength = (1L << 33) - 1; // Max value of 11 octal digits = 2^33 - 1 or 8 Gb.
+ internal const UnixFileMode ValidUnixFileModes =
+ UnixFileMode.UserRead |
+ UnixFileMode.UserWrite |
+ UnixFileMode.UserExecute |
+ UnixFileMode.GroupRead |
+ UnixFileMode.GroupWrite |
+ UnixFileMode.GroupExecute |
+ UnixFileMode.OtherRead |
+ UnixFileMode.OtherWrite |
+ UnixFileMode.OtherExecute |
+ UnixFileMode.StickyBit |
+ UnixFileMode.SetGroup |
+ UnixFileMode.SetUser;
+
// Default mode for TarEntry created for a file-type.
private const UnixFileMode DefaultFileMode =
UnixFileMode.UserRead | UnixFileMode.UserWrite |
diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs
index a691582178df6..357e4a8a7587f 100644
--- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs
+++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarWriter.Unix.cs
@@ -66,7 +66,8 @@ private TarEntry ConstructEntryForWriting(string fullPath, string entryName, Fil
entry._header._aTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(status.ATime);
entry._header._cTime = TarHelpers.GetDateTimeOffsetFromSecondsSinceEpoch(status.CTime);
- entry._header._mode = status.Mode & 4095; // First 12 bits
+ // This mask only keeps the least significant 12 bits valid for UnixFileModes
+ entry._header._mode = status.Mode & (int)TarHelpers.ValidUnixFileModes;
// Uid and UName
entry._header._uid = (int)status.Uid;
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 70c6fcbf8049d..82c37fb0dd0a7 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
@@ -97,6 +97,19 @@ public async Task ExtractEntry_ManySubfolderSegments_NoPrecedingDirectoryEntries
}
}
+ [Fact]
+ public async Task ExtractEntry_DockerImageTarWithFileTypeInDirectoriesInMode_SuccessfullyExtracts_Async()
+ {
+ using (TempDirectory root = new TempDirectory())
+ {
+ await using MemoryStream archiveStream = GetTarMemoryStream(CompressionMethod.Uncompressed, "golang_tar", "docker-hello-world");
+ await TarFile.ExtractToDirectoryAsync(archiveStream, root.Path, overwriteFiles: true);
+
+ Assert.True(File.Exists(Path.Join(root.Path, "manifest.json")));
+ Assert.True(File.Exists(Path.Join(root.Path, "repositories")));
+ }
+ }
+
[Theory]
[InlineData(TarEntryType.SymbolicLink)]
[InlineData(TarEntryType.HardLink)]
From 7cb0085ea51880a6e00a7e2e6b3ef572e547bd8a Mon Sep 17 00:00:00 2001
From: Jeff Handley
Date: Mon, 31 Oct 2022 11:43:42 -0700
Subject: [PATCH 2/2] Bump package version for TAR test assets
---
eng/Versions.props | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/eng/Versions.props b/eng/Versions.props
index bf5ca9e368df6..6a06b30e7d7d5 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -126,7 +126,7 @@
7.0.0-beta.22503.1
7.0.0-beta.22503.1
7.0.0-beta.22503.1
- 7.0.0-beta.22503.1
+ 7.0.0-beta.22524.1
7.0.0-beta.22503.1
7.0.0-beta.22503.1
7.0.0-beta.22503.1