Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/mpc-hc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXhmikosR <xhmikosr@users.sourceforge.net>2013-05-20 19:43:54 +0400
committerXhmikosR <xhmikosr@users.sourceforge.net>2013-05-20 19:46:10 +0400
commitae4d75d223b7de9d8edbaad1498740211c47a291 (patch)
treedffa8a3fde62fd655d798bd1bec40f1a2c9f951a /src/thirdparty/unrar
parent720ba19a3c00e4918b4bc05f5c657c8b6e9b4079 (diff)
Update Unrar to v5.0.4.
Diffstat (limited to 'src/thirdparty/unrar')
-rw-r--r--src/thirdparty/unrar/dll.rc8
-rw-r--r--src/thirdparty/unrar/loclang.hpp2
-rw-r--r--src/thirdparty/unrar/unpack.cpp70
-rw-r--r--src/thirdparty/unrar/unpack.hpp22
-rw-r--r--src/thirdparty/unrar/unpack50.cpp61
-rw-r--r--src/thirdparty/unrar/unpack50frag.cpp92
-rw-r--r--src/thirdparty/unrar/unpackinline.cpp4
-rw-r--r--src/thirdparty/unrar/version.hpp4
8 files changed, 220 insertions, 43 deletions
diff --git a/src/thirdparty/unrar/dll.rc b/src/thirdparty/unrar/dll.rc
index 3c0c6fce4..e8e8ad184 100644
--- a/src/thirdparty/unrar/dll.rc
+++ b/src/thirdparty/unrar/dll.rc
@@ -2,8 +2,8 @@
#include <commctrl.h>
VS_VERSION_INFO VERSIONINFO
-FILEVERSION 5, 0, 3, 860
-PRODUCTVERSION 5, 0, 3, 860
+FILEVERSION 5, 0, 4, 871
+PRODUCTVERSION 5, 0, 4, 871
FILEOS VOS__WINDOWS32
FILETYPE VFT_APP
{
@@ -14,8 +14,8 @@ FILETYPE VFT_APP
VALUE "CompanyName", "Alexander Roshal\0"
VALUE "ProductName", "RAR decompression library\0"
VALUE "FileDescription", "RAR decompression library\0"
- VALUE "FileVersion", "5.0.3\0"
- VALUE "ProductVersion", "5.0.3\0"
+ VALUE "FileVersion", "5.0.4\0"
+ VALUE "ProductVersion", "5.0.4\0"
VALUE "LegalCopyright", "Copyright © Alexander Roshal 1993-2013\0"
VALUE "OriginalFilename", "Unrar.dll\0"
}
diff --git a/src/thirdparty/unrar/loclang.hpp b/src/thirdparty/unrar/loclang.hpp
index 6941a3189..aa6b12f72 100644
--- a/src/thirdparty/unrar/loclang.hpp
+++ b/src/thirdparty/unrar/loclang.hpp
@@ -384,3 +384,5 @@
#define MErrCreateLnkS "\nCannot create symbolic link %s"
#define MErrCreateLnkH "\nCannot create hard link %s"
#define MNeedAdmin "\nYou may need to run RAR as administrator"
+#define MDictOutMem "\nNot enough memory for %d MB compression dictionary, changed to %d MB."
+#define MUseSmalllerDict "\nPlease use a smaller compression dictionary."
diff --git a/src/thirdparty/unrar/unpack.cpp b/src/thirdparty/unrar/unpack.cpp
index a20d37f9e..df9259c61 100644
--- a/src/thirdparty/unrar/unpack.cpp
+++ b/src/thirdparty/unrar/unpack.cpp
@@ -13,12 +13,14 @@
#endif
#include "unpack30.cpp"
#include "unpack50.cpp"
+#include "unpack50frag.cpp"
Unpack::Unpack(ComprDataIO *DataIO)
:Inp(true),VMCodeInp(true)
{
UnpIO=DataIO;
Window=NULL;
+ Fragmented=false;
Suspended=false;
UnpAllBuf=false;
UnpSomeRead=false;
@@ -30,6 +32,16 @@ Unpack::Unpack(ComprDataIO *DataIO)
#endif
MaxWinSize=0;
MaxWinMask=0;
+
+ // Perform initialization, which should be done only once for all files.
+ // It prevents crash if first DoUnpack call is later made with wrong
+ // (true) 'Solid' value.
+ UnpInitData(false);
+#ifndef SFX_MODULE
+ // RAR 1.5 decompression initialization
+ UnpInitData15(false);
+ InitHuff();
+#endif
}
@@ -37,7 +49,8 @@ Unpack::~Unpack()
{
InitFilters30();
- delete[] Window;
+ if (Window!=NULL)
+ free(Window);
#ifdef RAR_SMP
DestroyThreadPool(UnpThreadPool);
delete[] ReadBufMT;
@@ -48,17 +61,6 @@ Unpack::~Unpack()
void Unpack::Init(size_t WinSize,bool Solid)
{
- if (Window==NULL) // Perform initialization, which should be done only once for all files.
- {
- // Prevent crash if DoUnpack is later called with wrong 'Solid' value.
- UnpInitData(false);
-#ifndef SFX_MODULE
- // RAR 1.5 decompression initialization
- UnpInitData15(false);
- InitHuff();
-#endif
- }
-
// If 32-bit RAR unpacks an archive with 4 GB dictionary, the window size
// will be 0 because of size_t overflow. Let's issue the memory error.
if (WinSize==0)
@@ -83,23 +85,41 @@ void Unpack::Init(size_t WinSize,bool Solid)
// or increasing the size of non-solid window. So we could safely reject
// current window data without copying them to a new window, though being
// extra cautious, we still handle the solid window grow case below.
+ bool Grow=Solid && (Window!=NULL || Fragmented);
- byte *NewWindow=new byte[WinSize];
+ byte *NewWindow=(byte *)malloc(WinSize);
- // Clean the window to generate the same output when unpacking corrupt
- // RAR files, which may access to unused areas of sliding dictionary.
- memset(NewWindow,0,WinSize);
+ // We do not handle growth for fragmented window now.
+ if (Grow && (NewWindow==NULL || Fragmented))
+ throw std::bad_alloc();
- // If Window is not NULL, it means that window size has grown.
- // In solid streams we need to copy data to a new window in such case.
- // RAR archiving code does not allow it in solid streams now,
- // but let's implement it anyway just in case we'll change it sometimes.
- if (Solid && Window!=NULL)
- for (size_t I=1;I<MaxWinSize;I++)
- NewWindow[(UnpPtr-I)&(WinSize-1)]=Window[(UnpPtr-I)&(MaxWinSize-1)];
+ if (NewWindow==NULL)
+ if (WinSize<0x1000000) // Exclude RAR4 and small dictionaries.
+ throw std::bad_alloc();
+ else
+ {
+ FragWindow.Init(WinSize);
+ Fragmented=true;
+ }
- delete Window;
- Window=NewWindow;
+ if (!Fragmented)
+ {
+ // Clean the window to generate the same output when unpacking corrupt
+ // RAR files, which may access to unused areas of sliding dictionary.
+ memset(NewWindow,0,WinSize);
+
+ // If Window is not NULL, it means that window size has grown.
+ // In solid streams we need to copy data to a new window in such case.
+ // RAR archiving code does not allow it in solid streams now,
+ // but let's implement it anyway just in case we'll change it sometimes.
+ if (Grow)
+ for (size_t I=1;I<MaxWinSize;I++)
+ NewWindow[(UnpPtr-I)&(WinSize-1)]=Window[(UnpPtr-I)&(MaxWinSize-1)];
+
+ if (Window!=NULL)
+ free(Window);
+ Window=NewWindow;
+ }
MaxWinSize=WinSize;
MaxWinMask=MaxWinSize-1;
diff --git a/src/thirdparty/unrar/unpack.hpp b/src/thirdparty/unrar/unpack.hpp
index 87dfee2b4..2cd739722 100644
--- a/src/thirdparty/unrar/unpack.hpp
+++ b/src/thirdparty/unrar/unpack.hpp
@@ -165,6 +165,25 @@ struct AudioVariables // For RAR 2.0 archives only.
};
+// We can use the fragmented dictionary in case heap does not have the single
+// large enough memory block. It is slower than normal dictionary.
+class FragmentedWindow
+{
+ private:
+ enum {MAX_MEM_BLOCKS=32};
+ byte *Mem[MAX_MEM_BLOCKS];
+ size_t MemSize[MAX_MEM_BLOCKS];
+ public:
+ FragmentedWindow();
+ ~FragmentedWindow();
+ void Init(size_t WinSize);
+ byte& operator [](size_t Item);
+ void CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask);
+ void CopyData(byte *Dest,size_t WinPos,size_t Size);
+ size_t GetBlockSize(size_t StartPos,size_t RequiredSize);
+};
+
+
class Unpack
{
private:
@@ -237,6 +256,9 @@ class Unpack
byte *Window;
+ FragmentedWindow FragWindow;
+ bool Fragmented;
+
int64 DestUnpSize;
diff --git a/src/thirdparty/unrar/unpack50.cpp b/src/thirdparty/unrar/unpack50.cpp
index 989d15bd1..6132409b9 100644
--- a/src/thirdparty/unrar/unpack50.cpp
+++ b/src/thirdparty/unrar/unpack50.cpp
@@ -52,7 +52,10 @@ void Unpack::Unpack5(bool Solid)
uint MainSlot=DecodeNumber(Inp,&BlockTables.LD);
if (MainSlot<256)
{
- Window[UnpPtr++]=(byte)MainSlot;
+ if (Fragmented)
+ FragWindow[UnpPtr++]=(byte)MainSlot;
+ else
+ Window[UnpPtr++]=(byte)MainSlot;
continue;
}
if (MainSlot>=262)
@@ -103,7 +106,10 @@ void Unpack::Unpack5(bool Solid)
InsertOldDist(Distance);
LastLength=Length;
- CopyString(Length,Distance);
+ if (Fragmented)
+ FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
+ else
+ CopyString(Length,Distance);
continue;
}
if (MainSlot==256)
@@ -116,7 +122,10 @@ void Unpack::Unpack5(bool Solid)
if (MainSlot==257)
{
if (LastLength!=0)
- CopyString(LastLength,OldDist[0]);
+ if (Fragmented)
+ FragWindow.CopyString(LastLength,OldDist[0],UnpPtr,MaxWinMask);
+ else
+ CopyString(LastLength,OldDist[0]);
continue;
}
if (MainSlot<262)
@@ -130,7 +139,10 @@ void Unpack::Unpack5(bool Solid)
uint LengthSlot=DecodeNumber(Inp,&BlockTables.RD);
uint Length=SlotToLength(Inp,LengthSlot);
LastLength=Length;
- CopyString(Length,Distance);
+ if (Fragmented)
+ FragWindow.CopyString(Length,Distance,UnpPtr,MaxWinMask);
+ else
+ CopyString(Length,Distance);
continue;
}
}
@@ -286,12 +298,25 @@ void Unpack::UnpWriteBuf()
FilterSrcMemory.Alloc(BlockLength);
byte *Mem=&FilterSrcMemory[0];
if (BlockStart<BlockEnd || BlockEnd==0)
- memcpy(Mem,Window+BlockStart,BlockLength);
+ {
+ if (Fragmented)
+ FragWindow.CopyData(Mem,BlockStart,BlockLength);
+ else
+ memcpy(Mem,Window+BlockStart,BlockLength);
+ }
else
{
size_t FirstPartLength=size_t(MaxWinSize-BlockStart);
- memcpy(Mem,Window+BlockStart,FirstPartLength);
- memcpy(Mem+FirstPartLength,Window,BlockEnd);
+ if (Fragmented)
+ {
+ FragWindow.CopyData(Mem,BlockStart,FirstPartLength);
+ FragWindow.CopyData(Mem+FirstPartLength,0,BlockEnd);
+ }
+ else
+ {
+ memcpy(Mem,Window+BlockStart,FirstPartLength);
+ memcpy(Mem+FirstPartLength,Window,BlockEnd);
+ }
}
byte *OutMem=ApplyFilter(Mem,BlockLength,flt);
@@ -652,13 +677,27 @@ void Unpack::UnpWriteArea(size_t StartPtr,size_t EndPtr)
if (EndPtr!=StartPtr)
UnpSomeRead=true;
if (EndPtr<StartPtr)
- {
- UnpWriteData(&Window[StartPtr],-(int)StartPtr & MaxWinMask);
- UnpWriteData(Window,EndPtr);
UnpAllBuf=true;
+
+ if (Fragmented)
+ {
+ size_t SizeToWrite=(EndPtr-StartPtr) & MaxWinMask;
+ while (SizeToWrite>0)
+ {
+ size_t BlockSize=FragWindow.GetBlockSize(StartPtr,SizeToWrite);
+ UnpWriteData(&FragWindow[StartPtr],BlockSize);
+ SizeToWrite-=BlockSize;
+ StartPtr=(StartPtr+BlockSize) & MaxWinMask;
+ }
}
else
- UnpWriteData(&Window[StartPtr],EndPtr-StartPtr);
+ if (EndPtr<StartPtr)
+ {
+ UnpWriteData(Window+StartPtr,MaxWinSize-StartPtr);
+ UnpWriteData(Window,EndPtr);
+ }
+ else
+ UnpWriteData(Window+StartPtr,EndPtr-StartPtr);
}
diff --git a/src/thirdparty/unrar/unpack50frag.cpp b/src/thirdparty/unrar/unpack50frag.cpp
new file mode 100644
index 000000000..32c09b6fb
--- /dev/null
+++ b/src/thirdparty/unrar/unpack50frag.cpp
@@ -0,0 +1,92 @@
+FragmentedWindow::FragmentedWindow()
+{
+ memset(Mem,0,sizeof(Mem));
+ memset(MemSize,0,sizeof(MemSize));
+}
+
+
+FragmentedWindow::~FragmentedWindow()
+{
+ for (uint I=0;I<ASIZE(Mem);I++)
+ if (Mem[I]!=NULL)
+ free(Mem[I]);
+}
+
+
+void FragmentedWindow::Init(size_t WinSize)
+{
+ uint BlockNum=0;
+ size_t TotalSize=0; // Already allocated.
+ while (TotalSize<WinSize && BlockNum<ASIZE(Mem))
+ {
+ size_t Size=WinSize-TotalSize; // Size needed to allocate.
+
+ // Minimum still acceptable block size. Next allocations cannot be larger
+ // than current, so we do not need blocks if they are smaller than
+ // "size left / attempts left". Also we do not waste time to blocks
+ // smaller than some artbitrary constant.
+ size_t MinSize=Max(Size/(ASIZE(Mem)-BlockNum), 0x400000);
+
+ byte *NewMem=NULL;
+ while (Size>=MinSize)
+ {
+ NewMem=(byte *)malloc(Size);
+ if (NewMem!=NULL)
+ break;
+ Size-=Size/32;
+ }
+ if (NewMem==NULL)
+ throw std::bad_alloc();
+
+ // 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);
+
+ Mem[BlockNum]=NewMem;
+ TotalSize+=Size;
+ MemSize[BlockNum]=TotalSize;
+ BlockNum++;
+ }
+ if (TotalSize<WinSize) // Not found enough free blocks.
+ throw std::bad_alloc();
+}
+
+
+byte& FragmentedWindow::operator [](size_t Item)
+{
+ if (Item<MemSize[0])
+ return Mem[0][Item];
+ for (uint I=1;I<ASIZE(MemSize);I++)
+ if (Item<MemSize[I])
+ return Mem[I][Item-MemSize[I-1]];
+ return Mem[0][0]; // Must never happen;
+}
+
+
+void FragmentedWindow::CopyString(uint Length,uint Distance,size_t &UnpPtr,size_t MaxWinMask)
+{
+ size_t SrcPtr=UnpPtr-Distance;
+ while (Length-- > 0)
+ {
+ (*this)[UnpPtr]=(*this)[SrcPtr++ & MaxWinMask];
+ // We need to have masked UnpPtr after quit from loop, so it must not
+ // be replaced with '(*this)[UnpPtr++ & MaxWinMask]'
+ UnpPtr=(UnpPtr+1) & MaxWinMask;
+ }
+}
+
+
+void FragmentedWindow::CopyData(byte *Dest,size_t WinPos,size_t Size)
+{
+ for (size_t I=0;I<Size;I++)
+ Dest[I]=(*this)[WinPos+I];
+}
+
+
+size_t FragmentedWindow::GetBlockSize(size_t StartPos,size_t RequiredSize)
+{
+ for (uint I=0;I<ASIZE(MemSize);I++)
+ if (StartPos<MemSize[I])
+ return Min(MemSize[I]-StartPos,RequiredSize);
+ return 0; // Must never be here.
+}
diff --git a/src/thirdparty/unrar/unpackinline.cpp b/src/thirdparty/unrar/unpackinline.cpp
index 807c24ded..70b533dbb 100644
--- a/src/thirdparty/unrar/unpackinline.cpp
+++ b/src/thirdparty/unrar/unpackinline.cpp
@@ -64,9 +64,11 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance)
if (Length>6) { Dest[6]=Src[6]; } } } } } } } // Close all nested "if"s.
}
else
- while (Length--) // Slow copying with all possible precautions.
+ while (Length-- > 0) // Slow copying with all possible precautions.
{
Window[UnpPtr]=Window[SrcPtr++ & MaxWinMask];
+ // We need to have masked UnpPtr after quit from loop, so it must not
+ // be replaced with 'Window[UnpPtr++ & MaxWinMask]'
UnpPtr=(UnpPtr+1) & MaxWinMask;
}
}
diff --git a/src/thirdparty/unrar/version.hpp b/src/thirdparty/unrar/version.hpp
index 0e53da493..f34a08f54 100644
--- a/src/thirdparty/unrar/version.hpp
+++ b/src/thirdparty/unrar/version.hpp
@@ -1,6 +1,6 @@
#define RARVER_MAJOR 5
#define RARVER_MINOR 0
-#define RARVER_BETA 3
-#define RARVER_DAY 9
+#define RARVER_BETA 4
+#define RARVER_DAY 20
#define RARVER_MONTH 5
#define RARVER_YEAR 2013