Skip to content

Commit 1d18428

Browse files
Update unrar from 5.21 to 5.71 (#920)
1 parent 492f29e commit 1d18428

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+4243
-5926
lines changed

vendor/unrar/arccmt.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
77
SaveFilePos SavePos(*this);
88

99
#ifndef SFX_MODULE
10-
ushort CmtLength;
10+
uint CmtLength;
1111
if (Format==RARFMT14)
1212
{
1313
Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
@@ -22,7 +22,8 @@ bool Archive::GetComment(Array<wchar> *CmtData)
2222
// Old style (RAR 2.9) archive comment embedded into the main
2323
// archive header.
2424
Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
25-
ReadHeader();
25+
if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
26+
return false;
2627
}
2728
else
2829
{
@@ -33,7 +34,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
3334
#ifndef SFX_MODULE
3435
// Old style (RAR 2.9) comment header embedded into the main
3536
// archive header.
36-
if (BrokenHeader)
37+
if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
3738
{
3839
uiMsg(UIERROR_CMTBROKEN,FileName);
3940
return false;
@@ -45,17 +46,19 @@ bool Archive::GetComment(Array<wchar> *CmtData)
4546
if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
4647
{
4748
if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
48-
return(false);
49+
return false;
4950
ComprDataIO DataIO;
5051
DataIO.SetTestMode(true);
5152
uint UnpCmtLength;
5253
if (Format==RARFMT14)
5354
{
5455
#ifdef RAR_NOCRYPT
55-
return(false);
56+
return false;
5657
#else
5758
UnpCmtLength=GetByte();
5859
UnpCmtLength+=(GetByte()<<8);
60+
if (CmtLength<2)
61+
return false;
5962
CmtLength-=2;
6063
DataIO.SetCmt13Encryption();
6164
CommHead.UnpVer=15;
@@ -67,6 +70,7 @@ bool Archive::GetComment(Array<wchar> *CmtData)
6770
DataIO.EnableShowProgress(false);
6871
DataIO.SetPackedSizeToRead(CmtLength);
6972
DataIO.UnpHash.Init(HASH_CRC32,1);
73+
DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
7074

7175
Unpack CmtUnpack(&DataIO);
7276
CmtUnpack.Init(0x10000,false);
@@ -83,19 +87,31 @@ bool Archive::GetComment(Array<wchar> *CmtData)
8387
byte *UnpData;
8488
size_t UnpDataSize;
8589
DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
90+
if (UnpDataSize>0)
91+
{
8692
#ifdef _WIN_ALL
87-
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
93+
// If we ever decide to extend it to Android, we'll need to alloc
94+
// 4x memory for OEM to UTF-8 output here.
95+
OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
8896
#endif
89-
CmtData->Alloc(UnpDataSize+1);
90-
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
91-
CharToWide((char *)UnpData,CmtData->Addr(0),UnpDataSize);
92-
CmtData->Alloc(wcslen(CmtData->Addr(0)));
97+
CmtData->Alloc(UnpDataSize+1);
98+
memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
99+
CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
100+
CmtData->Alloc(wcslen(CmtData->Addr(0)));
101+
}
93102
}
94103
}
95104
else
96105
{
106+
if (CmtLength==0)
107+
return false;
97108
Array<byte> CmtRaw(CmtLength);
98-
Read(&CmtRaw[0],CmtLength);
109+
int ReadSize=Read(&CmtRaw[0],CmtLength);
110+
if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
111+
{
112+
CmtLength=ReadSize;
113+
CmtRaw.Alloc(CmtLength);
114+
}
99115

100116
if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
101117
{
@@ -105,9 +121,11 @@ bool Archive::GetComment(Array<wchar> *CmtData)
105121
CmtData->Alloc(CmtLength+1);
106122
CmtRaw.Push(0);
107123
#ifdef _WIN_ALL
124+
// If we ever decide to extend it to Android, we'll need to alloc
125+
// 4x memory for OEM to UTF-8 output here.
108126
OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
109127
#endif
110-
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength);
128+
CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
111129
CmtData->Alloc(wcslen(CmtData->Addr(0)));
112130
}
113131
#endif
@@ -143,11 +161,10 @@ bool Archive::ReadCommentData(Array<wchar> *CmtData)
143161

144162
void Archive::ViewComment()
145163
{
146-
#ifndef GUI
147164
if (Cmd->DisableComment)
148165
return;
149166
Array<wchar> CmtBuf;
150-
if (GetComment(&CmtBuf))
167+
if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
151168
{
152169
size_t CmtSize=CmtBuf.Size();
153170
wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
@@ -156,7 +173,6 @@ void Archive::ViewComment()
156173
mprintf(L"\n");
157174
OutComment(&CmtBuf[0],CmtSize);
158175
}
159-
#endif
160176
}
161177

162178

vendor/unrar/archive.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
#include "rar.hpp"
22

3-
#ifndef SHELL_EXT
43
#include "arccmt.cpp"
5-
#endif
64

75

86
Archive::Archive(RAROptions *InitCmd)
@@ -32,8 +30,6 @@ Archive::Archive(RAROptions *InitCmd)
3230
CurBlockPos=0;
3331
NextBlockPos=0;
3432

35-
RecoverySize=-1;
36-
RecoveryPercent=-1;
3733

3834
memset(&MainHead,0,sizeof(MainHead));
3935
memset(&CryptHead,0,sizeof(CryptHead));
@@ -50,6 +46,10 @@ Archive::Archive(RAROptions *InitCmd)
5046

5147
SilentOpen=false;
5248

49+
#ifdef USE_QOPEN
50+
ProhibitQOpen=false;
51+
#endif
52+
5353
}
5454

5555

@@ -60,7 +60,6 @@ Archive::~Archive()
6060
}
6161

6262

63-
#ifndef SHELL_EXT
6463
void Archive::CheckArc(bool EnableBroken)
6564
{
6665
if (!IsArchive(EnableBroken))
@@ -72,10 +71,9 @@ void Archive::CheckArc(bool EnableBroken)
7271
ErrHandler.Exit(RARX_FATAL);
7372
}
7473
}
75-
#endif
7674

7775

78-
#if !defined(SHELL_EXT) && !defined(SFX_MODULE)
76+
#if !defined(SFX_MODULE)
7977
void Archive::CheckOpen(const wchar *Name)
8078
{
8179
TOpen(Name);
@@ -109,16 +107,16 @@ RARFORMAT Archive::IsSignature(const byte *D,size_t Size)
109107
#endif
110108
if (Size>=7 && D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07)
111109
{
112-
// We check for non-zero last signature byte, so we can return
113-
// a sensible warning in case we'll want to change the archive
114-
// format sometimes in the future.
110+
// We check the last signature byte, so we can return a sensible
111+
// warning in case we'll want to change the archive format
112+
// sometimes in the future.
115113
if (D[6]==0)
116114
Type=RARFMT15;
117115
else
118116
if (D[6]==1)
119117
Type=RARFMT50;
120118
else
121-
if (D[6]==2)
119+
if (D[6]>1 && D[6]<5)
122120
Type=RARFMT_FUTURE;
123121
}
124122
return Type;
@@ -179,8 +177,7 @@ bool Archive::IsArchive(bool EnableBroken)
179177
}
180178
if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer.
181179
{
182-
Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1);
183-
if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
180+
if (Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1)!=1 || MarkHead.Mark[SIZEOF_MARKHEAD3]!=0)
184181
return false;
185182
MarkHead.HeadSize=SIZEOF_MARKHEAD5;
186183
}
@@ -196,15 +193,19 @@ bool Archive::IsArchive(bool EnableBroken)
196193
SilentOpen=true;
197194
#endif
198195

196+
bool HeadersLeft; // Any headers left to read.
197+
bool StartFound=false; // Main or encryption headers found.
199198
// Skip the archive encryption header if any and read the main header.
200-
while (ReadHeader()!=0)
199+
while ((HeadersLeft=(ReadHeader()!=0))==true) // Additional parentheses to silence Clang.
201200
{
201+
SeekToNext();
202+
202203
HEADER_TYPE Type=GetHeaderType();
203204
// In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to
204205
// avoid the password prompt.
205-
if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT)
206+
StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT;
207+
if (StartFound)
206208
break;
207-
SeekToNext();
208209
}
209210

210211
// This check allows to make RS based recovery even if password is incorrect.
@@ -213,10 +214,10 @@ bool Archive::IsArchive(bool EnableBroken)
213214
if (FailedHeaderDecryption && !EnableBroken)
214215
return false;
215216

216-
SeekToNext();
217-
if (BrokenHeader) // Main archive header is corrupt.
217+
if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing.
218218
{
219-
uiMsg(UIERROR_MHEADERBROKEN,FileName);
219+
if (!FailedHeaderDecryption) // If not reported a wrong password already.
220+
uiMsg(UIERROR_MHEADERBROKEN,FileName);
220221
if (!EnableBroken)
221222
return false;
222223
}
@@ -230,7 +231,7 @@ bool Archive::IsArchive(bool EnableBroken)
230231
// first file header to set "comment" flag when reading service header.
231232
// Unless we are in silent mode, we need to know about presence of comment
232233
// immediately after IsArchive call.
233-
if (!SilentOpen || !Encrypted)
234+
if (HeadersLeft && (!SilentOpen || !Encrypted))
234235
{
235236
SaveFilePos SavePos(*this);
236237
int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos;
@@ -240,21 +241,30 @@ bool Archive::IsArchive(bool EnableBroken)
240241
{
241242
HEADER_TYPE HeaderType=GetHeaderType();
242243
if (HeaderType==HEAD_SERVICE)
244+
{
245+
// If we have a split service headers, it surely indicates non-first
246+
// volume. But not split service header does not guarantee the first
247+
// volume, because we can have split file after non-split archive
248+
// comment. So we do not quit from loop here.
243249
FirstVolume=Volume && !SubHead.SplitBefore;
250+
}
244251
else
245252
if (HeaderType==HEAD_FILE)
246253
{
247254
FirstVolume=Volume && !FileHead.SplitBefore;
248255
break;
249256
}
257+
else
258+
if (HeaderType==HEAD_ENDARC) // Might happen if archive contains only a split service header.
259+
break;
250260
SeekToNext();
251261
}
252262
CurBlockPos=SaveCurBlockPos;
253263
NextBlockPos=SaveNextBlockPos;
254264
CurHeaderType=SaveCurHeaderType;
255265
}
256266
if (!Volume || FirstVolume)
257-
wcscpy(FirstVolumeName,FileName);
267+
wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName));
258268

259269
return true;
260270
}

vendor/unrar/archive.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ enum ADDSUBDATA_FLAGS
2020
ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode.
2121
};
2222

23+
// RAR5 headers must not exceed 2 MB.
24+
#define MAX_HEADER_SIZE_RAR5 0x200000
25+
2326
class Archive:public File
2427
{
2528
private:
@@ -34,21 +37,16 @@ class Archive:public File
3437
void RequestArcPassword();
3538
void UnexpEndArcMsg();
3639
void BrokenHeaderMsg();
37-
void UnkEncVerMsg(const wchar *Name);
38-
void UnkEncVerMsg();
40+
void UnkEncVerMsg(const wchar *Name,const wchar *Info);
3941
bool ReadCommentData(Array<wchar> *CmtData);
4042

41-
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
43+
#if !defined(RAR_NOCRYPT)
4244
CryptData HeadersCrypt;
4345
#endif
44-
#ifndef SHELL_EXT
4546
ComprDataIO SubDataIO;
46-
#endif
4747
bool DummyCmd;
4848
RAROptions *Cmd;
4949

50-
int64 RecoverySize;
51-
int RecoveryPercent;
5250

5351
RarTime LatestTime;
5452
int LastReadBlock;
@@ -57,11 +55,12 @@ class Archive:public File
5755
bool SilentOpen;
5856
#ifdef USE_QOPEN
5957
QuickOpen QOpen;
58+
bool ProhibitQOpen;
6059
#endif
6160
public:
6261
Archive(RAROptions *InitCmd=NULL);
6362
~Archive();
64-
RARFORMAT IsSignature(const byte *D,size_t Size);
63+
static RARFORMAT IsSignature(const byte *D,size_t Size);
6564
bool IsArchive(bool EnableBroken);
6665
size_t SearchBlock(HEADER_TYPE HeaderType);
6766
size_t SearchSubBlock(const wchar *Type);
@@ -85,15 +84,19 @@ class Archive:public File
8584
void AddSubData(byte *SrcData,uint64 DataSize,File *SrcFile,
8685
const wchar *Name,uint Flags);
8786
bool ReadSubData(Array<byte> *UnpData,File *DestFile);
88-
HEADER_TYPE GetHeaderType() {return CurHeaderType;};
87+
HEADER_TYPE GetHeaderType() {return CurHeaderType;}
8988
RAROptions* GetRAROptions() {return Cmd;}
9089
void SetSilentOpen(bool Mode) {SilentOpen=Mode;}
90+
#if 0
91+
void GetRecoveryInfo(bool Required,int64 *Size,int *Percent);
92+
#endif
9193
#ifdef USE_QOPEN
9294
bool Open(const wchar *Name,uint Mode=FMF_READ);
9395
int Read(void *Data,size_t Size);
9496
void Seek(int64 Offset,int Method);
9597
int64 Tell();
9698
void QOpenUnload() {QOpen.Unload();}
99+
void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;}
97100
#endif
98101

99102
BaseBlock ShortBlock;
@@ -106,10 +109,7 @@ class Archive:public File
106109
FileHeader SubHead;
107110
CommentHeader CommHead;
108111
ProtectHeader ProtectHead;
109-
AVHeader AVHead;
110-
SignHeader SignHead;
111112
UnixOwnersHeader UOHead;
112-
MacFInfoHeader MACHead;
113113
EAHeader EAHead;
114114
StreamHeader StreamHead;
115115

@@ -130,7 +130,7 @@ class Archive:public File
130130
bool BrokenHeader;
131131
bool FailedHeaderDecryption;
132132

133-
#if !defined(SHELL_EXT) && !defined(RAR_NOCRYPT)
133+
#if !defined(RAR_NOCRYPT)
134134
byte ArcSalt[SIZE_SALT50];
135135
#endif
136136

0 commit comments

Comments
 (0)