From b2bd20b47eb0e9fadd74f5655f1e8f4c1e81d476 Mon Sep 17 00:00:00 2001 From: Daniel Nash Date: Mon, 3 Jun 2019 13:02:28 -0400 Subject: [PATCH] Handle a bad extra field in a local file header in zip files --- .../Common/Zip/Headers/ZipFileEntry.cs | 11 +++++++- .../SharpCompress.Test/Zip/ZipArchiveTests.cs | 24 ++++++++++++++++++ .../Archives/Zip.badlocalextra.zip | Bin 0 -> 185 bytes 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/TestArchives/Archives/Zip.badlocalextra.zip diff --git a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs index 8a6449c9..accae7d0 100644 --- a/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs +++ b/src/SharpCompress/Common/Zip/Headers/ZipFileEntry.cs @@ -87,6 +87,15 @@ namespace SharpCompress.Common.Zip.Headers } ushort length = DataConverter.LittleEndian.GetUInt16(extra, i + 2); + + // 7zip has this same kind of check to ignore extras blocks that don't conform to the standard 2-byte ID, 2-byte length, N-byte value. + // CPP/7Zip/Zip/ZipIn.cpp: CInArchive::ReadExtra + if (length > extra.Length) + { + // bad extras block + return; + } + byte[] data = new byte[length]; Buffer.BlockCopy(extra, i + 4, data, 0, length); Extra.Add(LocalEntryHeaderExtraFactory.Create(type, length, data)); @@ -99,4 +108,4 @@ namespace SharpCompress.Common.Zip.Headers internal bool IsZip64 => CompressedSize == uint.MaxValue; } -} \ No newline at end of file +} diff --git a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs index 2576f253..f76b380d 100644 --- a/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs +++ b/tests/SharpCompress.Test/Zip/ZipArchiveTests.cs @@ -512,5 +512,29 @@ namespace SharpCompress.Test.Zip } } } + + [Fact] + public void Zip_BadLocalExtra_Read() + { + string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.badlocalextra.zip"); + + using (ZipArchive za = ZipArchive.Open(zipPath)) + { + var ex = Record.Exception(() => + { + var firstEntry = za.Entries.First(x => x.Key == "first.txt"); + var buffer = new byte[4096]; + + using (var memoryStream = new MemoryStream()) + using (var firstStream = firstEntry.OpenEntryStream()) + { + firstStream.CopyTo(memoryStream); + Assert.Equal(199, memoryStream.Length); + } + }); + + Assert.Null(ex); + } + } } } diff --git a/tests/TestArchives/Archives/Zip.badlocalextra.zip b/tests/TestArchives/Archives/Zip.badlocalextra.zip new file mode 100644 index 0000000000000000000000000000000000000000..3a812a5357e7506149a82671a0616e626ed0f214 GIT binary patch literal 185 zcmWIWW@Zs#U|`^2*c7nVubu4!vm^rp!*K=%22KVJhP2G0;u5`*iV{X9W)@a9c8;q@ z40#zCc$hZSYb|5b-_!7aL9-m|(?7q$1H2iT>=|&Gq{09J4G;=pE*FCWScs89f}!D| k{`)DMR~hF!{NYL#LeK%;tZX1fj0}tn(F_a>9v}__0J=aaYybcN literal 0 HcmV?d00001