Skip to content
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
49 changes: 49 additions & 0 deletions src/SharpCompress/Compressors/Filters/BCJFilterARM.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System.IO;

namespace SharpCompress.Compressors.Filters;

internal class BCJFilterARM : Filter
{
private int _pos;

public BCJFilterARM(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 8) => _pos = 8;

protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;

for (i = offset; i <= end; i += 4)
{
if ((buffer[i + 3] & 0xFF) == 0xEB)
{
int src =
((buffer[i + 2] & 0xFF) << 16)
| ((buffer[i + 1] & 0xFF) << 8)
| (buffer[i] & 0xFF);

src <<= 2;

int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}

dest >>>= 2;
buffer[i + 2] = (byte)(dest >>> 16);
buffer[i + 1] = (byte)(dest >>> 8);
buffer[i] = (byte)dest;
}
}

i -= offset;
_pos += i;
return i;
}
}
47 changes: 47 additions & 0 deletions src/SharpCompress/Compressors/Filters/BCJFilterARMT.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.IO;

namespace SharpCompress.Compressors.Filters;

internal class BCJFilterARMT : Filter
{
private int _pos;

public BCJFilterARMT(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 4;

protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;

for (i = offset; i <= end; i += 2)
{
if ((buffer[i + 1] & 0xF8) == 0xF0 && (buffer[i + 3] & 0xF8) == 0xF8)
{
int src =
((buffer[i + 1] & 0x07) << 19)
| ((buffer[i] & 0xFF) << 11)
| ((buffer[i + 3] & 0x07) << 8)
| (buffer[i + 2] & 0xFF);
src <<= 1;

int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);

dest >>>= 1;
buffer[i + 1] = (byte)(0xF0 | ((dest >>> 19) & 0x07));
buffer[i] = (byte)(dest >>> 11);
buffer[i + 3] = (byte)(0xF8 | ((dest >>> 8) & 0x07));
buffer[i + 2] = (byte)dest;
i += 2;
}
}

i -= offset;
_pos += i;
return i;
}
}
107 changes: 107 additions & 0 deletions src/SharpCompress/Compressors/Filters/BCJFilterIA64.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
using System.IO;

namespace SharpCompress.Compressors.Filters;

internal class BCJFilterIA64 : Filter
{
private int _pos;

private static readonly int[] BRANCH_TABLE =
{
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
4,
4,
6,
6,
0,
0,
7,
7,
4,
4,
0,
0,
4,
4,
0,
0
};

public BCJFilterIA64(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 16) => _pos = 0;

protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 16;
int i;

for (i = offset; i <= end; i += 16)
{
int instrTemplate = buffer[i] & 0x1F;
int mask = BRANCH_TABLE[instrTemplate];

for (int slot = 0, bitPos = 5; slot < 3; ++slot, bitPos += 41)
{
if (((mask >>> slot) & 1) == 0)
continue;

int bytePos = bitPos >>> 3;
int bitRes = bitPos & 7;

long instr = 0;
for (int j = 0; j < 6; ++j)
{
instr |= (buffer[i + bytePos + j] & 0xFFL) << (8 * j);
}

long instrNorm = instr >>> bitRes;

if (((instrNorm >>> 37) & 0x0F) != 0x05 || ((instrNorm >>> 9) & 0x07) != 0x00)
continue;

int src = (int)((instrNorm >>> 13) & 0x0FFFFF);
src |= ((int)(instrNorm >>> 36) & 1) << 20;
src <<= 4;

int dest;
if (_isEncoder)
dest = src + (_pos + i - offset);
else
dest = src - (_pos + i - offset);

dest >>>= 4;

instrNorm &= ~(0x8FFFFFL << 13);
instrNorm |= (dest & 0x0FFFFFL) << 13;
instrNorm |= (dest & 0x100000L) << (36 - 20);

instr &= (1 << bitRes) - 1;
instr |= instrNorm << bitRes;

for (int j = 0; j < 6; ++j)
{
buffer[i + bytePos + j] = (byte)(instr >>> (8 * j));
}
}
}

i -= offset;
_pos += i;
return i;
}
}
48 changes: 48 additions & 0 deletions src/SharpCompress/Compressors/Filters/BCJFilterPPC.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using System.IO;

namespace SharpCompress.Compressors.Filters;

internal class BCJFilterPPC : Filter
{
private int _pos;

public BCJFilterPPC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;

protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;

for (i = offset; i <= end; i += 4)
{
if ((buffer[i] & 0xFC) == 0x48 && (buffer[i + 3] & 0x03) == 0x01)
{
int src =
((buffer[i] & 0x03) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFC);

int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}

buffer[i] = (byte)(0x48 | ((dest >>> 24) & 0x03));
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)((buffer[i + 3] & 0x03) | dest);
}
}

i -= offset;
_pos += i;
return i;
}
}
58 changes: 58 additions & 0 deletions src/SharpCompress/Compressors/Filters/BCJFilterSPARC.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.IO;

namespace SharpCompress.Compressors.Filters;

internal class BCJFilterSPARC : Filter
{
private int _pos;

public BCJFilterSPARC(bool isEncoder, Stream baseStream)
: base(isEncoder, baseStream, 4) => _pos = 0;

protected override int Transform(byte[] buffer, int offset, int count)
{
var end = offset + count - 4;
int i;

for (i = offset; i <= end; i += 4)
{
if (
(buffer[i] == 0x40 && (buffer[i + 1] & 0xC0) == 0x00)
|| (buffer[i] == 0x7F && (buffer[i + 1] & 0xC0) == 0xC0)
)
{
int src =
((buffer[i] & 0xFF) << 24)
| ((buffer[i + 1] & 0xFF) << 16)
| ((buffer[i + 2] & 0xFF) << 8)
| (buffer[i + 3] & 0xFF);
src <<= 2;

int dest;
if (_isEncoder)
{
dest = src + (_pos + i - offset);
}
else
{
dest = src - (_pos + i - offset);
}

dest >>>= 2;
dest =
(((0 - ((dest >>> 22) & 1)) << 22) & 0x3FFFFFFF)
| (dest & 0x3FFFFF)
| 0x40000000;

buffer[i] = (byte)(dest >>> 24);
buffer[i + 1] = (byte)(dest >>> 16);
buffer[i + 2] = (byte)(dest >>> 8);
buffer[i + 3] = (byte)dest;
}
}

i -= offset;
_pos += i;
return i;
}
}
15 changes: 15 additions & 0 deletions src/SharpCompress/Compressors/LZMA/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ internal static class DecoderRegistry
private const uint K_PPMD = 0x030401;
private const uint K_BCJ = 0x03030103;
private const uint K_BCJ2 = 0x0303011B;
private const uint K_PPC = 0x03030205;
private const uint K_IA64 = 0x03030401;
private const uint K_ARM = 0x03030501;
private const uint K_ARMT = 0x03030701;
private const uint K_SPARC = 0x03030805;
private const uint K_DEFLATE = 0x040108;
private const uint K_B_ZIP2 = 0x040202;
private const uint K_ZSTD = 0x4F71101;
Expand Down Expand Up @@ -51,6 +56,16 @@ long limit
return new BCJFilter(false, inStreams.Single());
case K_BCJ2:
return new Bcj2DecoderStream(inStreams, info, limit);
case K_PPC:
return new BCJFilterPPC(false, inStreams.Single());
case K_IA64:
return new BCJFilterIA64(false, inStreams.Single());
case K_ARM:
return new BCJFilterARM(false, inStreams.Single());
case K_ARMT:
return new BCJFilterARMT(false, inStreams.Single());
case K_SPARC:
return new BCJFilterSPARC(false, inStreams.Single());
case K_B_ZIP2:
return new BZip2Stream(inStreams.Single(), CompressionMode.Decompress, true);
case K_PPMD:
Expand Down
26 changes: 26 additions & 0 deletions tests/SharpCompress.Test/SevenZip/SevenZipArchiveTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Linq;
using SharpCompress.Common;
using SharpCompress.Readers;
using Xunit;
Expand Down Expand Up @@ -132,8 +133,33 @@ public void SevenZipArchive_ZSTD_Split() =>
)
);

[Fact]
public void SevenZipArchive_Delta_FileRead() => ArchiveFileRead("7Zip.delta.7z");

[Fact]
public void SevenZipArchive_ARM_FileRead() => ArchiveFileRead("7Zip.ARM.7z");

[Fact]
public void SevenZipArchive_ARMT_FileRead() => ArchiveFileRead("7Zip.ARMT.7z");

[Fact]
public void SevenZipArchive_BCJ_FileRead() => ArchiveFileRead("7Zip.BCJ.7z");

[Fact]
public void SevenZipArchive_BCJ2_FileRead() => ArchiveFileRead("7Zip.BCJ2.7z");

[Fact]
public void SevenZipArchive_IA64_FileRead() => ArchiveFileRead("7Zip.IA64.7z");

[Fact]
public void SevenZipArchive_PPC_FileRead() => ArchiveFileRead("7Zip.PPC.7z");

[Fact]
public void SevenZipArchive_SPARC_FileRead() => ArchiveFileRead("7Zip.SPARC.7z");

[Fact]
public void SevenZipArchive_Filters_FileRead() => ArchiveFileRead("7Zip.Filters.7z");

[Fact]
public void SevenZipArchive_Delta_Distance() =>
ArchiveDeltaDistanceRead("7Zip.delta.distance.7z");
Expand Down
Binary file added tests/TestArchives/Archives/7Zip.ARM.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.ARMT.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.BCJ.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.BCJ2.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.Filters.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.IA64.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.PPC.7z
Binary file not shown.
Binary file added tests/TestArchives/Archives/7Zip.SPARC.7z
Binary file not shown.