mirror of
https://github.com/adamhathcock/sharpcompress.git
synced 2026-09-23 07:25:11 +00:00
BCJ executable filter (only for decoding), used by XZ.
This commit is contained in:
297
src/SharpCompress/Compressors/Filters/BranchExecFilter.cs
Normal file
297
src/SharpCompress/Compressors/Filters/BranchExecFilter.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* BranchExecFilter.cs -- Converters for executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Encoding
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SharpCompress.Compressors.Filters
|
||||
{
|
||||
[CLSCompliant(false)]
|
||||
public sealed class BranchExecFilter
|
||||
{
|
||||
public enum Alignment : int
|
||||
{
|
||||
ARCH_x86_ALIGNMENT = 1,
|
||||
ARCH_PowerPC_ALIGNMENT = 4,
|
||||
ARCH_IA64_ALIGNMENT = 16,
|
||||
ARCH_ARM_ALIGNMENT = 4,
|
||||
ARCH_ARMTHUMB_ALIGNMENT = 2,
|
||||
ARCH_SPARC_ALIGNMENT = 4,
|
||||
}
|
||||
|
||||
public static void X86Converter(byte[] data, UInt32 ip, ref UInt32 state) {
|
||||
|
||||
long i = 0;
|
||||
long size = data.Length;
|
||||
UInt32 pos = 0;
|
||||
UInt32 mask = state & 7;
|
||||
if (size < 5)
|
||||
return;
|
||||
size -= 4;
|
||||
ip += 5;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
i = pos;
|
||||
|
||||
for (; i < size; i++)
|
||||
{
|
||||
if ((data[i] & 0xFE) == 0xE8)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 d = (UInt32)(i) - pos;
|
||||
pos = (UInt32)i;
|
||||
if (i >= size)
|
||||
{
|
||||
state = (d > 2 ? 0 : mask >> (int)d);
|
||||
return;
|
||||
}
|
||||
if (d > 2)
|
||||
{
|
||||
mask = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mask >>= (int)d;
|
||||
if (mask != 0 && (mask > 4 || mask == 3 || (((((data[(UInt32)(mask >> 1) + 1])) + 1) & 0xFE) == 0) ))
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((((data[i + 4]) + 1) & 0xFE) == 0)
|
||||
{
|
||||
UInt32 inst = ((UInt32)data[i + 4] << 24) | ((UInt32)data[i + 3] << 16) | ((UInt32)data[i + 2] << 8) | ((UInt32)data[i + 1]);
|
||||
UInt32 cur = ip + (UInt32)pos;
|
||||
pos += 5;
|
||||
|
||||
inst -= cur;
|
||||
if (mask != 0)
|
||||
{
|
||||
UInt32 sh = (mask & 6) << 2;
|
||||
if (((((((Byte)(inst >> (int)sh))) + 1) & 0xFE) == 0))
|
||||
{
|
||||
inst ^= (((UInt32)0x100 << (int)sh) - 1);
|
||||
inst -= cur;
|
||||
}
|
||||
mask = 0;
|
||||
}
|
||||
data[i + 1] = (Byte)inst;
|
||||
data[i + 2] = (Byte)(inst >> 8);
|
||||
data[i + 3] = (Byte)(inst >> 16);
|
||||
data[i + 4] = (Byte)(0 - ((inst >> 24) & 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void PowerPCConverter(byte[] data, UInt32 ip)
|
||||
{
|
||||
long i = 0;
|
||||
long size = data.Length;
|
||||
size &= ~(UInt32)3;
|
||||
ip -= 4;
|
||||
|
||||
for (;; ) // infinite loop
|
||||
{
|
||||
for (;; ) // infinite loop
|
||||
{
|
||||
if (i >= size)
|
||||
return;
|
||||
i += 4;
|
||||
|
||||
if ((data[i - 4] & 0xFC) == 0x48 && (data[i - 1] & 3) == 1)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 inst = BitConverter.ToUInt32(data, (int)i - 4);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
inst = Utility.SwapUINT32(inst);
|
||||
}
|
||||
|
||||
inst -= (UInt32)(ip + i);
|
||||
inst &= 0x03FFFFFF;
|
||||
inst |= 0x48000000;
|
||||
|
||||
Utility.SetBigUInt32(ref data, inst, (i - 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void ARMConverter(byte[] data, UInt32 ip)
|
||||
{
|
||||
long i = 0;
|
||||
long size = data.Length;
|
||||
size &= ~(UInt32)3;
|
||||
ip += 4;
|
||||
|
||||
for (;;) // infinite loop
|
||||
{
|
||||
for (;;) // infinite loop
|
||||
{
|
||||
if (i >= size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
i += 4;
|
||||
if (data[i - 1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
|
||||
UInt32 inst = BitConverter.ToUInt32(data, (int)i - 4);
|
||||
inst <<= 2;
|
||||
inst -= (UInt32)(ip + i);
|
||||
inst >>= 2;
|
||||
inst &= 0x00FFFFFF;
|
||||
inst |= 0xEB000000;
|
||||
|
||||
Utility.SetLittleUInt32(ref data, inst, i - 4);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ARMTConverter(byte[] data, UInt32 ip)
|
||||
{
|
||||
long i = 0;
|
||||
long size = data.Length;
|
||||
size &= ~(UInt32)1;
|
||||
long lim = size - 4;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b1;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b3;
|
||||
if (i > lim)
|
||||
return;
|
||||
b1 = data[i + 1];
|
||||
b3 = data[i + 3];
|
||||
i += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
|
||||
UInt32 inst = ((UInt32)b1 << 19)
|
||||
+ (((UInt32)data[i + 1] & 0x7) << 8)
|
||||
+ (((UInt32)data[i - 2] << 11))
|
||||
+ (data[i]);
|
||||
|
||||
i += 2;
|
||||
|
||||
UInt32 cur = ((UInt32)(ip + i)) >> 1;
|
||||
inst -= cur;
|
||||
|
||||
|
||||
data[i - 4] = (Byte)(inst >> 11);
|
||||
data[i - 3] = (Byte)(0xF0 | ((inst >> 19) & 0x7));
|
||||
data[i - 2] = (Byte)inst;
|
||||
data[i - 1] = (Byte)(0xF8 | (inst >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
public static void IA64Converter(byte[] data, UInt32 ip)
|
||||
{
|
||||
UInt32 i = 0;
|
||||
long size = data.Length;
|
||||
if (size < 16)
|
||||
throw new InvalidDataException("Unexpected data size");
|
||||
size -= 16;
|
||||
|
||||
do
|
||||
{
|
||||
UInt32 m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3;
|
||||
if (m != 0)
|
||||
{
|
||||
m++;
|
||||
do
|
||||
{
|
||||
UInt32 iterator = (UInt32)( (i + (m * 5) - 8));
|
||||
if (((data[iterator + 3] >> (int)m) & 15) == 5
|
||||
&& (((data[iterator - 1] | ((UInt32)data[iterator] << 8)) >> (int)m) & 0x70) == 0)
|
||||
{
|
||||
UInt32 raw = BitConverter.ToUInt32(data, (int)iterator);
|
||||
UInt32 inst = raw >> (int)m;
|
||||
inst = (inst & 0xFFFFF) | ((inst & (1 << 23)) >> 3);
|
||||
|
||||
inst <<= 4;
|
||||
inst -= (ip + (UInt32)i);
|
||||
inst >>= 4;
|
||||
|
||||
inst &= 0x1FFFFF;
|
||||
inst += 0x700000;
|
||||
inst &= 0x8FFFFF;
|
||||
raw &= ~((UInt32)0x8FFFFF << (int)m);
|
||||
raw |= (inst << (int)m);
|
||||
|
||||
Utility.SetLittleUInt32(ref data, raw, iterator);
|
||||
}
|
||||
}
|
||||
while (++m <= 4);
|
||||
}
|
||||
i += 16;
|
||||
}
|
||||
while (i <= size);
|
||||
return;
|
||||
}
|
||||
|
||||
public static void SPARCConverter(byte[] data, UInt32 ip)
|
||||
{
|
||||
long i = 0;
|
||||
long size = data.Length;
|
||||
size &= ~(UInt32)3;
|
||||
ip -= 4;
|
||||
|
||||
for (;;) // infinite loop
|
||||
{
|
||||
for (;;) // infinite loop
|
||||
{
|
||||
if (i >= size)
|
||||
return;
|
||||
|
||||
i += 4;
|
||||
if ((data[i - 4] == 0x40 && (data[i - 3] & 0xC0) == 0) ||
|
||||
(data[i - 4] == 0x7F && (data[i - 3] >= 0xC0)))
|
||||
break;
|
||||
}
|
||||
|
||||
UInt32 inst = BitConverter.ToUInt32(data, (int)i - 4);
|
||||
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
inst = Utility.SwapUINT32(inst);
|
||||
}
|
||||
|
||||
inst <<= 2;
|
||||
inst -= (UInt32)(ip + i);
|
||||
|
||||
inst &= 0x01FFFFFF;
|
||||
inst -= (UInt32)1 << 24;
|
||||
inst ^= 0xFF000000;
|
||||
inst >>= 2;
|
||||
inst |= 0x40000000;
|
||||
|
||||
Utility.SetBigUInt32(ref data, inst, (i - 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
68
src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs
Normal file
68
src/SharpCompress/Compressors/Xz/Filters/ArmFilter.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* ArmFilter.cs -- XZ converter ARM executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class ArmFilter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties)
|
||||
{
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("ARM properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("ARM properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_ARM_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.ARMConverter(buffer, _ip);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override void SetBaseStream(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs
Normal file
69
src/SharpCompress/Compressors/Xz/Filters/ArmThumbFilter.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* ArmFThumbFilter.cs -- XZ converter ARMThumb executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class ArmThumbFilter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties)
|
||||
{
|
||||
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("ARM Thumb properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("ARM Thumb properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_ARMTHUMB_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.ARMTConverter(buffer, _ip);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override void SetBaseStream(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -20,6 +20,12 @@ namespace SharpCompress.Compressors.Xz.Filters
|
||||
|
||||
private static readonly Dictionary<FilterTypes, Type> FilterMap = new Dictionary<FilterTypes, Type>
|
||||
{
|
||||
{FilterTypes.ARCH_x86_FILTER, typeof(X86Filter) },
|
||||
{FilterTypes.ARCH_PowerPC_FILTER, typeof(PowerPCFilter) },
|
||||
{FilterTypes.ARCH_IA64_FILTER, typeof(IA64Filter) },
|
||||
{FilterTypes.ARCH_ARM_FILTER, typeof(ArmFilter) },
|
||||
{FilterTypes.ARCH_ARMTHUMB_FILTER, typeof(ArmThumbFilter) },
|
||||
{FilterTypes.ARCH_SPARC_FILTER, typeof(SparcFilter) },
|
||||
{FilterTypes.LZMA2, typeof(Lzma2Filter) }
|
||||
};
|
||||
|
||||
|
||||
67
src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs
Normal file
67
src/SharpCompress/Compressors/Xz/Filters/IA64Filter.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* IA64Filter.cs -- XZ converter IA64 executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class IA64Filter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties)
|
||||
{
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("IA64 properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("IA64 properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_IA64_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.IA64Converter(buffer, _ip);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
public override void SetBaseStream(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
66
src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs
Normal file
66
src/SharpCompress/Compressors/Xz/Filters/PowerPCFilter.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* PowerPCFilter.cs -- XZ converter PowerPC executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class PowerPCFilter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties)
|
||||
{
|
||||
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("PPC properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("PPC properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_PowerPC_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter() { }
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.PowerPCConverter(buffer, _ip);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override void SetBaseStream(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs
Normal file
65
src/SharpCompress/Compressors/Xz/Filters/SparcFilter.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* SparcFilter.cs -- XZ converter SPARC executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class SparcFilter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties) {
|
||||
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("SPARC properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("SPARC properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_SPARC_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter() {
|
||||
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count){
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.SPARCConverter(buffer, _ip);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override void SetBaseStream(Stream stream) {
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
70
src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs
Normal file
70
src/SharpCompress/Compressors/Xz/Filters/X86Filter.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* X86Filter.cs -- XZ converter x86 executable
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
* @TODO Properties offset
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using SharpCompress.Compressors.Filters;
|
||||
|
||||
namespace SharpCompress.Compressors.Xz.Filters
|
||||
{
|
||||
internal class X86Filter : BlockFilter
|
||||
{
|
||||
public override bool AllowAsLast => false;
|
||||
|
||||
public override bool AllowAsNonLast => true;
|
||||
|
||||
public override bool ChangesDataSize => false;
|
||||
|
||||
private UInt32 _ip = 0;
|
||||
|
||||
private UInt32 _state = 0;
|
||||
|
||||
//private UInt32 _offset = 0;
|
||||
|
||||
public override void Init(byte[] properties)
|
||||
{
|
||||
if (properties.Length != 0 && properties.Length != 4)
|
||||
{
|
||||
throw new InvalidDataException("X86 properties unexpected length");
|
||||
}
|
||||
|
||||
if (properties.Length == 4)
|
||||
{
|
||||
// Even XZ doesn't support it.
|
||||
throw new InvalidDataException("X86 properties offset is not supported");
|
||||
|
||||
//_offset = BitConverter.ToUInt32(properties, 0);
|
||||
//
|
||||
//if (_offset % (UInt32)BranchExec.Alignment.ARCH_x86_ALIGNMENT != 0)
|
||||
//{
|
||||
// throw new InvalidDataException("Filter offset does not match alignment");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ValidateFilter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count)
|
||||
{
|
||||
int bytesRead = BaseStream.Read(buffer, offset, count);
|
||||
BranchExecFilter.X86Converter(buffer, _ip, ref _state);
|
||||
_ip += (UInt32)bytesRead;
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
public override void SetBaseStream(Stream stream)
|
||||
{
|
||||
BaseStream = stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -315,5 +315,46 @@ namespace SharpCompress
|
||||
{
|
||||
return source.Replace('\0', ' ').Trim();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Swap the endianness of a UINT32
|
||||
/// </summary>
|
||||
/// <param name="number">The UINT32 you want to swap his endianness</param>
|
||||
/// <returns>Return the new UINT32 in the other endianness format</returns>
|
||||
public static UInt32 SwapUINT32(UInt32 number)
|
||||
{
|
||||
return (number >> 24) |
|
||||
((number << 8) & 0x00FF0000) |
|
||||
((number >> 8) & 0x0000FF00) |
|
||||
(number << 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Insert a little endian UINT32 into a byte array
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to insert into</param>
|
||||
/// <param name="number">The UINT32 to insert</param>
|
||||
/// <param name="offset">Offset of the buffer to insert into</param>
|
||||
public static void SetLittleUInt32(ref byte[] buffer, UInt32 number, long offset)
|
||||
{
|
||||
buffer[offset] = (byte)(number);
|
||||
buffer[offset + 1] = (byte)(number >> 8);
|
||||
buffer[offset + 2] = (byte)(number >> 16);
|
||||
buffer[offset + 3] = (byte)(number >> 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Insert a big endian UINT32 into a byte array
|
||||
/// </summary>
|
||||
/// <param name="buffer">The buffer to insert into</param>
|
||||
/// <param name="number">The UINT32 to insert</param>
|
||||
/// <param name="offset">Offset of the buffer to insert into</param>
|
||||
public static void SetBigUInt32(ref byte[] buffer, UInt32 number, long offset)
|
||||
{
|
||||
buffer[offset] = (byte)(number >> 24);
|
||||
buffer[offset + 1] = (byte)(number >> 16);
|
||||
buffer[offset + 2] = (byte)(number >> 8);
|
||||
buffer[offset + 3] = (byte)number;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
157
tests/SharpCompress.Test/Filters/BranchExecTests.cs
Normal file
157
tests/SharpCompress.Test/Filters/BranchExecTests.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* BranchExecTests.cs -- Test for converters
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
*
|
||||
* All data is extracted from busybox, where "ip" is the offset within the busybox file.
|
||||
*/
|
||||
|
||||
using SharpCompress.Compressors.Filters;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Filters
|
||||
{
|
||||
public class BranchExecTests
|
||||
{
|
||||
private static byte[] x86resultData { get; } = new byte[] {
|
||||
0x12, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x00, 0x00, 0xE8, 0xBD, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, 0xF0, 0xCA,
|
||||
0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0x14, 0xC2, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x98, 0x0B, 0x00, 0x00, 0x60, 0x75, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xF1, 0xFF, 0x42, 0x01, 0x00, 0x00, 0x08, 0xC8, 0x00, 0x00, 0x1C, 0x00,
|
||||
};
|
||||
|
||||
private static byte[] x86Data { get; } = new byte[] {
|
||||
0x12, 0x00, 0x00, 0x00, 0x02, 0x0B, 0x00, 0x00, 0xE8, 0xCA, 0x20, 0x00, 0x00, 0x07, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x6D, 0x01, 0x00, 0x00, 0xF0, 0xCA,
|
||||
0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0xBC, 0x09, 0x00, 0x00, 0x14, 0xC2, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
|
||||
0x98, 0x0B, 0x00, 0x00, 0x60, 0x75, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xF1, 0xFF, 0x42, 0x01, 0x00, 0x00, 0x08, 0xC8, 0x00, 0x00, 0x1C, 0x00,
|
||||
};
|
||||
|
||||
private static byte[] ppcResultData { get; } = new byte[] {
|
||||
0xF8, 0x6B, 0x2E, 0x8C, 0x95, 0xC5, 0x4B, 0x1B, 0x94, 0x78, 0x9E, 0x7C, 0xBD, 0x8B, 0xA8, 0xAF, 0x31, 0x20, 0xFE, 0x0F, 0xB3, 0x15, 0x9A, 0x7C, 0xD5, 0x5C,
|
||||
0xC2, 0xC0, 0xEC, 0xE9, 0x43, 0x2B, 0xD0, 0x9F, 0x2C, 0xFC, 0xB8, 0x2B, 0x6B, 0x15, 0xCD, 0x3F, 0x0C, 0xAF, 0x8F, 0x68, 0xB0, 0x6E, 0x6B, 0x30, 0x2E, 0x8C,
|
||||
0x3F, 0x7E, 0x96, 0x7C, 0x93, 0xB2, 0xA4, 0x0E, 0x43, 0xEA, 0x20, 0x10, 0x38, 0x6D, 0x37, 0xF8, 0x87, 0xFE, 0xA9, 0x63, 0x75, 0xF5, 0x56, 0x34, 0x4A, 0xE3,
|
||||
0xCF, 0x89, 0x18, 0x08, 0xC2, 0x76, 0x74, 0x12, 0xEC, 0xA7, 0x6D, 0xC2, 0xB7, 0x1B, 0x7A, 0xB2, 0xD4, 0xED
|
||||
};
|
||||
|
||||
private static byte[] ppcData { get; } = new byte[] {
|
||||
0xF8, 0x6B, 0x2E, 0x8C, 0x95, 0xC5, 0x4B, 0x1B, 0x94, 0x78, 0x9E, 0x7C, 0xBD, 0x8B, 0xA8, 0xAF, 0x31, 0x20, 0xFE, 0x0F, 0xB3, 0x15, 0x9A, 0x7C, 0xD5, 0x5C,
|
||||
0xC2, 0xC0, 0xEC, 0xE9, 0x43, 0x2B, 0xD0, 0x9F, 0x2C, 0xFC, 0xB8, 0x2B, 0x6B, 0x15, 0xCD, 0x3F, 0x0C, 0xAF, 0x8F, 0x68, 0xB0, 0x6E, 0x6B, 0x30, 0x2E, 0x8C,
|
||||
0x3F, 0x7E, 0x96, 0x7C, 0x93, 0xB2, 0xA4, 0x0E, 0x43, 0xEA, 0x20, 0x10, 0x38, 0x6D, 0x37, 0xF8, 0x87, 0xFE, 0xA9, 0x63, 0x75, 0xF5, 0x56, 0x34, 0x4A, 0xE3,
|
||||
0xD6, 0x75, 0x18, 0x08, 0xC2, 0x76, 0x74, 0x12, 0xEC, 0xA7, 0x6D, 0xC2, 0xB7, 0x1B, 0x7A, 0xB2, 0xD4, 0xED
|
||||
};
|
||||
|
||||
private static byte[] armResultData { get; } = new byte[] {
|
||||
0x7C, 0xFC, 0x0A, 0x00, 0x16, 0x42, 0x01, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x16, 0xB8, 0x00, 0x00, 0x84, 0xFC, 0x0A, 0x00, 0x16, 0x3A, 0x00, 0x00, 0x04, 0xE0,
|
||||
0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0x0E, 0x04, 0x00, 0xEB, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0xE0, 0x2D, 0xE5,
|
||||
0x04, 0xE0, 0x9F, 0xE5, 0x0E, 0xE0, 0x8F, 0xE0, 0x08, 0xF0, 0xBE, 0xE5, 0xF0, 0x3A, 0x0A, 0x00, 0x00, 0xC6, 0x8F, 0xE2, 0xA3, 0xCA, 0x8C, 0xE2, 0xF0, 0xFA,
|
||||
0xBC, 0xE5, 0x00, 0xC6, 0x8F, 0xE2, 0xA3, 0xCA, 0x8C, 0xE2, 0xE8, 0xFA, 0xBC, 0xE5, 0x00, 0xC6, 0x8F, 0xE2
|
||||
};
|
||||
|
||||
private static byte[] armData { get; } = new byte[] {
|
||||
0x7C, 0xFC, 0x0A, 0x00, 0x16, 0x42, 0x01, 0x00, 0x80, 0xFC, 0x0A, 0x00, 0x16, 0xB8, 0x00, 0x00, 0x84, 0xFC, 0x0A, 0x00, 0x16, 0x3A, 0x00, 0x00, 0x04, 0xE0,
|
||||
0x2D, 0xE5, 0x04, 0xD0, 0x4D, 0xE2, 0x18, 0x13, 0x00, 0xEB, 0x04, 0xD0, 0x8D, 0xE2, 0x04, 0xE0, 0x9D, 0xE4, 0x1E, 0xFF, 0x2F, 0xE1, 0x04, 0xE0, 0x2D, 0xE5,
|
||||
0x04, 0xE0, 0x9F, 0xE5, 0x0E, 0xE0, 0x8F, 0xE0, 0x08, 0xF0, 0xBE, 0xE5, 0xF0, 0x3A, 0x0A, 0x00, 0x00, 0xC6, 0x8F, 0xE2, 0xA3, 0xCA, 0x8C, 0xE2, 0xF0, 0xFA,
|
||||
0xBC, 0xE5, 0x00, 0xC6, 0x8F, 0xE2, 0xA3, 0xCA, 0x8C, 0xE2, 0xE8, 0xFA, 0xBC, 0xE5, 0x00, 0xC6, 0x8F, 0xE2
|
||||
};
|
||||
|
||||
private static byte[] armtResultData { get; } = new byte[] {
|
||||
0x95, 0x23, 0xB6, 0xB1, 0xBE, 0x60, 0x79, 0xF0, 0xF6, 0x01, 0xD9, 0x7F, 0x2E, 0x03, 0x31, 0x1C, 0xFD, 0xD3, 0x40, 0x0F, 0x21, 0x3C, 0x06, 0x97, 0xE5, 0xC3,
|
||||
0x57, 0x11, 0x76, 0x6F, 0xE3, 0x70, 0xED, 0x49, 0xCB, 0xB5, 0xC9, 0x42, 0x59, 0x10, 0x2F, 0xBD, 0xAE, 0xB1, 0x40, 0x4D, 0x9D, 0x7C, 0xE9, 0xFC, 0x48, 0x3E,
|
||||
0xBC, 0x7F, 0x0B, 0x23, 0xB0, 0x8A, 0x4D, 0x02, 0x39, 0xC4, 0xFB, 0x66, 0x83, 0x7F, 0xA7, 0xBD, 0x12, 0xAC, 0xED, 0x31, 0x34, 0x93, 0x4D, 0x8D, 0xD7, 0x94,
|
||||
0x93, 0x1C, 0x0A, 0x50, 0x54, 0x4B, 0x03, 0x55, 0x27, 0xFE, 0xCE, 0x29, 0x66, 0x52, 0x81, 0xAE, 0x69, 0xA0, 0x69, 0xF2, 0x3D, 0xFF, 0xA1, 0x8A, 0x5D, 0x61,
|
||||
0x7D, 0xC5, 0x94, 0x0A, 0x7D, 0xED, 0x11, 0x0F
|
||||
};
|
||||
|
||||
private static byte[] armtData { get; } = new byte[] {
|
||||
0x95, 0x23, 0xB6, 0xB1, 0xBE, 0x60, 0x79, 0xF0, 0xF6, 0x01, 0xD9, 0x7F, 0x2E, 0x03, 0x31, 0x1C, 0xFD, 0xD3, 0x40, 0x0F, 0x21, 0x3C, 0x06, 0x97, 0xE5, 0xC3,
|
||||
0x57, 0x11, 0x76, 0x6F, 0xE3, 0x70, 0xED, 0x49, 0xCB, 0xB5, 0xC9, 0x42, 0x59, 0x10, 0x2F, 0xBD, 0xAE, 0xB1, 0x40, 0x4D, 0x9D, 0x7C, 0xE9, 0xFC, 0x48, 0x3E,
|
||||
0xBC, 0x7F, 0x0B, 0x23, 0xB0, 0x8A, 0x4D, 0x02, 0x39, 0xC4, 0xFB, 0x66, 0x83, 0x7F, 0xA7, 0xBD, 0x12, 0xAC, 0xED, 0x31, 0x34, 0x93, 0x4D, 0x8D, 0xD7, 0x94,
|
||||
0x93, 0x1C, 0x0A, 0x50, 0x54, 0x4B, 0x03, 0x55, 0x27, 0xFE, 0xCE, 0x29, 0x66, 0x52, 0x81, 0xAE, 0x69, 0xA0, 0x6A, 0xF2, 0x6F, 0xFC, 0xA1, 0x8A, 0x5D, 0x61,
|
||||
0x7D, 0xC5, 0x94, 0x0A, 0x7D, 0xED, 0x11, 0x0F
|
||||
};
|
||||
|
||||
private static byte[] ia64ResultData { get; } = new byte[] {
|
||||
0x4D, 0xF8, 0xF2, 0x0D, 0x06, 0x2F, 0x74, 0x0F, 0xF0, 0x91, 0x06, 0x0B, 0x19, 0x22, 0x91, 0x5A, 0x66, 0x56, 0xA7, 0x15, 0x77, 0x1E, 0x2F, 0xA3, 0xE4, 0xDE,
|
||||
0x93, 0x1C, 0xD5, 0xCE, 0x6E, 0x45, 0x36, 0x15, 0x15, 0x65, 0x4E, 0xC5, 0xA3, 0x8C, 0x5A, 0x8B, 0x8A, 0x1C, 0x12, 0x5B, 0x39, 0x1F, 0xA0, 0xF2, 0x93, 0x7C,
|
||||
0x7F, 0x5D, 0xD9, 0x30, 0x1F, 0xF6, 0x5C, 0x10, 0x62, 0x3E, 0xB4, 0x64, 0x56, 0x48, 0xB2, 0x20, 0x39, 0xE8, 0x44, 0x10, 0x87, 0x9E, 0x2C, 0xFC, 0x29, 0x0E,
|
||||
0x20, 0x76, 0xCE, 0xDA, 0x93, 0x1C, 0xED, 0x54, 0x0D, 0xAF, 0xEC, 0xDE, 0x93, 0x1C, 0x2B, 0x72, 0xD5, 0x0D
|
||||
};
|
||||
|
||||
private static byte[] ia64Data { get; } = new byte[] {
|
||||
0x4D, 0xF8, 0xF2, 0x0D, 0x06, 0x2F, 0x74, 0x0F, 0xF0, 0x91, 0x06, 0x0B, 0x19, 0x22, 0x91, 0x5A, 0x66, 0x56, 0xA7, 0x15, 0x77, 0x1E, 0x2F, 0xA3, 0xE4, 0xDE,
|
||||
0x93, 0x1C, 0xD5, 0xCE, 0x6E, 0x45, 0x36, 0x15, 0x15, 0x65, 0x4E, 0xC5, 0xA3, 0x8C, 0x5A, 0x8B, 0x8A, 0x1C, 0x12, 0x5B, 0x39, 0x1F, 0xA0, 0xF2, 0x93, 0x7C,
|
||||
0x7F, 0x5D, 0xD9, 0x30, 0x1F, 0xF6, 0x5C, 0x10, 0x62, 0x3E, 0xB4, 0x64, 0x56, 0x48, 0xB2, 0x20, 0x39, 0xE8, 0x44, 0x80, 0x8C, 0x9E, 0x2C, 0xFC, 0x29, 0x0E,
|
||||
0x20, 0x76, 0xCE, 0xDA, 0x93, 0x1C, 0xED, 0x54, 0x0D, 0xAF, 0xEC, 0xDE, 0x93, 0x1C, 0x2B, 0x72, 0xD5, 0x0D
|
||||
};
|
||||
|
||||
private static byte[] sparcResultData { get; } = new byte[] {
|
||||
0x78, 0x2E, 0x73, 0x6F, 0x2E, 0x33, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0xA2, 0x0D,
|
||||
0x10, 0x12, 0x30, 0x03, 0xC9, 0x37, 0x40, 0x1A, 0x85, 0xD9, 0x44, 0x34, 0x40, 0x32, 0x85, 0xA0, 0x30, 0x40, 0x00, 0x70, 0x00, 0x40, 0x84, 0x80, 0x04, 0x00,
|
||||
0xE4, 0xAC, 0x07, 0x04, 0x21, 0x44, 0x02, 0x20, 0x10, 0x00, 0x40, 0xC2, 0x89, 0x98, 0x85, 0x00, 0x58, 0x6A, 0x41, 0x8E, 0x18, 0xA1, 0x91, 0x00, 0x10, 0x00,
|
||||
};
|
||||
|
||||
private static byte[] sparcData { get; } = new byte[] {
|
||||
0x78, 0x2E, 0x73, 0x6F, 0x2E, 0x33, 0x00, 0x00, 0x07, 0x01, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x44, 0x0B, 0x00, 0x00, 0x00, 0xA2, 0x0D,
|
||||
0x10, 0x12, 0x30, 0x03, 0xC9, 0x37, 0x40, 0x1A, 0x86, 0x21, 0x44, 0x34, 0x40, 0x32, 0x85, 0xA0, 0x30, 0x40, 0x00, 0x70, 0x00, 0x40, 0x84, 0x80, 0x04, 0x00,
|
||||
0xE4, 0xAC, 0x07, 0x04, 0x21, 0x44, 0x02, 0x20, 0x10, 0x00, 0x40, 0xC2, 0x89, 0x98, 0x85, 0x00, 0x58, 0x6A, 0x41, 0x8E, 0x18, 0xA1, 0x91, 0x00, 0x10, 0x00,
|
||||
};
|
||||
|
||||
private void CompareBuffer(byte[] testBuffer, byte[] targetBuffer)
|
||||
{
|
||||
Assert.Equal(testBuffer, targetBuffer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void X86ConverterDecodeTest()
|
||||
{
|
||||
uint state = 0;
|
||||
uint ip = 0x2000;
|
||||
var testData = x86Data;
|
||||
BranchExecFilter.X86Converter(testData, ip, ref state);
|
||||
CompareBuffer(testData, x86resultData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PowerPCConverterDecodeTest()
|
||||
{
|
||||
uint ip = 0x6A0;
|
||||
var testData = ppcData;
|
||||
BranchExecFilter.PowerPCConverter(testData, ip);
|
||||
CompareBuffer(testData, ppcResultData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ARMConverteDecoderTest()
|
||||
{
|
||||
uint ip = 0x3C00;
|
||||
var testData = armData;
|
||||
BranchExecFilter.ARMConverter(testData, ip);
|
||||
CompareBuffer(testData, armResultData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ARMTConverterDecodeTest()
|
||||
{
|
||||
uint ip = 0xA00;
|
||||
var testData = armtData;
|
||||
BranchExecFilter.ARMTConverter(testData, ip);
|
||||
CompareBuffer(testData, armtResultData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IA64ConverterDecodeTest()
|
||||
{
|
||||
uint ip = 0xAA0;
|
||||
var testData = ia64Data;
|
||||
BranchExecFilter.IA64Converter(testData, ip);
|
||||
CompareBuffer(testData, ia64ResultData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SPARCConverterDecodeTest()
|
||||
{
|
||||
uint ip = 0x100;
|
||||
var testData = sparcData;
|
||||
BranchExecFilter.SPARCConverter(testData, ip);
|
||||
CompareBuffer(testData, sparcResultData);
|
||||
}
|
||||
}
|
||||
}
|
||||
88
tests/SharpCompress.Test/Xz/Filters/BCJTests.cs
Normal file
88
tests/SharpCompress.Test/Xz/Filters/BCJTests.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* BCJTests.cs -- XZ converter test class
|
||||
* <Contribution by Louis-Michel Bergeron, on behalf of aDolus Technolog Inc., 2022>
|
||||
*/
|
||||
|
||||
using System.IO;
|
||||
using SharpCompress.Compressors.Xz.Filters;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpCompress.Test.Xz.Filters
|
||||
{
|
||||
public class BCJTests : XZTestsBase
|
||||
{
|
||||
private readonly ArmFilter armFilter;
|
||||
private readonly ArmThumbFilter armtFilter;
|
||||
private readonly IA64Filter ia64Filter;
|
||||
private readonly PowerPCFilter ppcFilter;
|
||||
private readonly SparcFilter sparcFilter;
|
||||
private readonly X86Filter x86Filter;
|
||||
public BCJTests()
|
||||
{
|
||||
armFilter = new ArmFilter();
|
||||
armtFilter = new ArmThumbFilter();
|
||||
ia64Filter = new IA64Filter();
|
||||
ppcFilter = new PowerPCFilter();
|
||||
sparcFilter = new SparcFilter();
|
||||
x86Filter = new X86Filter();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsOnlyAllowedLast()
|
||||
{
|
||||
Assert.False(armFilter.AllowAsLast);
|
||||
Assert.True(armFilter.AllowAsNonLast);
|
||||
|
||||
Assert.False(armtFilter.AllowAsLast);
|
||||
Assert.True(armtFilter.AllowAsNonLast);
|
||||
|
||||
Assert.False(ia64Filter.AllowAsLast);
|
||||
Assert.True(ia64Filter.AllowAsNonLast);
|
||||
|
||||
Assert.False(ppcFilter.AllowAsLast);
|
||||
Assert.True(ppcFilter.AllowAsNonLast);
|
||||
|
||||
Assert.False(sparcFilter.AllowAsLast);
|
||||
Assert.True(sparcFilter.AllowAsNonLast);
|
||||
|
||||
Assert.False(x86Filter.AllowAsLast);
|
||||
Assert.True(x86Filter.AllowAsNonLast);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChangesStreamSize()
|
||||
{
|
||||
Assert.False(armFilter.ChangesDataSize);
|
||||
Assert.False(armtFilter.ChangesDataSize);
|
||||
Assert.False(ia64Filter.ChangesDataSize);
|
||||
Assert.False(ppcFilter.ChangesDataSize);
|
||||
Assert.False(sparcFilter.ChangesDataSize);
|
||||
Assert.False(x86Filter.ChangesDataSize);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[] { 0 })]
|
||||
[InlineData(new byte[] { 0, 0, 0, 0, 0 })]
|
||||
public void OnlyAcceptsOneByte(byte[] bytes)
|
||||
{
|
||||
InvalidDataException ex;
|
||||
ex = Assert.Throws<InvalidDataException>(() => armFilter.Init(bytes));
|
||||
Assert.Equal("ARM properties unexpected length", ex.Message);
|
||||
|
||||
ex = Assert.Throws<InvalidDataException>(() => armtFilter.Init(bytes));
|
||||
Assert.Equal("ARM Thumb properties unexpected length", ex.Message);
|
||||
|
||||
ex = Assert.Throws<InvalidDataException>(() => ia64Filter.Init(bytes));
|
||||
Assert.Equal("IA64 properties unexpected length", ex.Message);
|
||||
|
||||
ex = Assert.Throws<InvalidDataException>(() => ppcFilter.Init(bytes));
|
||||
Assert.Equal("PPC properties unexpected length", ex.Message);
|
||||
|
||||
ex = Assert.Throws<InvalidDataException>(() => sparcFilter.Init(bytes));
|
||||
Assert.Equal("SPARC properties unexpected length", ex.Message);
|
||||
|
||||
ex = Assert.Throws<InvalidDataException>(() => x86Filter.Init(bytes));
|
||||
Assert.Equal("X86 properties unexpected length", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user