rar5: unpack work

This commit is contained in:
coderb
2017-12-18 11:01:37 -05:00
parent 122a732206
commit b8a308012f
8 changed files with 39 additions and 17 deletions

View File

@@ -20,10 +20,11 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017
{
partial class FragmentedWindow
{
public FragmentedWindow()
{
memset(Mem,0,sizeof(Mem));
memset(MemSize,0,sizeof(MemSize));
//memset(Mem,0,sizeof(Mem));
//memset(MemSize,0,sizeof(MemSize));
}
@@ -60,10 +61,10 @@ public void Init(size_t WinSize)
// smaller than some arbitrary constant.
size_t MinSize=Math.Max(Size/(ASIZE(Mem)-BlockNum), 0x400000);
byte *NewMem=null;
byte[] NewMem=null;
while (Size>=MinSize)
{
NewMem=(byte *)malloc(Size);
NewMem=new byte[Size];
if (NewMem!=null)
break;
Size-=Size/32;
@@ -73,7 +74,7 @@ public void Init(size_t WinSize)
// Clean the window to generate the same output when unpacking corrupt
// RAR files, which may access to unused areas of sliding dictionary.
memset(NewMem,0,Size);
Utility.Memset(NewMem,0,Size);
Mem[BlockNum]=NewMem;
TotalSize+=Size;

View File

@@ -13,6 +13,11 @@ namespace SharpCompress.Compressors.Rar.UnpackV2017
public void DoUnpack(FileHeader fileHeader, Stream readStream, Stream writeStream)
{
// as of 12/2017 .NET limits array indexing to using a signed integer
// MaxWinSize causes unpack to use a fragmented window when the file
// window size exceeds MaxWinSize
MaxWinSize = ((uint)int.MaxValue) + 1;
// may be long.MaxValue which could indicate unknown size (not present in header)
DestUnpSize = fileHeader.UncompressedSize;
this.fileHeader = fileHeader;

View File

@@ -198,7 +198,7 @@ bool ReadTables20()
UnpAudioBlock=(BitField & 0x8000)!=0;
if (!(BitField & 0x4000))
memset(UnpOldTable20,0,sizeof(UnpOldTable20));
Utility.Memset(UnpOldTable20,0,UnpOldTable20.Length);
Inp.addbits(2);
uint TableSize;

View File

@@ -671,7 +671,7 @@ bool ReadTables30()
LowDistRepCount=0;
if ((BitField & 0x4000) == 0)
memset(UnpOldTable,0,sizeof(UnpOldTable));
Utility.Memset(UnpOldTable,0,UnpOldTable.Length);
Inp.faddbits(2);
for (uint I=0;I<BC;I++)
@@ -766,7 +766,7 @@ void UnpInitData30(bool Solid)
if (!Solid)
{
TablesRead3=false;
memset(UnpOldTable,0,sizeof(UnpOldTable));
Utility.Memset(UnpOldTable,0,(uint)UnpOldTable.Length);
PPMEscChar=2;
UnpBlockType=BLOCK_LZ;
}

View File

@@ -128,7 +128,8 @@ void Init(size_t WinSize,bool Solid)
{
// Clean the window to generate the same output when unpacking corrupt
// RAR files, which may access unused areas of sliding dictionary.
memset(NewWindow,0,WinSize);
// sharpcompress: don't need this, freshly allocated above
//memset(NewWindow,0,WinSize);
// If Window is not NULL, it means that window size has grown.
@@ -139,8 +140,8 @@ void Init(size_t WinSize,bool Solid)
for (size_t I=1;I<=MaxWinSize;I++)
NewWindow[(UnpPtr-I)&(WinSize-1)]=Window[(UnpPtr-I)&(MaxWinSize-1)];
if (Window!=null)
free(Window);
//if (Window!=null)
// free(Window);
Window=NewWindow;
}

View File

@@ -34,3 +34,17 @@ The size_t type is the unsigned integer type that is the result of the sizeof op
so it is guaranteed to be big enough to contain the size of the biggest object your system can handle (e.g., a static array of 8Gb).
[size_t] -> ulong (x64)
[size_t] -> uint (x86)
size_t is an unsigned data type defined by several C/C++ standards, e.g. the C99 ISO/IEC 9899 standard, that is defined
in stddef.h.1 It can be further imported by inclusion of stdlib.h as this file internally sub includes stddef.h.
This type is used to represent the size of an object. Library functions that take or return sizes expect them to be of type or
have the return type of size_t. Further, the most frequently used compiler-based operator sizeof should evaluate to a constant
value that is compatible with size_t.
20171218
urggh, this allows things like new int[int.MaxValue] but NOT new byte[uint.MaxValue]
currently arrays are limited to being indexed by an int hence int.MaxValue entries. weak.
To get arrays > 2GB on x64 we need to configure
<gcAllowVeryLargeObjects enabled="true"/>
https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/gcallowverylargeobjects-element

View File

@@ -366,7 +366,7 @@ internal partial class Unpack
ModelPPM PPM;
int PPMEscChar;
byte UnpOldTable[HUFF_TABLE_SIZE30];
readonly byte [] UnpOldTable = new byte[HUFF_TABLE_SIZE30];
int UnpBlockType;
// If we already read decoding tables for Unpack v2,v3,v5.

View File

@@ -79,15 +79,15 @@ namespace SharpCompress
#if NET45
// super fast memset, up to 40x faster than for loop on large arrays
// see https://stackoverflow.com/questions/1897555/what-is-the-equivalent-of-memset-in-c
private static readonly Action<IntPtr, byte, int> MemsetDelegate = CreateMemsetDelegate();
private static readonly Action<IntPtr, byte, uint> MemsetDelegate = CreateMemsetDelegate();
private static Action<IntPtr, byte, int> CreateMemsetDelegate() {
private static Action<IntPtr, byte, uint> CreateMemsetDelegate() {
var dynamicMethod = new DynamicMethod(
"Memset",
MethodAttributes.Public | MethodAttributes.Static,
CallingConventions.Standard,
null,
new[] { typeof(IntPtr), typeof(byte), typeof(int) },
new[] { typeof(IntPtr), typeof(byte), typeof(uint) },
typeof(Utility),
true);
var generator = dynamicMethod.GetILGenerator();
@@ -96,13 +96,13 @@ namespace SharpCompress
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Initblk);
generator.Emit(OpCodes.Ret);
return (Action<IntPtr, byte, int>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, int>));
return (Action<IntPtr, byte, uint>)dynamicMethod.CreateDelegate(typeof(Action<IntPtr, byte, uint>));
}
public static void Memset(byte[] array, byte what, int length)
{
var gcHandle = GCHandle.Alloc(array, GCHandleType.Pinned);
MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, length);
MemsetDelegate(gcHandle.AddrOfPinnedObject(), what, (uint)length);
gcHandle.Free();
}
#else
@@ -115,6 +115,7 @@ namespace SharpCompress
}
#endif
/// <summary>
/// Fills the array with an specific value.
/// </summary>