From e42d953f47e2339c03e663cdff5015d61873dcea Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Wed, 10 Jul 2024 19:53:32 +0200 Subject: [PATCH 1/3] Check crc on tar header --- .../Common/Tar/Headers/TarHeader.cs | 7 +++++++ tests/SharpCompress.Test/Tar/TarArchiveTests.cs | 11 +++++++++-- tests/TestArchives/Archives/false.positive.tar | Bin 0 -> 1024 bytes 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 tests/TestArchives/Archives/false.positive.tar diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index e9aa343c..510d38a0 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -134,6 +134,13 @@ internal sealed class TarHeader hasLongValue = false; } while (hasLongValue); + var crc = ReadAsciiInt64Base8(buffer, 148, 7); + + if (crc != RecalculateChecksum(buffer)) + { + return false; + } + Name = longName ?? ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); EntryType = entryType; Size = ReadSize(buffer); diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index bbf96c00..6a8f3294 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -217,8 +217,7 @@ public class TarArchiveTests : ArchiveTests { var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); using Stream stream = File.OpenRead(archiveFullPath); - using var archive = ArchiveFactory.Open(stream); - Assert.True(archive.Type == ArchiveType.Tar); + Assert.Throws(() => ArchiveFactory.Open(stream)); } [Theory] @@ -287,4 +286,12 @@ public class TarArchiveTests : ArchiveTests Assert.Equal(2, numberOfEntries); } + + [Fact] + public void Tar_Detect_Test() + { + var isTar = TarArchive.IsTarFile(Path.Combine(TEST_ARCHIVES_PATH, "false.positive.tar")); + + Assert.False(isTar); + } } diff --git a/tests/TestArchives/Archives/false.positive.tar b/tests/TestArchives/Archives/false.positive.tar new file mode 100644 index 0000000000000000000000000000000000000000..db91a2ff2657cb03d7538bb306d0b9816837fb6a GIT binary patch literal 1024 zcmdmZ+NXzsfq{V=L@+Qg%&j(MU}RumP=)eAY!H)^g@NHB0|Nsy11p1#7)S(y`571( zyqFjm*ch1OAR@FQS((|uZbP;K=00SxQ8w`*AjiPKz{ Date: Thu, 11 Jul 2024 19:52:33 +0200 Subject: [PATCH 2/3] Handle special case, empty file --- .../Common/Tar/Headers/TarHeader.cs | 42 +++++++++++++++++-- .../SharpCompress.Test/Tar/TarArchiveTests.cs | 3 +- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 510d38a0..9231833d 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -2,6 +2,7 @@ using System; using System.Buffers.Binary; using System.IO; using System.Text; +using ZstdSharp.Unsafe; namespace SharpCompress.Common.Tar.Headers; @@ -134,9 +135,8 @@ internal sealed class TarHeader hasLongValue = false; } while (hasLongValue); - var crc = ReadAsciiInt64Base8(buffer, 148, 7); - - if (crc != RecalculateChecksum(buffer)) + // Check header checksum + if (!checkChecksum(buffer)) { return false; } @@ -318,6 +318,42 @@ internal sealed class TarHeader (byte)' ' }; + internal static bool checkChecksum(byte[] buf) + { + const int eightSpacesChksum = 256; + var buffer = new Span(buf).Slice(0, 512); + int posix_sum = eightSpacesChksum; + int sun_sum = eightSpacesChksum; + + foreach (byte b in buffer) + { + posix_sum += b; + sun_sum += unchecked((sbyte)b); + } + + // Special case, empty file header + if (posix_sum == eightSpacesChksum) + { + return true; + } + + // Remove current checksum from calculation + foreach (byte b in buffer.Slice(148, 8)) + { + posix_sum -= b; + sun_sum -= unchecked((sbyte)b); + } + + // Read and compare checksum for header + var crc = ReadAsciiInt64Base8(buf, 148, 7); + if (crc != posix_sum && crc != sun_sum) + { + return false; + } + + return true; + } + internal static int RecalculateChecksum(byte[] buf) { // Set default value for checksum. That is 8 spaces. diff --git a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs index 6a8f3294..1024e945 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -217,7 +217,8 @@ public class TarArchiveTests : ArchiveTests { var archiveFullPath = Path.Combine(TEST_ARCHIVES_PATH, "Tar.Empty.tar"); using Stream stream = File.OpenRead(archiveFullPath); - Assert.Throws(() => ArchiveFactory.Open(stream)); + using var archive = ArchiveFactory.Open(stream); + Assert.True(archive.Type == ArchiveType.Tar); } [Theory] From 9515350f52a40cb54627c029a4fc7b6fe7ffc939 Mon Sep 17 00:00:00 2001 From: Lars Vahlenberg Date: Thu, 11 Jul 2024 19:56:46 +0200 Subject: [PATCH 3/3] Remove using directive --- src/SharpCompress/Common/Tar/Headers/TarHeader.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index 9231833d..72c83612 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -2,7 +2,6 @@ using System; using System.Buffers.Binary; using System.IO; using System.Text; -using ZstdSharp.Unsafe; namespace SharpCompress.Common.Tar.Headers;