Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mitigation of problems #686

Merged
merged 3 commits into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions src/SharpCompress/Common/Zip/StreamingZipFilePart.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,38 @@ internal BinaryReader FixStreamedFileLocation(ref RewindableStream rewindableStr
{
_decompressionStream ??= GetCompressedStream();

_decompressionStream.Skip();
if( Header.CompressionMethod != ZipCompressionMethod.None )
{
_decompressionStream.Skip();

if (_decompressionStream is DeflateStream deflateStream)
if (_decompressionStream is DeflateStream deflateStream)
{
rewindableStream.Rewind(deflateStream.InputBuffer);
}
}
else
{
rewindableStream.Rewind(deflateStream.InputBuffer);
// We would need to search for the magic word
rewindableStream.Position -= 4;
var pos = rewindableStream.Position;
while( Utility.Find(rewindableStream, new byte[] { 0x50,0x4b,0x07,0x08 } ) )
{
// We should probably check CRC32 for positive matching as well
var size = rewindableStream.Position - pos;
var br = new BinaryReader(rewindableStream);
br.ReadUInt32();
br.ReadUInt32(); // CRC32
var compressed_size = br.ReadUInt32();
var uncompressed_size = br.ReadUInt32();
if (compressed_size == size && compressed_size == uncompressed_size )
{
rewindableStream.Position -= 16;
break;
}
rewindableStream.Position -= 12;
}
}

Skipped = true;
}
var reader = new BinaryReader(rewindableStream);
Expand Down
2 changes: 1 addition & 1 deletion src/SharpCompress/Readers/AbstractReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ private void SkipEntry()
private void Skip()
{
var part = Entry.Parts.First();
part.Skipped = true;

if (ArchiveType != ArchiveType.Rar
&& !Entry.IsSolid
Expand All @@ -145,6 +144,7 @@ private void Skip()
{
var bytesToAdvance = Entry.CompressedSize;
rawStream.Skip(bytesToAdvance);
part.Skipped = true;
return;
}
}
Expand Down
35 changes: 35 additions & 0 deletions src/SharpCompress/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,41 @@ public static void Skip(this Stream source)
}
}

public static bool Find(this Stream source, byte[] array)
{
byte[] buffer = GetTransferByteArray();
try
{
var pos = source.Position;
int count = 0;
var len = source.Read(buffer, 0, buffer.Length);
source.Position = pos + len;

do
{
for (int i = 0; i < len; i++)
{
if (array[count] == buffer[i])
{
count++;
if (count == array.Length)
{
source.Position = source.Position - len + i - array.Length +1;
return true;
}
}
}
}
while ((len = source.Read(buffer, 0, buffer.Length)) > 0);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}

return false;
}

public static DateTime DosDateToDateTime(UInt16 iDate, UInt16 iTime)
{
int year = iDate / 512 + 1980;
Expand Down
11 changes: 9 additions & 2 deletions tests/SharpCompress.Test/Zip/ZipArchiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -738,13 +738,20 @@ public void Zip_Zip64_CompressedSizeExtraOnly_Read()
[Fact]
public void Zip_Uncompressed_Skip_All()
{
string zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip");
var keys = new string[] { "Folder/File1.txt", "Folder/File2.rtf", "Folder2/File1.txt", "Folder2/File2.txt", "DEADBEEF" };
var zipPath = Path.Combine(TEST_ARCHIVES_PATH, "Zip.uncompressed.zip");
using (var stream = File.Open(zipPath, FileMode.Open, FileAccess.Read))
{
IArchive archive = ArchiveFactory.Open(stream);
IReader reader = archive.ExtractAllEntries();
int x = 0;
while (reader.MoveToNextEntry())
;
{
Assert.Equal(keys[x], reader.Entry.Key);
x++;
}

Assert.Equal(4, x);
}
}
}
Expand Down
18 changes: 17 additions & 1 deletion tests/SharpCompress.Test/Zip/ZipReaderTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.IO;
using SharpCompress.Common;
using SharpCompress.IO;
Expand Down Expand Up @@ -368,5 +368,21 @@ public void Zip_None_Issue86_Streamed_Read()
}
}

[Fact]
public void Zip_ReaderMoveToNextEntry()
{
var keys = new string[] { "version", "sizehint", "data/0/metadata", "data/0/records" };

using (var fileStream = File.OpenRead(Path.Combine(TEST_ARCHIVES_PATH, "test_477.zip")))
using (var reader = ZipReader.Open(fileStream))
{
foreach( var key in keys)
{
reader.MoveToNextEntry();

Assert.Equal(reader.Entry.Key, key);
}
}
}
}
}
Binary file added tests/TestArchives/Archives/test_477.zip
Binary file not shown.