diff --git a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs index e9aa343c..72c83612 100644 --- a/src/SharpCompress/Common/Tar/Headers/TarHeader.cs +++ b/src/SharpCompress/Common/Tar/Headers/TarHeader.cs @@ -134,6 +134,12 @@ internal bool Read(BinaryReader reader) hasLongValue = false; } while (hasLongValue); + // Check header checksum + if (!checkChecksum(buffer)) + { + return false; + } + Name = longName ?? ArchiveEncoding.Decode(buffer, 0, 100).TrimNulls(); EntryType = entryType; Size = ReadSize(buffer); @@ -311,6 +317,42 @@ private static long ReadAsciiInt64(byte[] buffer, int offset, int count) (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 bbf96c00..1024e945 100644 --- a/tests/SharpCompress.Test/Tar/TarArchiveTests.cs +++ b/tests/SharpCompress.Test/Tar/TarArchiveTests.cs @@ -287,4 +287,12 @@ public void Tar_Read_One_At_A_Time() 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 00000000..db91a2ff Binary files /dev/null and b/tests/TestArchives/Archives/false.positive.tar differ