Dear Martin, dear all, I am proceeding according to the salvation guide lines. More than 21 days have passed till reporting this bug. I have uploaded the unrar-nonfree_5.6.6-1 to the DELAYED/7 queue, and attach the debdiff here.
All the best Norbert On Fri, 28 Sep 2018, Norbert Preining wrote: > I intend to salvate unrar-nonfree according to > https://www.debian.org/doc/manuals/developers-reference/ch05.en.html#package-salvaging > > I haven't gotten any answer about libunrar in bug report > https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=720051 > in more than a year, despite providing patches to support > libunrar shared lib building, and your last activity according to > https://qa.debian.org/developer.php?login=m...@debian.org > is also more than a year ago (last upload 2017-08-29). > > Several new versions have been uploaded, and the need for > the shared library as been expressed in the above mentioned > bug report. > > According to the procedure laid out, I will wait 21 days before > uploading a new package into the DELAYED queue, but I still hope > to hear from you. -- PREINING Norbert http://www.preining.info Accelia Inc. + JAIST + TeX Live + Debian Developer GPG: 0x860CDC13 fp: F7D8 A928 26E3 16A1 9FA0 ACF0 6CAC A448 860C DC13
diff -Nru unrar-nonfree-5.5.8/arccmt.cpp unrar-nonfree-5.6.6/arccmt.cpp --- unrar-nonfree-5.5.8/arccmt.cpp 2017-08-11 22:56:21.000000000 +0900 +++ unrar-nonfree-5.6.6/arccmt.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -22,7 +22,8 @@ // Old style (RAR 2.9) archive comment embedded into the main // archive header. Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET); - ReadHeader(); + if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT) + return false; } else { @@ -67,6 +68,7 @@ DataIO.EnableShowProgress(false); DataIO.SetPackedSizeToRead(CmtLength); DataIO.UnpHash.Init(HASH_CRC32,1); + DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet. Unpack CmtUnpack(&DataIO); CmtUnpack.Init(0x10000,false); @@ -99,7 +101,12 @@ if (CmtLength==0) return false; Array<byte> CmtRaw(CmtLength); - Read(&CmtRaw[0],CmtLength); + int ReadSize=Read(&CmtRaw[0],CmtLength); + if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared. + { + CmtLength=ReadSize; + CmtRaw.Alloc(CmtLength); + } if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff)) { @@ -113,7 +120,7 @@ // 4x memory for OEM to UTF-8 output here. OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]); #endif - CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtLength); + CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); CmtData->Alloc(wcslen(CmtData->Addr(0))); } #endif diff -Nru unrar-nonfree-5.5.8/archive.cpp unrar-nonfree-5.6.6/archive.cpp --- unrar-nonfree-5.5.8/archive.cpp 2017-08-11 22:56:21.000000000 +0900 +++ unrar-nonfree-5.6.6/archive.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -30,8 +30,6 @@ CurBlockPos=0; NextBlockPos=0; - RecoverySize=-1; - RecoveryPercent=-1; memset(&MainHead,0,sizeof(MainHead)); memset(&CryptHead,0,sizeof(CryptHead)); @@ -48,6 +46,10 @@ SilentOpen=false; +#ifdef USE_QOPEN + ProhibitQOpen=false; +#endif + } @@ -114,7 +116,7 @@ if (D[6]==1) Type=RARFMT50; else - if (D[6]==2) + if (D[6]>1 && D[6]<5) Type=RARFMT_FUTURE; } return Type; @@ -175,8 +177,7 @@ } if (Format==RARFMT50) // RAR 5.0 signature is by one byte longer. { - Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1); - if (MarkHead.Mark[SIZEOF_MARKHEAD3]!=0) + if (Read(MarkHead.Mark+SIZEOF_MARKHEAD3,1)!=1 || MarkHead.Mark[SIZEOF_MARKHEAD3]!=0) return false; MarkHead.HeadSize=SIZEOF_MARKHEAD5; } @@ -192,15 +193,19 @@ SilentOpen=true; #endif + bool HeadersLeft; // Any headers left to read. + bool StartFound=false; // Main or encryption headers found. // Skip the archive encryption header if any and read the main header. - while (ReadHeader()!=0) + while ((HeadersLeft=(ReadHeader()!=0))==true) // Additional parentheses to silence Clang. { + SeekToNext(); + HEADER_TYPE Type=GetHeaderType(); // In RAR 5.0 we need to quit after reading HEAD_CRYPT if we wish to // avoid the password prompt. - if (Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT) + StartFound=Type==HEAD_MAIN || SilentOpen && Type==HEAD_CRYPT; + if (StartFound) break; - SeekToNext(); } // This check allows to make RS based recovery even if password is incorrect. @@ -209,10 +214,10 @@ if (FailedHeaderDecryption && !EnableBroken) return false; - SeekToNext(); - if (BrokenHeader) // Main archive header is corrupt. + if (BrokenHeader || !StartFound) // Main archive header is corrupt or missing. { - uiMsg(UIERROR_MHEADERBROKEN,FileName); + if (!FailedHeaderDecryption) // If not reported a wrong password already. + uiMsg(UIERROR_MHEADERBROKEN,FileName); if (!EnableBroken) return false; } @@ -226,7 +231,7 @@ // first file header to set "comment" flag when reading service header. // Unless we are in silent mode, we need to know about presence of comment // immediately after IsArchive call. - if (!SilentOpen || !Encrypted) + if (HeadersLeft && (!SilentOpen || !Encrypted)) { SaveFilePos SavePos(*this); int64 SaveCurBlockPos=CurBlockPos,SaveNextBlockPos=NextBlockPos; @@ -259,7 +264,7 @@ CurHeaderType=SaveCurHeaderType; } if (!Volume || FirstVolume) - wcscpy(FirstVolumeName,FileName); + wcsncpyz(FirstVolumeName,FileName,ASIZE(FirstVolumeName)); return true; } diff -Nru unrar-nonfree-5.5.8/archive.hpp unrar-nonfree-5.6.6/archive.hpp --- unrar-nonfree-5.5.8/archive.hpp 2017-08-11 22:56:21.000000000 +0900 +++ unrar-nonfree-5.6.6/archive.hpp 2018-09-03 19:21:39.000000000 +0900 @@ -20,6 +20,9 @@ ASDF_CRYPTIFHEADERS = 8 // Encrypt data after subheader only in -hp mode. }; +// RAR5 headers must not exceed 2 MB. +#define MAX_HEADER_SIZE_RAR5 0x200000 + class Archive:public File { private: @@ -45,8 +48,6 @@ bool DummyCmd; RAROptions *Cmd; - int64 RecoverySize; - int RecoveryPercent; RarTime LatestTime; int LastReadBlock; @@ -55,6 +56,7 @@ bool SilentOpen; #ifdef USE_QOPEN QuickOpen QOpen; + bool ProhibitQOpen; #endif public: Archive(RAROptions *InitCmd=NULL); @@ -95,6 +97,7 @@ void Seek(int64 Offset,int Method); int64 Tell(); void QOpenUnload() {QOpen.Unload();} + void SetProhibitQOpen(bool Mode) {ProhibitQOpen=Mode;} #endif BaseBlock ShortBlock; @@ -107,10 +110,7 @@ FileHeader SubHead; CommentHeader CommHead; ProtectHeader ProtectHead; - AVHeader AVHead; - SignHeader SignHead; UnixOwnersHeader UOHead; - MacFInfoHeader MACHead; EAHeader EAHead; StreamHeader StreamHead; diff -Nru unrar-nonfree-5.5.8/arcmem.cpp unrar-nonfree-5.6.6/arcmem.cpp --- unrar-nonfree-5.5.8/arcmem.cpp 1970-01-01 09:00:00.000000000 +0900 +++ unrar-nonfree-5.6.6/arcmem.cpp 2018-03-11 15:24:06.000000000 +0900 @@ -0,0 +1,67 @@ +ArcMemory::ArcMemory() +{ + Loaded=false; + SeekPos=0; +} + + +void ArcMemory::Load(const byte *Data,size_t Size) +{ + ArcData.Alloc(Size); + memcpy(&ArcData[0],Data,Size); + Loaded=true; + SeekPos=0; +} + + +bool ArcMemory::Unload() +{ + if (!Loaded) + return false; + Loaded=false; + return true; +} + + +bool ArcMemory::Read(void *Data,size_t Size,size_t &Result) +{ + if (!Loaded) + return false; + Result=(size_t)Min(Size,ArcData.Size()-SeekPos); + memcpy(Data,&ArcData[(size_t)SeekPos],Result); + SeekPos+=Result; + return true; +} + + +bool ArcMemory::Seek(int64 Offset,int Method) +{ + if (!Loaded) + return false; + if (Method==SEEK_SET) + { + if (Offset<0) + SeekPos=0; + else + SeekPos=Min((uint64)Offset,ArcData.Size()); + } + else + if (Method==SEEK_CUR || Method==SEEK_END) + { + if (Method==SEEK_END) + SeekPos=ArcData.Size(); + SeekPos+=(uint64)Offset; + if (SeekPos>ArcData.Size()) + SeekPos=Offset<0 ? 0 : ArcData.Size(); + } + return true; +} + + +bool ArcMemory::Tell(int64 *Pos) +{ + if (!Loaded) + return false; + *Pos=SeekPos; + return true; +} diff -Nru unrar-nonfree-5.5.8/arcmem.hpp unrar-nonfree-5.6.6/arcmem.hpp --- unrar-nonfree-5.5.8/arcmem.hpp 1970-01-01 09:00:00.000000000 +0900 +++ unrar-nonfree-5.6.6/arcmem.hpp 2018-03-11 15:24:06.000000000 +0900 @@ -0,0 +1,22 @@ +#ifndef _RAR_ARCMEM_ +#define _RAR_ARCMEM_ + +// Memory interface for software fuzzers. + +class ArcMemory +{ + private: + bool Loaded; + Array<byte> ArcData; + uint64 SeekPos; + public: + ArcMemory(); + void Load(const byte *Data,size_t Size); + bool Unload(); + bool IsLoaded() {return Loaded;} + bool Read(void *Data,size_t Size,size_t &Result); + bool Seek(int64 Offset,int Method); + bool Tell(int64 *Pos); +}; + +#endif diff -Nru unrar-nonfree-5.5.8/arcread.cpp unrar-nonfree-5.6.6/arcread.cpp --- unrar-nonfree-5.5.8/arcread.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/arcread.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -26,11 +26,18 @@ break; } + // It is important to check ReadSize>0 here, because it is normal + // for RAR2 and RAR3 archives without end of archive block to have + // NextBlockPos==CurBlockPos after the end of archive has reached. if (ReadSize>0 && NextBlockPos<=CurBlockPos) { BrokenHeaderMsg(); - return 0; + ReadSize=0; } + + if (ReadSize==0) + CurHeaderType=HEAD_UNKNOWN; + return ReadSize; } @@ -113,6 +120,17 @@ } +// Return f in case of signed integer overflow or negative parameters +// or v1+v2 otherwise. We use it for file offsets, which are signed +// for compatibility with off_t in POSIX file functions and third party code. +// Signed integer overflow is the undefined behavior according to +// C++ standard and it causes fuzzers to complain. +inline int64 SafeAdd(int64 v1,int64 v2,int64 f) +{ + return v1>=0 && v2>=0 && v1<=MAX_INT64-v2 ? v1+v2 : f; +} + + size_t Archive::ReadHeader15() { RawRead Raw(this); @@ -246,6 +264,11 @@ uint FileTime=Raw.Get4(); hd->UnpVer=Raw.Get1(); + + // RAR15 did not use the special dictionary size to mark dirs. + if (hd->UnpVer<20 && (hd->FileAttr & 0x10)!=0) + hd->Dir=true; + hd->Method=Raw.Get1()-0x30; size_t NameSize=Raw.Get2(); hd->FileAttr=Raw.Get4(); @@ -315,7 +338,7 @@ size_t Length=strlen(FileName); Length++; if (ReadNameSize>Length) - NameCoder.Decode(FileName,(byte *)FileName+Length, + NameCoder.Decode(FileName,ReadNameSize,(byte *)FileName+Length, ReadNameSize-Length,hd->FileName, ASIZE(hd->FileName)); } @@ -343,17 +366,7 @@ // They are stored after the file name and before salt. hd->SubData.Alloc(DataSize); Raw.GetB(&hd->SubData[0],DataSize); - if (hd->CmpName(SUBHEAD_TYPE_RR)) - { - byte *D=&hd->SubData[8]; - RecoverySize=D[0]+((uint)D[1]<<8)+((uint)D[2]<<16)+((uint)D[3]<<24); - RecoverySize*=512; // Sectors to size. - int64 CurPos=Tell(); - RecoveryPercent=ToPercent(RecoverySize,CurPos); - // Round fractional percent exceeding .5 to upper value. - if (ToPercent(RecoverySize+CurPos/200,CurPos)>RecoveryPercent) - RecoveryPercent++; - } + } if (hd->CmpName(SUBHEAD_TYPE_CMT)) @@ -397,7 +410,9 @@ CurTime->SetLocal(&rlt); } } - NextBlockPos+=hd->PackSize; + // Set to 0 in case of overflow, so end of ReadHeader cares about it. + NextBlockPos=SafeAdd(NextBlockPos,hd->PackSize,0); + bool CRCProcessedOnly=hd->CommentInHeader; ushort HeaderCRC=Raw.GetCRC15(CRCProcessedOnly); if (hd->HeadCRC!=HeaderCRC) @@ -434,19 +449,6 @@ CommHead.Method=Raw.Get1(); CommHead.CommCRC=Raw.Get2(); break; - case HEAD3_SIGN: - *(BaseBlock *)&SignHead=ShortBlock; - SignHead.CreationTime=Raw.Get4(); - SignHead.ArcNameSize=Raw.Get2(); - SignHead.UserNameSize=Raw.Get2(); - break; - case HEAD3_AV: - *(BaseBlock *)&AVHead=ShortBlock; - AVHead.UnpVer=Raw.Get1(); - AVHead.Method=Raw.Get1(); - AVHead.AVVer=Raw.Get1(); - AVHead.AVInfoCRC=Raw.Get4(); - break; case HEAD3_PROTECT: *(BaseBlock *)&ProtectHead=ShortBlock; ProtectHead.DataSize=Raw.Get4(); @@ -455,9 +457,8 @@ ProtectHead.TotalBlocks=Raw.Get4(); Raw.GetB(ProtectHead.Mark,8); NextBlockPos+=ProtectHead.DataSize; - RecoverySize=ProtectHead.RecSectors*512; break; - case HEAD3_OLDSERVICE: + case HEAD3_OLDSERVICE: // RAR 2.9 and earlier. *(BaseBlock *)&SubBlockHead=ShortBlock; SubBlockHead.DataSize=Raw.Get4(); NextBlockPos+=SubBlockHead.DataSize; @@ -478,13 +479,6 @@ UOHead.OwnerName[UOHead.OwnerNameSize]=0; UOHead.GroupName[UOHead.GroupNameSize]=0; break; - case MAC_HEAD: - *(SubBlockHeader *)&MACHead=SubBlockHead; - MACHead.fileType=Raw.Get4(); - MACHead.fileCreator=Raw.Get4(); - break; - case EA_HEAD: - case BEEA_HEAD: case NTACL_HEAD: *(SubBlockHeader *)&EAHead=SubBlockHead; EAHead.UnpSize=Raw.Get4(); @@ -546,12 +540,6 @@ } } - if (NextBlockPos<=CurBlockPos) - { - BrokenHeaderMsg(); - return 0; - } - return Raw.Size(); } @@ -567,7 +555,6 @@ #if defined(RAR_NOCRYPT) return 0; #else - RequestArcPassword(); byte HeadersInitV[SIZE_INITV]; if (Read(HeadersInitV,SIZE_INITV)!=SIZE_INITV) @@ -576,15 +563,48 @@ return 0; } - byte PswCheck[SIZE_PSWCHECK]; - HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck); - // Verify password validity. - if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0) + // We repeat the password request only for manually entered passwords + // and not for -p<pwd>. Wrong password can be intentionally provided + // in -p<pwd> to not stop batch processing for encrypted archives. + bool GlobalPassword=Cmd->Password.IsSet(); + + while (true) // Repeat the password prompt for wrong passwords. { - uiMsg(UIERROR_BADPSW,FileName); - FailedHeaderDecryption=true; - ErrHandler.SetErrorCode(RARX_BADPWD); - return 0; + RequestArcPassword(); + + byte PswCheck[SIZE_PSWCHECK]; + HeadersCrypt.SetCryptKeys(false,CRYPT_RAR50,&Cmd->Password,CryptHead.Salt,HeadersInitV,CryptHead.Lg2Count,NULL,PswCheck); + // Verify password validity. + if (CryptHead.UsePswCheck && memcmp(PswCheck,CryptHead.PswCheck,SIZE_PSWCHECK)!=0) + { + if (GlobalPassword) // For -p<pwd> or Ctrl+P. + { + // This message is used by Android GUI to reset cached passwords. + // Update appropriate code if changed. + uiMsg(UIERROR_BADPSW,FileName); + FailedHeaderDecryption=true; + ErrHandler.SetErrorCode(RARX_BADPWD); + return 0; + } + else // For passwords entered manually. + { + // This message is used by Android GUI and Windows GUI and SFX to + // reset cached passwords. Update appropriate code if changed. + uiMsg(UIWAIT_BADPSW,FileName); + Cmd->Password.Clean(); + } + +#ifdef RARDLL + // Avoid new requests for unrar.dll to prevent the infinite loop + // if app always returns the same password. + ErrHandler.SetErrorCode(RARX_BADPWD); + Cmd->DllError=ERAR_BAD_PASSWORD; + ErrHandler.Exit(RARX_BADPWD); +#else + continue; // Request a password again. +#endif + } + break; } Raw.SetCrypt(&HeadersCrypt); @@ -592,8 +612,8 @@ } // Header size must not occupy more than 3 variable length integer bytes - // resulting in 2 MB maximum header size, so here we read 4 byte CRC32 - // followed by 3 bytes or less of header size. + // resulting in 2 MB maximum header size (MAX_HEADER_SIZE_RAR5), + // so here we read 4 byte CRC32 followed by 3 bytes or less of header size. const size_t FirstReadSize=7; // Smallest possible block size. if (Raw.Read(FirstReadSize)<FirstReadSize) { @@ -670,7 +690,9 @@ if ((ShortBlock.Flags & HFL_DATA)!=0) DataSize=Raw.GetV(); - NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize)+DataSize; + NextBlockPos=CurBlockPos+FullHeaderSize(ShortBlock.HeadSize); + // Set to 0 in case of overflow, so end of ReadHeader cares about it. + NextBlockPos=SafeAdd(NextBlockPos,DataSize,0); switch(ShortBlock.HeaderType) { @@ -734,7 +756,7 @@ ProcessExtra50(&Raw,(size_t)ExtraSize,&MainHead); #ifdef USE_QOPEN - if (MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE) + if (!ProhibitQOpen && MainHead.Locator && MainHead.QOpenOffset>0 && Cmd->QOpenMode!=QOPEN_NONE) { // We seek to QO block in the end of archive when processing // QOpen.Load, so we need to preserve current block positions @@ -868,11 +890,6 @@ break; } - if (NextBlockPos<=CurBlockPos) - { - BrokenHeaderMsg(); - return 0; - } return Raw.Size(); } @@ -908,11 +925,10 @@ ErrHandler.Exit(RARX_USERBREAK); } #else - if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password) || - !Cmd->Password.IsSet()) + if (!uiGetPassword(UIPASSWORD_ARCHIVE,FileName,&Cmd->Password)) { Close(); - uiMsg(UIERROR_INCERRCOUNT); + uiMsg(UIERROR_INCERRCOUNT); // Prevent archive deleting if delete after extraction is on. ErrHandler.Exit(RARX_USERBREAK); } #endif @@ -931,14 +947,17 @@ Raw->SetPos(ExtraStart); while (Raw->DataLeft()>=2) { - int64 FieldSize=Raw->GetV(); - if (FieldSize==0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft()) + int64 FieldSize=Raw->GetV(); // Needs to be signed for check below and can be negative. + if (FieldSize<=0 || Raw->DataLeft()==0 || FieldSize>(int64)Raw->DataLeft()) break; size_t NextPos=size_t(Raw->GetPos()+FieldSize); uint64 FieldType=Raw->GetV(); FieldSize=int64(NextPos-Raw->GetPos()); // Field size without size and type fields. + if (FieldSize<0) // FieldType is longer than expected extra field size. + break; + if (bb->HeaderType==HEAD_MAIN) { MainHeader *hd=(MainHeader *)bb; @@ -1070,7 +1089,7 @@ wchar VerText[20]; swprintf(VerText,ASIZE(VerText),L";%u",Version); - wcsncatz(FileHead.FileName,VerText,ASIZE(FileHead.FileName)); + wcsncatz(hd->FileName,VerText,ASIZE(hd->FileName)); } } break; @@ -1136,7 +1155,7 @@ // required. It did not hurt extraction, because UnRAR 5.21 // and earlier ignored this field and set FieldSize as data left // in entire extra area. But now we set the correct field size - // and set FieldSize based on actual extra record size, + // and set FieldSize based on the actual extra record size, // so we need to adjust it for those older archives here. // FHEXTRA_SUBDATA in those archives always belongs to HEAD_SERVICE // and always is last in extra area. So since its size is by 1 @@ -1145,6 +1164,9 @@ if (bb->HeaderType==HEAD_SERVICE && Raw->Size()-NextPos==1) FieldSize++; + // We cannot allocate too much memory here, because above + // we check FieldSize againt Raw size and we control that Raw size + // is sensible when reading headers. hd->SubData.Alloc((size_t)FieldSize); Raw->GetB(hd->SubData.Addr(0),(size_t)FieldSize); } @@ -1168,6 +1190,8 @@ byte Mark[4]; Raw.GetB(Mark,4); uint HeadSize=Raw.Get2(); + if (HeadSize<7) + return false; byte Flags=Raw.Get1(); NextBlockPos=CurBlockPos+HeadSize; CurHeaderType=HEAD_MAIN; @@ -1189,6 +1213,8 @@ FileHead.FileHash.Type=HASH_RAR14; FileHead.FileHash.CRC32=Raw.Get2(); FileHead.HeadSize=Raw.Get2(); + if (FileHead.HeadSize<21) + return false; uint FileTime=Raw.Get4(); FileHead.FileAttr=Raw.Get1(); FileHead.Flags=Raw.Get1()|LONG_BLOCK; @@ -1203,6 +1229,10 @@ FileHead.PackSize=FileHead.DataSize; FileHead.WinSize=0x10000; + FileHead.Dir=(FileHead.FileAttr & 0x10)!=0; + + FileHead.HostOS=HOST_MSDOS; + FileHead.HSType=HSYS_WINDOWS; FileHead.mtime.SetDos(FileTime); @@ -1308,8 +1338,6 @@ void Archive::ConvertFileHeader(FileHeader *hd) { - if (Format==RARFMT15 && hd->UnpVer<20 && (hd->FileAttr & 0x10)) - hd->Dir=true; if (hd->HSType==HSYS_UNKNOWN) if (hd->Dir) hd->FileAttr=0x10; diff -Nru unrar-nonfree-5.5.8/cmddata.cpp unrar-nonfree-5.6.6/cmddata.cpp --- unrar-nonfree-5.5.8/cmddata.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/cmddata.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -13,6 +13,7 @@ *Command=0; *ArcName=0; FileLists=false; + NoMoreSwitches=false; ListMode=RCLM_AUTO; @@ -96,7 +97,7 @@ else if (*Command==0) { - wcsncpy(Command,Arg,ASIZE(Command)); + wcsncpyz(Command,Arg,ASIZE(Command)); *Command=toupperw(*Command); @@ -133,17 +134,7 @@ { FileLists=true; - RAR_CHARSET Charset=FilelistCharset; - -#if defined(_WIN_ALL) - // for compatibility reasons we use OEM encoding - // in Win32 console version by default - -// if (Charset==RCH_DEFAULT) -// Charset=RCH_OEM; -#endif - - ReadTextFile(Arg+1,&FileArgs,false,true,Charset,true,true,true); + ReadTextFile(Arg+1,&FileArgs,false,true,FilelistCharset,true,true,true); } else @@ -248,7 +239,7 @@ if (C0=='R' && (C1=='R' || C1=='V')) Cmd[2]=0; wchar SwName[16+ASIZE(Cmd)]; - swprintf(SwName,ASIZE(SwName),L"switches_%s=",Cmd); + swprintf(SwName,ASIZE(SwName),L"switches_%ls=",Cmd); size_t Length=wcslen(SwName); if (wcsnicomp(Str,SwName,Length)==0) ProcessSwitchesString(Str+Length); @@ -424,6 +415,9 @@ if (wcsicomp(Switch+1,L"ERR")==0) { MsgStream=MSG_STDERR; + // Set it immediately when parsing the command line, so it also + // affects messages issued while parsing the command line. + SetConsoleMsgStream(MSG_STDERR); break; } if (wcsnicomp(Switch+1,L"EML",3)==0) @@ -431,9 +425,15 @@ wcsncpyz(EmailTo,Switch[4]!=0 ? Switch+4:L"@",ASIZE(EmailTo)); break; } + if (wcsicomp(Switch+1,L"M")==0) + { + MoreInfo=true; + break; + } if (wcsicomp(Switch+1,L"NUL")==0) { MsgStream=MSG_NULL; + SetConsoleMsgStream(MSG_NULL); break; } if (toupperw(Switch[1])=='D') @@ -443,6 +443,7 @@ { case 'Q': MsgStream=MSG_ERRONLY; + SetConsoleMsgStream(MSG_ERRONLY); break; case 'C': DisableCopyright=true; @@ -456,9 +457,24 @@ } break; } - if (wcsicomp(Switch+1,L"OFF")==0) + if (wcsnicomp(Switch+1,L"OFF",3)==0) { - Shutdown=true; + switch(Switch[4]) + { + case 0: + case '1': + Shutdown=POWERMODE_OFF; + break; + case '2': + Shutdown=POWERMODE_HIBERNATE; + break; + case '3': + Shutdown=POWERMODE_SLEEP; + break; + case '4': + Shutdown=POWERMODE_RESTART; + break; + } break; } if (wcsicomp(Switch+1,L"VER")==0) @@ -574,19 +590,7 @@ { StringList *Args=toupperw(Switch[0])=='N' ? &InclArgs:&ExclArgs; if (Switch[1]=='@' && !IsWildcard(Switch)) - { - RAR_CHARSET Charset=FilelistCharset; - -#if defined(_WIN_ALL) - // for compatibility reasons we use OEM encoding - // in Win32 console version by default - -// if (Charset==RCH_DEFAULT) -// Charset=RCH_OEM; -#endif - - ReadTextFile(Switch+2,Args,false,true,Charset,true,true,true); - } + ReadTextFile(Switch+2,Args,false,true,FilelistCharset,true,true,true); else Args->AddString(Switch+1); } @@ -783,6 +787,9 @@ AlreadyBad=true; break; } + // Set it immediately when parsing the command line, so it also + // affects messages issued while parsing the command line. + SetConsoleRedirectCharset(RedirectCharset); } break; @@ -1190,8 +1197,8 @@ { if (MatchedArg!=NULL && MatchedArgSize>0) *MatchedArg=0; - if (wcslen(FileHead.FileName)>=NM) - return 0; +// if (wcslen(FileHead.FileName)>=NM) +// return 0; bool Dir=FileHead.Dir; if (ExclCheck(FileHead.FileName,Dir,false,true)) return 0; diff -Nru unrar-nonfree-5.5.8/compress.hpp unrar-nonfree-5.6.6/compress.hpp --- unrar-nonfree-5.5.8/compress.hpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/compress.hpp 2018-09-03 19:21:39.000000000 +0900 @@ -6,7 +6,16 @@ class PackDef { public: + // Maximum LZ match length we can encode even for short distances. static const uint MAX_LZ_MATCH = 0x1001; + + // We increment LZ match length for longer distances, because shortest + // matches are not allowed for them. Maximum length increment is 3 + // for distances larger than 256KB (0x40000). Here we define the maximum + // incremented LZ match. Normally packer does not use it, but we must be + // ready to process it in corrupt archives. + static const uint MAX_INC_LZ_MATCH = MAX_LZ_MATCH + 3; + static const uint MAX3_LZ_MATCH = 0x101; // Maximum match length for RAR v3. static const uint LOW_DIST_REP_COUNT = 16; diff -Nru unrar-nonfree-5.5.8/consio.cpp unrar-nonfree-5.6.6/consio.cpp --- unrar-nonfree-5.5.8/consio.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/consio.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -49,9 +49,14 @@ } -void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset) +void SetConsoleMsgStream(MESSAGE_TYPE MsgStream) { ::MsgStream=MsgStream; +} + + +void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset) +{ ::RedirectCharset=RedirectCharset; } diff -Nru unrar-nonfree-5.5.8/consio.hpp unrar-nonfree-5.6.6/consio.hpp --- unrar-nonfree-5.5.8/consio.hpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/consio.hpp 2018-09-03 19:21:39.000000000 +0900 @@ -2,7 +2,8 @@ #define _RAR_CONSIO_ void InitConsole(); -void InitConsoleOptions(MESSAGE_TYPE MsgStream,RAR_CHARSET RedirectCharset); +void SetConsoleMsgStream(MESSAGE_TYPE MsgStream); +void SetConsoleRedirectCharset(RAR_CHARSET RedirectCharset); void OutComment(const wchar *Comment,size_t Size); #ifndef SILENT diff -Nru unrar-nonfree-5.5.8/crc.cpp unrar-nonfree-5.6.6/crc.cpp --- unrar-nonfree-5.5.8/crc.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/crc.cpp 2018-09-03 19:21:39.000000000 +0900 @@ -66,7 +66,7 @@ uint NextData = Data[4]|(Data[5] << 8)|(Data[6] << 16)|(Data[7] << 24); #else StartCRC ^= *(uint32 *) Data; - uint NextData = *(uint32 *) (Data +4); + uint NextData = *(uint32 *) (Data+4); #endif StartCRC = crc_tables[7][(byte) StartCRC ] ^ crc_tables[6][(byte)(StartCRC >> 8) ] ^ diff -Nru unrar-nonfree-5.5.8/debian/changelog unrar-nonfree-5.6.6/debian/changelog --- unrar-nonfree-5.5.8/debian/changelog 2017-08-21 21:29:11.000000000 +0900 +++ unrar-nonfree-5.6.6/debian/changelog 2018-10-22 10:37:47.000000000 +0900 @@ -1,3 +1,11 @@ +unrar-nonfree (1:5.6.6-1) unstable; urgency=medium + + * Package salvaged (Closes: #909795) + * add libunrar5 and libunrar-dev packages + * bump standards version, no changes necessary + + -- Norbert Preining <prein...@debian.org> Mon, 22 Oct 2018 10:37:47 +0900 + unrar-nonfree (1:5.5.8-1) unstable; urgency=high * New upstream release diff -Nru unrar-nonfree-5.5.8/debian/control unrar-nonfree-5.6.6/debian/control --- unrar-nonfree-5.5.8/debian/control 2017-08-21 21:29:11.000000000 +0900 +++ unrar-nonfree-5.6.6/debian/control 2018-10-22 10:37:47.000000000 +0900 @@ -1,11 +1,13 @@ Source: unrar-nonfree Section: non-free/utils Priority: optional -Maintainer: Martin Meredith <m...@debian.org> +Maintainer: Norbert Preining <prein...@debian.org> Homepage: http://www.rarlabs.com/ Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~) -Standards-Version: 4.0.1 +Standards-Version: 4.2.1 XS-Autobuild: yes +Vcs-Browser: https://salsa.debian.org/preining/unrar-nonfree +Vcs-Git: https://salsa.debian.org/preining/unrar-nonfree.git Package: unrar Architecture: any @@ -14,3 +16,22 @@ Description: Unarchiver for .rar files (non-free version) Unrar can extract files from .rar archives. If you want to create .rar archives, install package rar. + +Package: libunrar5 +Section: non-free/libs +Architecture: any +Multi-Arch: same +Depends: ${misc:Depends}, ${shlibs:Depends} +Pre-Depends: ${misc:Pre-Depends} +Description: Unarchiver for .rar files (non-free version) - shared library + library for unarchiving .rar files + +Package: libunrar-dev +Section: non-free/libdevel +Architecture: any +Multi-Arch: same +Depends: ${misc:Depends}, libunrar5 (= ${binary:Version}), ${shlibs:Depends} +Description: Unarchiver for .rar files (non-free version) - development files + This package contains the static library and header files for the + libunrar library. + diff -Nru unrar-nonfree-5.5.8/debian/patches/fix-buildflags unrar-nonfree-5.6.6/debian/patches/fix-buildflags --- unrar-nonfree-5.5.8/debian/patches/fix-buildflags 2017-06-23 02:07:52.000000000 +0900 +++ unrar-nonfree-5.6.6/debian/patches/fix-buildflags 2018-10-22 10:37:47.000000000 +0900 @@ -1,16 +1,30 @@ ---- a/makefile -+++ b/makefile -@@ -3,12 +3,10 @@ +--- + makefile | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) +--- unrar.orig/makefile ++++ unrar/makefile +@@ -3,12 +3,12 @@ + # Linux using GCC CXX=c++ --CXXFLAGS=-O2 --LIBFLAGS=-fPIC +-CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else ++CXXFLAGS=-Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else + LIBFLAGS=-fPIC DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP STRIP=strip AR=ar -LDFLAGS=-pthread +LDFLAGS+=-pthread DESTDIR=/usr - + # Linux using LCC +@@ -156,7 +156,7 @@ lib: CXXFLAGS+=$(LIBFLAGS) + lib: clean $(OBJECTS) $(LIB_OBJ) + @rm -f libunrar.so + @rm -f libunrar.a +- $(LINK) -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ) ++ $(LINK) -Wl,-soname,libunrar.so.5 -shared -o libunrar.so $(LDFLAGS) $(OBJECTS) $(LIB_OBJ) + $(AR) rcs libunrar.a $(OBJECTS) $(LIB_OBJ) + + install-unrar: diff -Nru unrar-nonfree-5.5.8/debian/rules unrar-nonfree-5.6.6/debian/rules --- unrar-nonfree-5.5.8/debian/rules 2013-08-15 23:48:15.000000000 +0900 +++ unrar-nonfree-5.6.6/debian/rules 2018-10-22 10:37:47.000000000 +0900 @@ -1,5 +1,7 @@ #!/usr/bin/make -f +DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) + DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk @@ -9,13 +11,18 @@ build-stamp: dh_testdir make -f makefile + make -f makefile lib + touch build-stamp clean: dh_testdir dh_testroot make -f makefile clean - rm -rf unrar + rm -f unrar + rm -f libunrar.so + rm -f libunrar.a + rm -f build-stamp dh_clean binary-indep: @@ -30,9 +37,19 @@ install -o root -g root -s -m 0755 unrar debian/unrar/usr/bin/unrar-nonfree + mkdir -p debian/libunrar5/usr/lib/$(DEB_HOST_MULTIARCH) + mkdir -p debian/libunrar-dev/usr/lib/$(DEB_HOST_MULTIARCH) + mkdir -p debian/libunrar-dev/usr/include/$(DEB_HOST_MULTIARCH)/unrar + + install -o root -g root -s -m 0755 libunrar.so debian/libunrar5/usr/lib/$(DEB_HOST_MULTIARCH)/libunrar.so.5 + install -o root -g root -m 0644 libunrar.a debian/libunrar-dev/usr/lib/$(DEB_HOST_MULTIARCH)/libunrar.a + install -o root -g root -m 0644 *.hpp debian/libunrar-dev/usr/include/$(DEB_HOST_MULTIARCH)/unrar + ln -s libunrar.so.5 debian/libunrar-dev/usr/lib/$(DEB_HOST_MULTIARCH)/libunrar.so + dh_installdocs dh_installman debian/unrar-nonfree.1 dh_installchangelogs + dh_makeshlibs -plibunrar5 dh_strip dh_compress dh_fixperms diff -Nru unrar-nonfree-5.5.8/dll.cpp unrar-nonfree-5.6.6/dll.cpp --- unrar-nonfree-5.5.8/dll.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/dll.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -35,6 +35,8 @@ DataSet *Data=NULL; try { + ErrHandler.Clean(); + r->OpenResult=0; Data=new DataSet; Data->Cmd.DllError=0; @@ -151,9 +153,16 @@ int PASCAL RARCloseArchive(HANDLE hArcData) { DataSet *Data=(DataSet *)hArcData; - bool Success=Data==NULL ? false:Data->Arc.Close(); - delete Data; - return Success ? ERAR_SUCCESS : ERAR_ECLOSE; + try + { + bool Success=Data==NULL ? false:Data->Arc.Close(); + delete Data; + return Success ? ERAR_SUCCESS : ERAR_ECLOSE; + } + catch (RAR_EXIT ErrCode) + { + return Data->Cmd.DllError!=0 ? Data->Cmd.DllError : RarErrorToDll(ErrCode); + } } @@ -398,13 +407,13 @@ int PASCAL RARProcessFile(HANDLE hArcData,int Operation,char *DestPath,char *DestName) { - return(ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL)); + return ProcessFile(hArcData,Operation,DestPath,DestName,NULL,NULL); } int PASCAL RARProcessFileW(HANDLE hArcData,int Operation,wchar *DestPath,wchar *DestName) { - return(ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName)); + return ProcessFile(hArcData,Operation,NULL,NULL,DestPath,DestName); } diff -Nru unrar-nonfree-5.5.8/dll.rc unrar-nonfree-5.6.6/dll.rc --- unrar-nonfree-5.5.8/dll.rc 2017-08-11 22:53:04.000000000 +0900 +++ unrar-nonfree-5.6.6/dll.rc 2018-09-03 17:50:08.000000000 +0900 @@ -2,8 +2,8 @@ #include <commctrl.h> VS_VERSION_INFO VERSIONINFO -FILEVERSION 5, 50, 100, 2418 -PRODUCTVERSION 5, 50, 100, 2418 +FILEVERSION 5, 61, 1, 2807 +PRODUCTVERSION 5, 61, 1, 2807 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { @@ -14,9 +14,9 @@ VALUE "CompanyName", "Alexander Roshal\0" VALUE "ProductName", "RAR decompression library\0" VALUE "FileDescription", "RAR decompression library\0" - VALUE "FileVersion", "5.50.0\0" - VALUE "ProductVersion", "5.50.0\0" - VALUE "LegalCopyright", "Copyright � Alexander Roshal 1993-2017\0" + VALUE "FileVersion", "5.61.1\0" + VALUE "ProductVersion", "5.61.1\0" + VALUE "LegalCopyright", "Copyright � Alexander Roshal 1993-2018\0" VALUE "OriginalFilename", "Unrar.dll\0" } } diff -Nru unrar-nonfree-5.5.8/encname.cpp unrar-nonfree-5.6.6/encname.cpp --- unrar-nonfree-5.5.8/encname.cpp 2017-08-11 22:56:22.000000000 +0900 +++ unrar-nonfree-5.6.6/encname.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -11,8 +11,8 @@ -void EncodeFileName::Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW, - size_t MaxDecSize) +void EncodeFileName::Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize, + wchar *NameW,size_t MaxDecSize) { size_t EncPos=0,DecPos=0; byte HighByte=EncPos<EncSize ? EncName[EncPos++] : 0; @@ -53,11 +53,11 @@ if (EncPos>=EncSize) break; byte Correction=EncName[EncPos++]; - for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++) + for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++) NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8); } else - for (Length+=2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++) + for (Length+=2;Length>0 && DecPos<MaxDecSize && DecPos<NameSize;Length--,DecPos++) NameW[DecPos]=Name[DecPos]; } break; diff -Nru unrar-nonfree-5.5.8/encname.hpp unrar-nonfree-5.6.6/encname.hpp --- unrar-nonfree-5.5.8/encname.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/encname.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -14,7 +14,7 @@ public: EncodeFileName(); size_t Encode(char *Name,wchar *NameW,byte *EncName); - void Decode(char *Name,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize); + void Decode(char *Name,size_t NameSize,byte *EncName,size_t EncSize,wchar *NameW,size_t MaxDecSize); }; #endif diff -Nru unrar-nonfree-5.5.8/errhnd.cpp unrar-nonfree-5.6.6/errhnd.cpp --- unrar-nonfree-5.5.8/errhnd.cpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/errhnd.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -41,9 +41,12 @@ uiMsg(UIERROR_FILECLOSE,FileName); SysErrMsg(); } -#if !defined(SILENT) || defined(RARDLL) - Exit(RARX_FATAL); -#endif + // We must not call Exit and throw an exception here, because this function + // is called from File object destructor and can be invoked when stack + // unwinding while handling another exception. Throwing a new exception + // when stack unwinding is prohibited and terminates a program. + // If necessary, we can check std::uncaught_exception() before throw. + SetErrorCode(RARX_FATAL); } @@ -267,6 +270,7 @@ #endif ErrHandler.UserBreak=true; + ErrHandler.SetDisableShutdown(); mprintf(St(MBreak)); #ifdef _WIN_ALL @@ -290,7 +294,7 @@ #endif #if defined(_WIN_ALL) && !defined(_MSC_VER) - // never reached, just to avoid a compiler warning + // Never reached, just to avoid a compiler warning return TRUE; #endif } @@ -322,36 +326,15 @@ } -void ErrorHandler::SysErrMsg() +bool ErrorHandler::GetSysErrMsg(wchar *Msg,size_t Size) { #if !defined(SFX_MODULE) && !defined(SILENT) #ifdef _WIN_ALL - wchar *lpMsgBuf=NULL; int ErrType=GetLastError(); - if (ErrType!=0 && FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL,ErrType,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&lpMsgBuf,0,NULL)) - { - wchar *CurMsg=lpMsgBuf; - while (CurMsg!=NULL) - { - while (*CurMsg=='\r' || *CurMsg=='\n') - CurMsg++; - if (*CurMsg==0) - break; - wchar *EndMsg=wcschr(CurMsg,'\r'); - if (EndMsg==NULL) - EndMsg=wcschr(CurMsg,'\n'); - if (EndMsg!=NULL) - { - *EndMsg=0; - EndMsg++; - } - uiMsg(UIERROR_SYSERRMSG,CurMsg); - CurMsg=EndMsg; - } - } - LocalFree( lpMsgBuf ); + if (ErrType!=0) + return FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, + NULL,ErrType,MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), + Msg,(DWORD)Size,NULL)!=0; #endif #if defined(_UNIX) || defined(_EMX) @@ -360,12 +343,46 @@ char *err=strerror(errno); if (err!=NULL) { - wchar Msg[1024]; - CharToWide(err,Msg,ASIZE(Msg)); - uiMsg(UIERROR_SYSERRMSG,Msg); + CharToWide(err,Msg,Size); + return true; } } #endif +#endif + return false; +} + + +void ErrorHandler::SysErrMsg() +{ +#if !defined(SFX_MODULE) && !defined(SILENT) + wchar Msg[1024]; + if (!GetSysErrMsg(Msg,ASIZE(Msg))) + return; +#ifdef _WIN_ALL + wchar *CurMsg=Msg; + while (CurMsg!=NULL) + { + while (*CurMsg=='\r' || *CurMsg=='\n') + CurMsg++; + if (*CurMsg==0) + break; + wchar *EndMsg=wcschr(CurMsg,'\r'); + if (EndMsg==NULL) + EndMsg=wcschr(CurMsg,'\n'); + if (EndMsg!=NULL) + { + *EndMsg=0; + EndMsg++; + } + uiMsg(UIERROR_SYSERRMSG,CurMsg); + CurMsg=EndMsg; + } +#endif + +#if defined(_UNIX) || defined(_EMX) + uiMsg(UIERROR_SYSERRMSG,Msg); +#endif #endif } diff -Nru unrar-nonfree-5.5.8/errhnd.hpp unrar-nonfree-5.6.6/errhnd.hpp --- unrar-nonfree-5.5.8/errhnd.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/errhnd.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -57,9 +57,11 @@ void SetSignalHandlers(bool Enable); void Throw(RAR_EXIT Code); void SetSilent(bool Mode) {Silent=Mode;}; + bool GetSysErrMsg(wchar *Msg,size_t Size); void SysErrMsg(); int GetSystemErrorCode(); void SetSystemErrorCode(int Code); + void SetDisableShutdown() {DisableShutdown=true;} bool IsShutdownEnabled() {return !DisableShutdown;} bool UserBreak; // Ctrl+Break is pressed. diff -Nru unrar-nonfree-5.5.8/extract.cpp unrar-nonfree-5.6.6/extract.cpp --- unrar-nonfree-5.5.8/extract.cpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/extract.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -59,7 +59,11 @@ { if (!PasswordCancelled) uiMsg(UIERROR_NOFILESTOEXTRACT,ArcName); - ErrHandler.SetErrorCode(RARX_NOFILES); + + // Other error codes may explain a reason of "no files extracted" clearer, + // so set it only if no other errors found (wrong mask set by user). + if (ErrHandler.GetErrorCode()==RARX_SUCCESS) + ErrHandler.SetErrorCode(RARX_NOFILES); } else if (!Cmd->DisableDone) @@ -83,7 +87,7 @@ FirstFile=true; #endif - PasswordAll=(Cmd->Password.IsSet()); + GlobalPassword=Cmd->Password.IsSet(); DataIO.UnpVolume=false; @@ -157,7 +161,7 @@ // This size is necessary to display the correct total progress indicator. wchar NextName[NM]; - wcscpy(NextName,Arc.FileName); + wcsncpyz(NextName,Arc.FileName,ASIZE(NextName)); while (true) { @@ -226,18 +230,6 @@ bool CmdExtract::ExtractCurrentFile(Archive &Arc,size_t HeaderSize,bool &Repeat) { - // We can get negative sizes in corrupt archive and it is unacceptable - // for size comparisons in CmdExtract::UnstoreFile and ComprDataIO::UnpRead, - // where we cast sizes to size_t and can exceed another read or available - // size. We could fix it when reading an archive. But we prefer to do it - // here, because this function is called directly in unrar.dll, so we fix - // bad parameters passed to dll. Also we want to see real negative sizes - // in the listing of corrupt archive. - if (Arc.FileHead.PackSize<0) - Arc.FileHead.PackSize=0; - if (Arc.FileHead.UnpSize<0) - Arc.FileHead.UnpSize=0; - wchar Command=Cmd->Command[0]; if (HeaderSize==0) if (DataIO.UnpVolume) @@ -245,8 +237,8 @@ #ifdef NOVOLUME return false; #else - // Supposing we unpack an old RAR volume without end of archive record - // and last file is not split between volumes. + // Supposing we unpack an old RAR volume without the end of archive + // record and last file is not split between volumes. if (!MergeArchive(Arc,&DataIO,false,Command)) { ErrHandler.SetErrorCode(RARX_WARNING); @@ -256,11 +248,12 @@ } else return false; + HEADER_TYPE HeaderType=Arc.GetHeaderType(); if (HeaderType!=HEAD_FILE) { #ifndef SFX_MODULE - if (HeaderType==HEAD3_OLDSERVICE && PrevProcessed) + if (Arc.Format==RARFMT15 && HeaderType==HEAD3_OLDSERVICE && PrevProcessed) SetExtraInfo20(Cmd,Arc,DestFileName); #endif if (HeaderType==HEAD_SERVICE && PrevProcessed) @@ -285,6 +278,19 @@ } PrevProcessed=false; + // We can get negative sizes in corrupt archive and it is unacceptable + // for size comparisons in ComprDataIO::UnpRead, where we cast sizes + // to size_t and can exceed another read or available size. We could fix it + // when reading an archive. But we prefer to do it here, because this + // function is called directly in unrar.dll, so we fix bad parameters + // passed to dll. Also we want to see real negative sizes in the listing + // of corrupt archive. To prevent uninitialized data access perform + // these checks after rejecting zero length and non-file headers above. + if (Arc.FileHead.PackSize<0) + Arc.FileHead.PackSize=0; + if (Arc.FileHead.UnpSize<0) + Arc.FileHead.UnpSize=0; + if (!Cmd->Recurse && MatchedArgs>=Cmd->FileArgs.ItemsCount() && AllMatchesExact) return false; @@ -317,6 +323,7 @@ if (wcsicomp(ArcName,CurVolName)!=0 && FileExist(ArcName)) { + wcsncpyz(Cmd->ArcName,ArcName,ASIZE(ArcName)); // For GUI "Delete archive after extraction". // If first volume name does not match the current name and if such // volume name really exists, let's unpack from this first volume. Repeat=true; @@ -427,7 +434,7 @@ return !Arc.Solid; // Can try extracting next file only in non-solid archive. } - while (true) // Repeat password prompt in case of wrong password here. + while (true) // Repeat the password prompt for wrong and empty passwords. { if (Arc.FileHead.Encrypted) { @@ -445,21 +452,8 @@ return false; } #endif - // Skip only the current encrypted file if empty password is entered. - // Actually our "cancel" code above intercepts empty passwords too now, - // so we keep the code below just in case we'll decide process empty - // and cancelled passwords differently sometimes. - if (!Cmd->Password.IsSet()) - { - ErrHandler.SetErrorCode(RARX_WARNING); -#ifdef RARDLL - Cmd->DllError=ERAR_MISSING_PASSWORD; -#endif - ExtrFile=false; - } } - // Set a password before creating the file, so we can skip creating // in case of wrong password. SecPassword FilePassword=Cmd->Password; @@ -479,12 +473,24 @@ memcmp(Arc.FileHead.PswCheck,PswCheck,SIZE_PSWCHECK)!=0 && !Arc.BrokenHeader) { - uiMsg(UIWAIT_BADPSW,ArcFileName); - - if (!PasswordAll) // If entered manually and not through -p<pwd>. + if (GlobalPassword) // For -p<pwd> or Ctrl+P. + { + // This message is used by Android GUI to reset cached passwords. + // Update appropriate code if changed. + uiMsg(UIERROR_BADPSW,ArcFileName); + } + else // For passwords entered manually. { + // This message is used by Android GUI and Windows GUI and SFX to + // reset cached passwords. Update appropriate code if changed. + uiMsg(UIWAIT_BADPSW,ArcFileName); Cmd->Password.Clean(); + + // Avoid new requests for unrar.dll to prevent the infinite loop + // if app always returns the same password. +#ifndef RARDLL continue; // Request a password again. +#endif } #ifdef RARDLL // If we already have ERAR_EOPEN as result of missing volume, @@ -779,19 +785,18 @@ void CmdExtract::UnstoreFile(ComprDataIO &DataIO,int64 DestUnpSize) { - // 512 KB and larger buffer reported to reduce performance on old XP - // computers with WDC WD2000JD HDD. According to test made by user - // 256 KB buffer is optimal. - Array<byte> Buffer(0x40000); - while (1) + Array<byte> Buffer(File::CopyBufferSize()); + while (true) { - uint Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); - if (Code==0 || (int)Code==-1) + int ReadSize=DataIO.UnpRead(&Buffer[0],Buffer.Size()); + if (ReadSize<=0) break; - Code=Code<DestUnpSize ? Code:(uint)DestUnpSize; - DataIO.UnpWrite(&Buffer[0],Code); - if (DestUnpSize>=0) - DestUnpSize-=Code; + int WriteSize=ReadSize<DestUnpSize ? ReadSize:(int)DestUnpSize; + if (WriteSize>0) + { + DataIO.UnpWrite(&Buffer[0],WriteSize); + DestUnpSize-=WriteSize; + } } } @@ -958,19 +963,17 @@ { if (!Cmd->Password.IsSet()) { - if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password) || !Cmd->Password.IsSet()) + if (!uiGetPassword(UIPASSWORD_FILE,ArcFileName,&Cmd->Password)/* || !Cmd->Password.IsSet()*/) { - // Suppress "test is ok" message in GUI if user entered - // an empty password or cancelled a password prompt. + // Suppress "test is ok" message if user cancelled the password prompt. uiMsg(UIERROR_INCERRCOUNT); - return false; } Cmd->ManualPassword=true; } #if !defined(SILENT) else - if (!PasswordAll && !Arc.FileHead.Solid) + if (!GlobalPassword && !Arc.FileHead.Solid) { eprintf(St(MUseCurPsw),ArcFileName); switch(Cmd->AllYes ? 1 : Ask(St(MYesNoAll))) @@ -982,7 +985,7 @@ return false; break; case 3: - PasswordAll=true; + GlobalPassword=true; break; } } diff -Nru unrar-nonfree-5.5.8/extract.hpp unrar-nonfree-5.6.6/extract.hpp --- unrar-nonfree-5.5.8/extract.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/extract.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -43,7 +43,7 @@ wchar ArcName[NM]; - bool PasswordAll; + bool GlobalPassword; bool PrevProcessed; // If previous file was successfully extracted or tested. wchar DestFileName[NM]; bool PasswordCancelled; diff -Nru unrar-nonfree-5.5.8/file.cpp unrar-nonfree-5.6.6/file.cpp --- unrar-nonfree-5.5.8/file.cpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/file.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -692,7 +692,7 @@ #ifndef SFX_MODULE int64 File::Copy(File &Dest,int64 Length) { - Array<char> Buffer(0x40000); + Array<byte> Buffer(File::CopyBufferSize()); int64 CopySize=0; bool CopyAll=(Length==INT64NDF); @@ -700,7 +700,7 @@ { Wait(); size_t SizeToRead=(!CopyAll && Length<(int64)Buffer.Size()) ? (size_t)Length:Buffer.Size(); - char *Buf=&Buffer[0]; + byte *Buf=&Buffer[0]; int ReadSize=Read(Buf,SizeToRead); if (ReadSize==0) break; diff -Nru unrar-nonfree-5.5.8/file.hpp unrar-nonfree-5.6.6/file.hpp --- unrar-nonfree-5.5.8/file.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/file.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -72,13 +72,16 @@ File(); virtual ~File(); void operator = (File &SrcFile); + + // Several functions below are 'virtual', because they are redefined + // by Archive for QOpen and by MultiFile for split files in WinRAR. virtual bool Open(const wchar *Name,uint Mode=FMF_READ); void TOpen(const wchar *Name); bool WOpen(const wchar *Name); bool Create(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); void TCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); bool WCreate(const wchar *Name,uint Mode=FMF_UPDATE|FMF_SHAREREAD); - bool Close(); + virtual bool Close(); // 'virtual' for MultiFile class. bool Delete(); bool Rename(const wchar *NewName); bool Write(const void *Data,size_t Size); @@ -96,7 +99,7 @@ void SetCloseFileTime(RarTime *ftm,RarTime *fta=NULL); static void SetCloseFileTimeByName(const wchar *Name,RarTime *ftm,RarTime *fta); void GetOpenFileTime(RarTime *ft); - bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; + virtual bool IsOpened() {return hFile!=FILE_BAD_HANDLE;}; // 'virtual' for MultiFile class. int64 FileLength(); void SetHandleType(FILE_HANDLETYPE Type) {HandleType=Type;} FILE_HANDLETYPE GetHandleType() {return HandleType;} @@ -121,6 +124,17 @@ #endif } #endif + static size_t CopyBufferSize() + { +#ifdef _WIN_ALL + // USB flash performance is poor with 64 KB buffer, 256+ KB resolved it. + // For copying from HDD to same HDD the best performance was with 256 KB + // buffer in XP and with 1 MB buffer in Win10. + return WinNT()==WNT_WXP ? 0x40000:0x100000; +#else + return 0x100000; +#endif + } }; #endif diff -Nru unrar-nonfree-5.5.8/filestr.cpp unrar-nonfree-5.6.6/filestr.cpp --- unrar-nonfree-5.5.8/filestr.cpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/filestr.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -46,26 +46,12 @@ // Set to really read size, so we can zero terminate it correctly. Data.Alloc(DataSize); - int LowEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0; + int LittleEndian=DataSize>=2 && Data[0]==255 && Data[1]==254 ? 1:0; int BigEndian=DataSize>=2 && Data[0]==254 && Data[1]==255 ? 1:0; bool Utf8=DataSize>=3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf; if (SrcCharset==RCH_DEFAULT) - { - if (LowEndian || BigEndian) - for (size_t I=2;I<DataSize;I++) - if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n') - { - SrcCharset=RCH_UNICODE; // High byte in UTF-16 char is found. - break; - } - if (Utf8) - { - Data.Push(0); // Need a zero terminated string for UtfToWide. - if (IsTextUtf8((const char *)(Data+3))) - SrcCharset=RCH_UTF8; - } - } + SrcCharset=DetectTextEncoding(&Data[0],DataSize); Array<wchar> DataW; @@ -83,16 +69,16 @@ if (SrcCharset==RCH_UNICODE) { size_t Start=2; // Skip byte order mark. - if (!LowEndian && !BigEndian) // No byte order mask. + if (!LittleEndian && !BigEndian) // No byte order mask. { Start=0; - LowEndian=1; + LittleEndian=1; } DataW.Alloc(Data.Size()/2+1); size_t End=Data.Size() & ~1; // We need even bytes number for UTF-16. for (size_t I=Start;I<End;I+=2) - DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LowEndian]*256; + DataW[(I-Start)/2]=Data[I+BigEndian]+Data[I+LittleEndian]*256; DataW[(End-Start)/2]=0; } @@ -160,3 +146,21 @@ } return true; } + + +RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize) +{ + if (DataSize>3 && Data[0]==0xef && Data[1]==0xbb && Data[2]==0xbf && + IsTextUtf8(Data+3,DataSize-3)) + return RCH_UTF8; + + bool LittleEndian=DataSize>2 && Data[0]==255 && Data[1]==254; + bool BigEndian=DataSize>2 && Data[0]==254 && Data[1]==255; + + if (LittleEndian || BigEndian) + for (size_t I=LittleEndian ? 3 : 2;I<DataSize;I+=2) + if (Data[I]<32 && Data[I]!='\r' && Data[I]!='\n') + return RCH_UNICODE; // High byte in UTF-16 char is found. + + return RCH_DEFAULT; +} diff -Nru unrar-nonfree-5.5.8/filestr.hpp unrar-nonfree-5.6.6/filestr.hpp --- unrar-nonfree-5.5.8/filestr.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/filestr.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -12,4 +12,6 @@ bool ExpandEnvStr=false ); +RAR_CHARSET DetectTextEncoding(const byte *Data,size_t DataSize); + #endif diff -Nru unrar-nonfree-5.5.8/hardlinks.cpp unrar-nonfree-5.6.6/hardlinks.cpp --- unrar-nonfree-5.5.8/hardlinks.cpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/hardlinks.cpp 2018-09-03 19:21:40.000000000 +0900 @@ -3,7 +3,12 @@ SlashToNative(NameExisting,NameExisting,NameExistingSize); // Not needed for RAR 5.1+ archives. if (!FileExist(NameExisting)) + { + uiMsg(UIERROR_HLINKCREATE,NameNew); + uiMsg(UIERROR_NOLINKTARGET); + ErrHandler.SetErrorCode(RARX_CREATE); return false; + } CreatePath(NameNew,true); #ifdef _WIN_ALL diff -Nru unrar-nonfree-5.5.8/headers.hpp unrar-nonfree-5.6.6/headers.hpp --- unrar-nonfree-5.5.8/headers.hpp 2017-08-11 22:56:23.000000000 +0900 +++ unrar-nonfree-5.6.6/headers.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -11,12 +11,7 @@ #define SIZEOF_SUBBLOCKHEAD 14 #define SIZEOF_COMMHEAD 13 #define SIZEOF_PROTECTHEAD 26 -#define SIZEOF_AVHEAD 14 -#define SIZEOF_SIGNHEAD 15 #define SIZEOF_UOHEAD 18 -#define SIZEOF_MACHEAD 22 -#define SIZEOF_EAHEAD 24 -#define SIZEOF_BEEAHEAD 24 #define SIZEOF_STREAMHEAD 26 #define VER_PACK 29 @@ -86,6 +81,8 @@ HEAD3_SERVICE=0x7a,HEAD3_ENDARC=0x7b }; + +// RAR 2.9 and earlier. enum { EA_HEAD=0x100,UO_HEAD=0x101,MAC_HEAD=0x102,BEEA_HEAD=0x103, NTACL_HEAD=0x104,STREAM_HEAD=0x105 }; @@ -323,23 +320,6 @@ }; -struct AVHeader:BaseBlock -{ - byte UnpVer; - byte Method; - byte AVVer; - uint AVInfoCRC; -}; - - -struct SignHeader:BaseBlock -{ - uint CreationTime; - ushort ArcNameSize; - ushort UserNameSize; -}; - - struct UnixOwnersHeader:SubBlockHeader { ushort OwnerNameSize; @@ -370,11 +350,4 @@ }; -struct MacFInfoHeader:SubBlockHeader -{ - uint fileType; - uint fileCreator; -}; - - #endif diff -Nru unrar-nonfree-5.5.8/loclang.hpp unrar-nonfree-5.6.6/loclang.hpp --- unrar-nonfree-5.5.8/loclang.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/loclang.hpp 2018-09-03 19:21:40.000000000 +0900 @@ -82,9 +82,9 @@ #define MCHelpSwIDP L"\n id[c,d,p,q] Disable messages" #define MCHelpSwIEML L"\n ieml[addr] Send archive by email" #define MCHelpSwIERR L"\n ierr Send all messages to stderr" -#define MCHelpSwILOG L"\n ilog[name] Log errors to file (registered versions only)" +#define MCHelpSwILOG L"\n ilog[name] Log errors to file" #define MCHelpSwINUL L"\n inul Disable all messages" -#define MCHelpSwIOFF L"\n ioff Turn PC off after completing an operation" +#define MCHelpSwIOFF L"\n ioff[n] Turn PC off after completing an operation" #define MCHelpSwISND L"\n isnd Enable sound" #define MCHelpSwIVER L"\n iver Display the version number" #define MCHelpSwK L"\n k Lock archive" @@ -294,7 +294,8 @@ #define MRprNoFiles L"\nNo files found" #define MLogUnexpEOF L"\nUnexpected end of archive" #define MRepAskReconst L"\nReconstruct archive structure ?" -#define MRecScanning L"\nScanning..." +#define MRRSearch L"\nSearching for recovery record" +#define MAnalyzeFileData L"\nAnalyzing file data" #define MRecRNotFound L"\nData recovery record not found" #define MRecRFound L"\nData recovery record found" #define MRecSecDamage L"\nSector %ld (offsets %lX...%lX) damaged" @@ -310,8 +311,6 @@ #define MErrLnkRead L"\nWARNING: Cannot read symbolic link %s" #define MSymLinkExists L"\nWARNING: Symbolic link %s already exists" #define MAskRetryCreate L"\nCannot create %s. Retry ?" -#define MListMACHead1 L"\n Mac OS file type: %c%c%c%c ; " -#define MListMACHead2 L"file creator: %c%c%c%c\n" #define MDataBadCRC L"\n%-20s : packed data checksum error in volume %s" #define MFileRO L"\n%s is read-only" #define MACLGetError L"\nWARNING: Cannot get %s security data\n" @@ -353,6 +352,7 @@ #define MRecVolLimit L"\nTotal number of usual and recovery volumes must not exceed %d" #define MVolumeNumber L"volume %d" #define MCannotDelete L"\nCannot delete %s" +#define MRecycleFailed L"\nCannot move some files and folders to Recycle Bin" #define MCalcCRC L"\nCalculating the checksum" #define MTooLargeSFXArc L"\nWARNING: Too large SFX archive. Windows cannot run the executable file exceeding 4 GB." #define MCalcCRCAllVol L"\nCalculating checksums of all volumes." @@ -360,9 +360,8 @@ #define MNewerRAR L"\nYou may need a newer version of RAR." #define MUnkEncMethod L"\nUnknown encryption method in %s" #define MWrongPassword L"\nThe specified password is incorrect." -#define MRepairing L"\nRepairing" #define MAreaDamaged L"\nCorrupt %d bytes at %08x %08x" -#define MBlocksRecovered L"\n%d blocks recovered." +#define MBlocksRecovered L"\n%u blocks are recovered, %u blocks are relocated" #define MRRDamaged L"\nRecovery record is corrupt." #define MTestingRR L"\nTesting the recovery record" #define MFailed L"Failed" @@ -376,6 +375,7 @@ #define MCopyingData L"\nCopying data" #define MErrCreateLnkS L"\nCannot create symbolic link %s" #define MErrCreateLnkH L"\nCannot create hard link %s" +#define MErrLnkTarget L"\nYou need to unpack the link target first" #define MNeedAdmin L"\nYou may need to run RAR as administrator" #define MDictOutMem L"\nNot enough memory for %d MB compression dictionary, changed to %d MB." #define MUseSmalllerDict L"\nPlease use a smaller compression dictionary." diff -Nru unrar-nonfree-5.5.8/makefile unrar-nonfree-5.6.6/makefile --- unrar-nonfree-5.5.8/makefile 2017-06-13 20:04:49.000000000 +0900 +++ unrar-nonfree-5.6.6/makefile 2017-11-22 15:53:39.000000000 +0900 @@ -3,7 +3,7 @@ # Linux using GCC CXX=c++ -CXXFLAGS=-O2 +CXXFLAGS=-O2 -Wno-logical-op-parentheses -Wno-switch -Wno-dangling-else LIBFLAGS=-fPIC DEFINES=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DRAR_SMP STRIP=strip diff -Nru unrar-nonfree-5.5.8/model.cpp unrar-nonfree-5.6.6/model.cpp --- unrar-nonfree-5.5.8/model.cpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/model.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -42,10 +42,14 @@ SubAlloc.InitSubAllocator(); InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1; MinContext = MaxContext = (RARPPM_CONTEXT*) SubAlloc.AllocContext(); + if (MinContext == NULL) + throw std::bad_alloc(); MinContext->Suffix=NULL; OrderFall=MaxOrder; MinContext->U.SummFreq=(MinContext->NumStats=256)+1; FoundState=MinContext->U.Stats=(RARPPM_STATE*)SubAlloc.AllocUnits(256/2); + if (FoundState == NULL) + throw std::bad_alloc(); for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) { MinContext->U.Stats[i].Symbol=i; @@ -166,9 +170,6 @@ inline RARPPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,RARPPM_STATE* p1) { -#ifdef __ICL - static -#endif RARPPM_STATE UpState; RARPPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor; RARPPM_STATE * p, * ps[MAX_O], ** pps=ps; @@ -202,7 +203,14 @@ { pc=p->Successor; break; + } + // We ensure that PPM order input parameter does not exceed MAX_O (64), + // so we do not really need this check and added it for extra safety. + // See CVE-2017-17969 for details. + if (pps>=ps+ASIZE(ps)) + return NULL; + *pps++ = p; } while ( pc->Suffix ); NO_LOOP: @@ -492,6 +500,12 @@ p++; } while (Model->CharMask[p->Symbol] == Model->EscCount); HiCnt += p->Freq; + + // We do not reuse PPMd coder in unstable state, so we do not really need + // this check and added it for extra safety. See CVE-2017-17969 for details. + if (pps>=ps+ASIZE(ps)) + return false; + *pps++ = p; } while ( --i ); Model->Coder.SubRange.scale += HiCnt; @@ -503,7 +517,12 @@ { HiCnt=0; while ((HiCnt += p->Freq) <= count) - p=*++pps; + { + pps++; + if (pps>=ps+ASIZE(ps)) // Extra safety check. + return false; + p=*pps; + } Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq; psee2c->update(); update2(Model,p); @@ -516,12 +535,15 @@ pps--; do { - Model->CharMask[(*++pps)->Symbol]=Model->EscCount; + pps++; + if (pps>=ps+ASIZE(ps)) // Extra safety check. + return false; + Model->CharMask[(*pps)->Symbol]=Model->EscCount; } while ( --i ); psee2c->Summ += Model->Coder.SubRange.scale; Model->NumMasked = NumStats; } - return(true); + return true; } diff -Nru unrar-nonfree-5.5.8/options.hpp unrar-nonfree-5.6.6/options.hpp --- unrar-nonfree-5.5.8/options.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/options.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -12,11 +12,7 @@ EXCL_SKIPWHOLEPATH, // -ep (exclude the path completely) EXCL_BASEPATH, // -ep1 (exclude the base part of path) EXCL_SAVEFULLPATH, // -ep2 (the full path without the disk letter) - EXCL_ABSPATH, // -ep3 (the full path with the disk letter) - - EXCL_SKIPABSPATH // Works as EXCL_BASEPATH for fully qualified paths - // and as EXCL_UNCHANGED for relative paths. - // Used by WinRAR GUI only. + EXCL_ABSPATH // -ep3 (the full path with the disk letter) }; enum {SOLID_NONE=0,SOLID_NORMAL=1,SOLID_COUNT=2,SOLID_FILEEXT=4, @@ -63,6 +59,11 @@ SAVECOPY_DUPLISTEXIT }; +enum POWER_MODE { + POWERMODE_KEEP=0,POWERMODE_OFF,POWERMODE_HIBERNATE,POWERMODE_SLEEP, + POWERMODE_RESTART +}; + struct FilterMode { FilterState State; @@ -85,10 +86,12 @@ bool InclAttrSet; size_t WinSize; wchar TempPath[NM]; -#ifdef USE_QOPEN wchar SFXModule[NM]; + +#ifdef USE_QOPEN QOPEN_MODE QOpenMode; #endif + bool ConfigDisabled; // Switch -cfg-. wchar ExtrPath[NM]; wchar CommentFile[NM]; @@ -128,6 +131,7 @@ Array<int64> NextVolSizes; uint CurVolNum; bool AllYes; + bool MoreInfo; // -im, show more information, used only in "WinRAR t" now. bool DisableSortSolid; int ArcTime; int ConvertNames; @@ -166,7 +170,7 @@ wchar EmailTo[NM]; uint VersionControl; bool AppendArcNameToPath; - bool Shutdown; + POWER_MODE Shutdown; EXTTIME_MODE xmtime; EXTTIME_MODE xctime; EXTTIME_MODE xatime; diff -Nru unrar-nonfree-5.5.8/os.hpp unrar-nonfree-5.6.6/os.hpp --- unrar-nonfree-5.5.8/os.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/os.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -22,7 +22,16 @@ #ifdef _WIN_ALL -#define STRICT + +// We got a report that just "#define STRICT" is incompatible with +// "#define STRICT 1" in Windows 10 SDK minwindef.h and depending on the order +// in which these statements are reached this may cause a compiler warning +// and build break for other projects incorporating this source. +// So we changed it to "#define STRICT 1". +#ifndef STRICT +#define STRICT 1 +#endif + #define UNICODE #undef WINVER #undef _WIN32_WINNT @@ -39,6 +48,8 @@ #include <prsht.h> #include <shlwapi.h> #pragma comment(lib, "Shlwapi.lib") +#include <PowrProf.h> +#pragma comment(lib, "PowrProf.lib") #include <shellapi.h> #include <shlobj.h> #include <winioctl.h> diff -Nru unrar-nonfree-5.5.8/pathfn.cpp unrar-nonfree-5.6.6/pathfn.cpp --- unrar-nonfree-5.5.8/pathfn.cpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/pathfn.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -260,9 +260,9 @@ { char *EnvStr=getenv("HOME"); if (EnvStr!=NULL) - GetWideName(EnvStr,NULL,Path,MaxSize); + CharToWide(EnvStr,Path,MaxSize); else - wcsncpyz(Path, ConfPath[0], MaxSize); + wcsncpyz(Path,ConfPath[0],MaxSize); return true; } Number--; @@ -969,7 +969,8 @@ if (IsPathDiv(Name[Src]) || Name[Src]==0) for (int I=Dest-1;I>0 && (Name[I]==' ' || Name[I]=='.');I--) { - if (IsPathDiv(Name[I-1])) // Permit path1/./path2 paths. + // Permit path1/./path2 and ../path1 paths. + if (Name[I]=='.' && (IsPathDiv(Name[I-1]) || Name[I-1]=='.' && I==1)) break; Dest--; } diff -Nru unrar-nonfree-5.5.8/qopen.cpp unrar-nonfree-5.6.6/qopen.cpp --- unrar-nonfree-5.5.8/qopen.cpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/qopen.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -61,17 +61,30 @@ void QuickOpen::Load(uint64 BlockPos) { - if (!Loaded) // If loading the first time, perform additional intialization. + if (!Loaded) { + // If loading for the first time, perform additional intialization. SeekPos=Arc->Tell(); UnsyncSeekPos=false; SaveFilePos SavePos(*Arc); Arc->Seek(BlockPos,SEEK_SET); - if (Arc->ReadHeader()==0 || Arc->GetHeaderType()!=HEAD_SERVICE || + + // If BlockPos points to original main header, we'll have the infinite + // recursion, because ReadHeader() for main header will attempt to load + // QOpen and call QuickOpen::Load again. If BlockPos points to long chain + // of other main headers, we'll have multiple recursive calls of this + // function wasting resources. So we prohibit QOpen temporarily to + // prevent this. ReadHeader() calls QOpen.Init and sets MainHead Locator + // and QOpenOffset fields, so we cannot use them to prohibit QOpen. + Arc->SetProhibitQOpen(true); + size_t ReadSize=Arc->ReadHeader(); + Arc->SetProhibitQOpen(false); + + if (ReadSize==0 || Arc->GetHeaderType()!=HEAD_SERVICE || !Arc->SubHead.CmpName(SUBHEAD_TYPE_QOPEN)) return; - QLHeaderPos=Arc->CurBlockPos; + QOHeaderPos=Arc->CurBlockPos; RawDataStart=Arc->Tell(); RawDataSize=Arc->SubHead.UnpSize; @@ -88,7 +101,10 @@ Arc->SubHead.HashKey,Arc->SubHead.PswCheck); else #endif + { + Loaded=false; return; + } } RawDataPos=0; @@ -156,7 +172,7 @@ // archive updating involve several passes. So if we detect that file // pointer is moved back, we reload quick open data from beginning. if (Method==SEEK_SET && (uint64)Offset<SeekPos && (uint64)Offset<LastReadHeaderPos) - Load(QLHeaderPos); + Load(QOHeaderPos); if (Method==SEEK_SET) SeekPos=Offset; @@ -234,10 +250,10 @@ return false; } - // If rest of block data crosses buffer boundary, read it in loop. - size_t DataLeft=ReadBufSize-ReadBufPos; + // If rest of block data crosses Buf boundary, read it in loop. while (SizeToRead>0) { + size_t DataLeft=ReadBufSize-ReadBufPos; size_t CurSizeToRead=Min(DataLeft,(size_t)SizeToRead); Raw.Read(Buf+ReadBufPos,CurSizeToRead); ReadBufPos+=CurSizeToRead; @@ -264,9 +280,11 @@ uint Flags=(uint)Raw.GetV(); uint64 Offset=Raw.GetV(); size_t HeaderSize=(size_t)Raw.GetV(); + if (HeaderSize>MAX_HEADER_SIZE_RAR5) + return false; LastReadHeader.Alloc(HeaderSize); Raw.GetB(&LastReadHeader[0],HeaderSize); // Calculate the absolute position as offset from quick open service header. - LastReadHeaderPos=QLHeaderPos-Offset; + LastReadHeaderPos=QOHeaderPos-Offset; return true; } diff -Nru unrar-nonfree-5.5.8/qopen.hpp unrar-nonfree-5.6.6/qopen.hpp --- unrar-nonfree-5.5.8/qopen.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/qopen.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -29,24 +29,24 @@ QuickOpenItem *ListStart; QuickOpenItem *ListEnd; - byte *Buf; - static const size_t MaxBufSize=0x10000; // Must be multiple of CRYPT_BLOCK_SIZE. - size_t CurBufSize; + byte *Buf; // Read quick open data here. + static const size_t MaxBufSize=0x10000; // Buf size, must be multiple of CRYPT_BLOCK_SIZE. + size_t CurBufSize; // Current size of buffered data in write mode. #ifndef RAR_NOCRYPT // For shell extension. CryptData Crypt; #endif bool Loaded; - uint64 QLHeaderPos; - uint64 RawDataStart; - uint64 RawDataSize; - uint64 RawDataPos; - size_t ReadBufSize; - size_t ReadBufPos; + uint64 QOHeaderPos; // Main QO header position. + uint64 RawDataStart; // Start of QO data, just after the main header. + uint64 RawDataSize; // Size of entire QO data. + uint64 RawDataPos; // Current read position in QO data. + size_t ReadBufSize; // Size of Buf data currently read from QO. + size_t ReadBufPos; // Current read position in Buf data. Array<byte> LastReadHeader; uint64 LastReadHeaderPos; uint64 SeekPos; - bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer. + bool UnsyncSeekPos; // QOpen SeekPos does not match an actual file pointer. public: QuickOpen(); ~QuickOpen(); diff -Nru unrar-nonfree-5.5.8/rar.cpp unrar-nonfree-5.6.6/rar.cpp --- unrar-nonfree-5.5.8/rar.cpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/rar.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -29,7 +29,7 @@ #if defined(_WIN_ALL) && !defined(SFX_MODULE) // Must be initialized, normal initialization can be skipped in case of // exception. - bool ShutdownOnClose=false; + POWER_MODE ShutdownOnClose=POWERMODE_KEEP; #endif try @@ -71,7 +71,6 @@ #endif uiInit(Cmd->Sound); - InitConsoleOptions(Cmd->MsgStream,Cmd->RedirectCharset); InitLogOptions(Cmd->LogName,Cmd->ErrlogCharset); ErrHandler.SetSilent(Cmd->AllYes || Cmd->MsgStream==MSG_NULL); @@ -94,8 +93,8 @@ } #if defined(_WIN_ALL) && !defined(SFX_MODULE) - if (ShutdownOnClose && ErrHandler.IsShutdownEnabled()) - Shutdown(); + if (ShutdownOnClose!=POWERMODE_KEEP && ErrHandler.IsShutdownEnabled()) + Shutdown(ShutdownOnClose); #endif ErrHandler.MainExit=true; return ErrHandler.GetErrorCode(); diff -Nru unrar-nonfree-5.5.8/rardefs.hpp unrar-nonfree-5.6.6/rardefs.hpp --- unrar-nonfree-5.5.8/rardefs.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/rardefs.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -4,7 +4,7 @@ #define Min(x,y) (((x)<(y)) ? (x):(y)) #define Max(x,y) (((x)>(y)) ? (x):(y)) -// Universal replacement of abs function for non-int arguments. +// Universal replacement of abs function. #define Abs(x) (((x)<0) ? -(x):(x)) #define ASIZE(x) (sizeof(x)/sizeof(x[0])) diff -Nru unrar-nonfree-5.5.8/rar.hpp unrar-nonfree-5.6.6/rar.hpp --- unrar-nonfree-5.5.8/rar.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/rar.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -29,6 +29,9 @@ #include "pathfn.hpp" #include "strfn.hpp" #include "strlist.hpp" +#ifdef _WIN_ALL +#include "isnt.hpp" +#endif #include "file.hpp" #include "crc.hpp" #include "ui.hpp" @@ -48,9 +51,6 @@ #include "filcreat.hpp" #include "consio.hpp" #include "system.hpp" -#ifdef _WIN_ALL -#include "isnt.hpp" -#endif #include "log.hpp" #include "rawint.hpp" #include "rawread.hpp" diff -Nru unrar-nonfree-5.5.8/rartypes.hpp unrar-nonfree-5.6.6/rartypes.hpp --- unrar-nonfree-5.5.8/rartypes.hpp 2017-08-11 22:56:24.000000000 +0900 +++ unrar-nonfree-5.6.6/rartypes.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -18,6 +18,9 @@ // Make 64 bit integer from two 32 bit. #define INT32TO64(high,low) ((((uint64)(high))<<32)+((uint64)low)) +// Maximum int64 value. +#define MAX_INT64 int64(INT32TO64(0x7fffffff,0xffffffff)) + // Special int64 value, large enough to never be found in real life. // We use it in situations, when we need to indicate that parameter // is not defined and probably should be calculated inside of function. diff -Nru unrar-nonfree-5.5.8/rdwrfn.cpp unrar-nonfree-5.6.6/rdwrfn.cpp --- unrar-nonfree-5.5.8/rdwrfn.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/rdwrfn.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -19,6 +19,7 @@ ShowProgress=true; TestMode=false; SkipUnpCRC=false; + NoFileHeader=false; PackVolume=false; UnpVolume=false; NextVolumeMissing=false; @@ -95,7 +96,7 @@ return -1; ReadSize=SrcFile->Read(ReadAddr,SizeToRead); FileHeader *hd=SubHead!=NULL ? SubHead:&SrcArc->FileHead; - if (hd->SplitAfter) + if (!NoFileHeader && hd->SplitAfter) PackedDataHash.Update(ReadAddr,ReadSize); } } diff -Nru unrar-nonfree-5.5.8/rdwrfn.hpp unrar-nonfree-5.6.6/rdwrfn.hpp --- unrar-nonfree-5.5.8/rdwrfn.hpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/rdwrfn.hpp 2018-09-03 19:21:41.000000000 +0900 @@ -32,6 +32,7 @@ bool ShowProgress; bool TestMode; bool SkipUnpCRC; + bool NoFileHeader; File *SrcFile; File *DestFile; @@ -62,6 +63,7 @@ void SetPackedSizeToRead(int64 Size) {UnpPackedSize=Size;} void SetTestMode(bool Mode) {TestMode=Mode;} void SetSkipUnpCRC(bool Skip) {SkipUnpCRC=Skip;} + void SetNoFileHeader(bool Mode) {NoFileHeader=Mode;} void SetFiles(File *SrcFile,File *DestFile); void SetCommand(CmdAdd *Cmd) {Command=Cmd;} void SetSubHeader(FileHeader *hd,int64 *Pos) {SubHead=hd;SubHeadPos=Pos;} diff -Nru unrar-nonfree-5.5.8/recvol5.cpp unrar-nonfree-5.6.6/recvol5.cpp --- unrar-nonfree-5.5.8/recvol5.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/recvol5.cpp 2018-09-03 19:21:41.000000000 +0900 @@ -139,8 +139,12 @@ wcsncpyz(ArcName,Name,ASIZE(ArcName)); wchar *Num=GetVolNumPart(ArcName); + if (Num==ArcName) + return false; // Number part is missing in the name. while (Num>ArcName && IsDigit(*(Num-1))) Num--; + if (Num==ArcName) + return false; // Entire volume name is numeric, not possible for REV file. wcsncpyz(Num,L"*.*",ASIZE(ArcName)-(Num-ArcName)); wchar FirstVolName[NM]; diff -Nru unrar-nonfree-5.5.8/resource.cpp unrar-nonfree-5.6.6/resource.cpp --- unrar-nonfree-5.5.8/resource.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/resource.cpp 2018-09-03 19:21:42.000000000 +0900 @@ -7,5 +7,14 @@ { return StringId; } + + +// Needed for Unix swprintf to convert %s to %ls in legacy language resources. +const wchar *StF(MSGID StringId) +{ + static wchar FormattedStr[512]; + PrintfPrepareFmt(St(StringId),FormattedStr,ASIZE(FormattedStr)); + return FormattedStr; +} #endif diff -Nru unrar-nonfree-5.5.8/resource.hpp unrar-nonfree-5.6.6/resource.hpp --- unrar-nonfree-5.5.8/resource.hpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/resource.hpp 2018-09-03 19:21:42.000000000 +0900 @@ -3,8 +3,10 @@ #ifdef RARDLL #define St(x) (L"") +#define StF(x) (L"") #else const wchar *St(MSGID StringId); +const wchar *StF(MSGID StringId); #endif diff -Nru unrar-nonfree-5.5.8/savepos.hpp unrar-nonfree-5.6.6/savepos.hpp --- unrar-nonfree-5.5.8/savepos.hpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/savepos.hpp 2018-09-03 19:21:42.000000000 +0900 @@ -14,7 +14,13 @@ } ~SaveFilePos() { - SaveFile->Seek(SavePos,SEEK_SET); + // If file is already closed by current exception processing, + // we would get uneeded error messages and an exception inside of + // exception and terminate if we try to seek without checking + // if file is still opened. We should not also restore the position + // if external code closed the file on purpose. + if (SaveFile->IsOpened()) + SaveFile->Seek(SavePos,SEEK_SET); } }; diff -Nru unrar-nonfree-5.5.8/scantree.cpp unrar-nonfree-5.6.6/scantree.cpp --- unrar-nonfree-5.5.8/scantree.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/scantree.cpp 2018-09-03 19:21:42.000000000 +0900 @@ -226,7 +226,7 @@ SpecPathLength=Name-CurMask; Depth=0; - wcscpy(OrigCurMask,CurMask); + wcsncpyz(OrigCurMask,CurMask,ASIZE(OrigCurMask)); return true; } @@ -350,16 +350,19 @@ if (Slash!=NULL) { wchar Mask[NM]; - wcscpy(Mask,Slash); + wcsncpyz(Mask,Slash,ASIZE(Mask)); if (Depth<SetAllMaskDepth) - wcscpy(Mask+1,PointToName(OrigCurMask)); + wcsncpyz(Mask+1,PointToName(OrigCurMask),ASIZE(Mask)-1); *Slash=0; - wcscpy(DirName,CurMask); + wcsncpyz(DirName,CurMask,ASIZE(DirName)); wchar *PrevSlash=wcsrchr(CurMask,CPATHDIVIDER); if (PrevSlash==NULL) - wcscpy(CurMask,Mask+1); + wcsncpyz(CurMask,Mask+1,ASIZE(CurMask)); else - wcscpy(PrevSlash,Mask); + { + *(PrevSlash+1)=0; + wcsncatz(CurMask,Mask,ASIZE(CurMask)); + } } if (GetDirs==SCAN_GETDIRSTWICE && FindFile::FastFind(DirName,FD,GetLinks) && FD->IsDir) @@ -397,8 +400,8 @@ wchar Mask[NM]; - wcscpy(Mask,FastFindFile ? MASKALL:PointToName(CurMask)); - wcscpy(CurMask,FD->Name); + wcsncpyz(Mask,FastFindFile ? MASKALL:PointToName(CurMask),ASIZE(Mask)); + wcsncpyz(CurMask,FD->Name,ASIZE(CurMask)); if (wcslen(CurMask)+wcslen(Mask)+1>=NM || Depth>=MAXSCANDEPTH-1) { diff -Nru unrar-nonfree-5.5.8/strfn.cpp unrar-nonfree-5.6.6/strfn.cpp --- unrar-nonfree-5.5.8/strfn.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/strfn.cpp 2018-09-03 19:21:42.000000000 +0900 @@ -28,7 +28,8 @@ } -// Convert archived names to Unicode. Allow user to select a code page in GUI. +// Convert archived names and comments to Unicode. +// Allows user to select a code page in GUI. void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding) { #if defined(_WIN_ALL) // Console Windows RAR. @@ -36,11 +37,12 @@ UtfToWide(Src,Dest,DestSize); else { - char NameA[NM]; + Array<char> NameA; if (Encoding==ACTW_OEM) { - IntToExt(Src,NameA,ASIZE(NameA)); - Src=NameA; + NameA.Alloc(DestSize+1); + IntToExt(Src,&NameA[0],NameA.Size()); + Src=&NameA[0]; } CharToWide(Src,Dest,DestSize); } @@ -58,6 +60,8 @@ } + + int stricomp(const char *s1,const char *s2) { #ifdef _WIN_ALL @@ -121,7 +125,8 @@ { #if defined(_WIN_ALL) // Convert to LPARAM first to avoid a warning in 64 bit mode. - return (int)(LPARAM)CharLowerA((LPSTR)ch); + // Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast] + return (int)(LPARAM)CharLowerA((LPSTR)(uintptr_t)ch); #else return tolower(ch); #endif @@ -132,7 +137,8 @@ { #if defined(_WIN_ALL) // Convert to LPARAM first to avoid a warning in 64 bit mode. - return (int)(LPARAM)CharUpperA((LPSTR)ch); + // Convert to uintptr_t to avoid Clang/win error: cast to 'char *' from smaller integer type 'unsigned char' [-Werror,-Wint-to-pointer-cast] + return (int)(LPARAM)CharUpperA((LPSTR)(uintptr_t)ch); #else return toupper(ch); #endif @@ -428,7 +434,7 @@ } -#ifndef SILENT +#ifndef RARDLL // For compatibility with existing translations we use %s to print Unicode // strings in format strings and convert them to %ls here. %s could work // without such conversion in Windows, but not in Unix wprintf. diff -Nru unrar-nonfree-5.5.8/strfn.hpp unrar-nonfree-5.6.6/strfn.hpp --- unrar-nonfree-5.5.8/strfn.hpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/strfn.hpp 2018-09-03 19:21:42.000000000 +0900 @@ -8,6 +8,7 @@ enum ACTW_ENCODING { ACTW_DEFAULT, ACTW_OEM, ACTW_UTF8}; void ArcCharToWide(const char *Src,wchar *Dest,size_t DestSize,ACTW_ENCODING Encoding); + int stricomp(const char *s1,const char *s2); int strnicomp(const char *s1,const char *s2,size_t n); wchar* RemoveEOL(wchar *Str); @@ -43,7 +44,7 @@ void itoa(int64 n,wchar *Str,size_t MaxSize); const wchar* GetWide(const char *Src); const wchar* GetCmdParam(const wchar *CmdLine,wchar *Param,size_t MaxSize); -#ifndef SILENT +#ifndef RARDLL void PrintfPrepareFmt(const wchar *Org,wchar *Cvt,size_t MaxSize); #endif diff -Nru unrar-nonfree-5.5.8/strlist.hpp unrar-nonfree-5.6.6/strlist.hpp --- unrar-nonfree-5.5.8/strlist.hpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/strlist.hpp 2018-09-03 19:21:42.000000000 +0900 @@ -7,7 +7,7 @@ Array<wchar> StringData; size_t CurPos; - uint StringsCount; + size_t StringsCount; size_t SaveCurPos[16],SavePosNumber; public: @@ -21,7 +21,7 @@ wchar* GetString(); bool GetString(wchar **Str); void Rewind(); - uint ItemsCount() {return StringsCount;}; + size_t ItemsCount() {return StringsCount;}; size_t GetCharCount() {return StringData.Size();} bool Search(const wchar *Str,bool CaseSensitive); void SavePosition(); diff -Nru unrar-nonfree-5.5.8/suballoc.cpp unrar-nonfree-5.6.6/suballoc.cpp --- unrar-nonfree-5.5.8/suballoc.cpp 2017-08-11 22:56:25.000000000 +0900 +++ unrar-nonfree-5.6.6/suballoc.cpp 2018-09-03 19:21:42.000000000 +0900 @@ -80,7 +80,7 @@ { uint t=SASize << 20; if (SubAllocatorSize == t) - return TRUE; + return true; StopSubAllocator(); // Original algorithm expects FIXED_UNIT_SIZE, but actual structure size @@ -91,7 +91,7 @@ if ((HeapStart=(byte *)malloc(AllocSize)) == NULL) { ErrHandler.MemoryError(); - return FALSE; + return false; } // HeapEnd did not present in original algorithm. We added it to control @@ -99,7 +99,7 @@ HeapEnd=HeapStart+AllocSize-UNIT_SIZE; SubAllocatorSize=t; - return TRUE; + return true; } @@ -215,13 +215,13 @@ GlueCount--; i=U2B(Indx2Units[indx]); int j=FIXED_UNIT_SIZE*Indx2Units[indx]; - if (FakeUnitsStart-pText > j) + if (FakeUnitsStart - pText > j) { - FakeUnitsStart-=j; + FakeUnitsStart -= j; UnitsStart -= i; - return(UnitsStart); + return UnitsStart; } - return(NULL); + return NULL; } } while ( !FreeList[i].next ); void* RetVal=RemoveNode(i); diff -Nru unrar-nonfree-5.5.8/system.cpp unrar-nonfree-5.6.6/system.cpp --- unrar-nonfree-5.5.8/system.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/system.cpp 2018-09-03 19:21:42.000000000 +0900 @@ -102,7 +102,7 @@ #if defined(_WIN_ALL) && !defined(SFX_MODULE) -void Shutdown() +void Shutdown(POWER_MODE Mode) { HANDLE hToken; TOKEN_PRIVILEGES tkp; @@ -114,7 +114,14 @@ AdjustTokenPrivileges(hToken,FALSE,&tkp,0,(PTOKEN_PRIVILEGES)NULL,0); } - ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE|EWX_POWEROFF,SHTDN_REASON_FLAG_PLANNED); + if (Mode==POWERMODE_OFF) + ExitWindowsEx(EWX_SHUTDOWN|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED); + if (Mode==POWERMODE_SLEEP) + SetSuspendState(FALSE,FALSE,FALSE); + if (Mode==POWERMODE_HIBERNATE) + SetSuspendState(TRUE,FALSE,FALSE); + if (Mode==POWERMODE_RESTART) + ExitWindowsEx(EWX_REBOOT|EWX_FORCE,SHTDN_REASON_FLAG_PLANNED); } #endif diff -Nru unrar-nonfree-5.5.8/system.hpp unrar-nonfree-5.6.6/system.hpp --- unrar-nonfree-5.5.8/system.hpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/system.hpp 2018-09-03 19:21:42.000000000 +0900 @@ -22,7 +22,7 @@ clock_t MonoClock(); void Wait(); bool EmailFile(const wchar *FileName,const wchar *MailToW); -void Shutdown(); +void Shutdown(POWER_MODE Mode); #ifdef _WIN_ALL HMODULE WINAPI LoadSysLibrary(const wchar *Name); diff -Nru unrar-nonfree-5.5.8/timefn.cpp unrar-nonfree-5.6.6/timefn.cpp --- unrar-nonfree-5.5.8/timefn.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/timefn.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -25,9 +25,9 @@ // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime. FILETIME rft; SystemTimeToFileTime(&st1,&rft); - int64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)- - INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ - INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime); + uint64 Corrected=INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime)- + INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ + INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime); lft.dwLowDateTime=(DWORD)Corrected; lft.dwHighDateTime=(DWORD)(Corrected>>32); } @@ -100,9 +100,9 @@ // Correct precision loss (low 4 decimal digits) in FileTimeToSystemTime. FILETIME rft; SystemTimeToFileTime(&st2,&rft); - int64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)- - INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ - INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime); + uint64 Corrected=INT32TO64(lft.dwHighDateTime,lft.dwLowDateTime)- + INT32TO64(rft.dwHighDateTime,rft.dwLowDateTime)+ + INT32TO64(ft.dwHighDateTime,ft.dwLowDateTime); ft.dwLowDateTime=(DWORD)Corrected; ft.dwHighDateTime=(DWORD)(Corrected>>32); } diff -Nru unrar-nonfree-5.5.8/uiconsole.cpp unrar-nonfree-5.6.6/uiconsole.cpp --- unrar-nonfree-5.5.8/uiconsole.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/uiconsole.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -100,6 +100,7 @@ Log(Str[0],St(MWrongPassword)); break; case UIERROR_MEMORY: + mprintf(L"\n"); Log(NULL,St(MErrOutMem)); break; case UIERROR_FILEOPEN: @@ -124,6 +125,9 @@ case UIERROR_FILEDELETE: Log(Str[0],St(MCannotDelete),Str[1]); break; + case UIERROR_RECYCLEFAILED: + Log(Str[0],St(MRecycleFailed)); + break; case UIERROR_FILERENAME: Log(Str[0],St(MErrRename),Str[1],Str[2]); break; @@ -147,6 +151,10 @@ case UIERROR_HLINKCREATE: Log(NULL,St(MErrCreateLnkH),Str[0]); break; + case UIERROR_NOLINKTARGET: + Log(NULL,St(MErrLnkTarget)); + mprintf(L" "); // For progress percent. + break; case UIERROR_NEEDADMIN: Log(NULL,St(MNeedAdmin)); break; @@ -339,7 +347,10 @@ bool uiGetPassword(UIPASSWORD_TYPE Type,const wchar *FileName,SecPassword *Password) { - return GetConsolePassword(Type,FileName,Password); + // Unlike GUI we cannot provide Cancel button here, so we use the empty + // password to abort. Otherwise user not knowing a password would need to + // press Ctrl+C multiple times to quit from infinite password request loop. + return GetConsolePassword(Type,FileName,Password) && Password->IsSet(); } diff -Nru unrar-nonfree-5.5.8/ui.hpp unrar-nonfree-5.6.6/ui.hpp --- unrar-nonfree-5.5.8/ui.hpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/ui.hpp 2018-09-03 19:21:43.000000000 +0900 @@ -10,15 +10,15 @@ UIERROR_SYSERRMSG, UIERROR_GENERALERRMSG, UIERROR_INCERRCOUNT, UIERROR_CHECKSUM, UIERROR_CHECKSUMENC, UIERROR_CHECKSUMPACKED, UIERROR_BADPSW, UIERROR_MEMORY, UIERROR_FILEOPEN, UIERROR_FILECREATE, - UIERROR_FILECLOSE, UIERROR_FILESEEK, UIERROR_FILEREAD, - UIERROR_FILEWRITE, UIERROR_FILEDELETE, UIERROR_FILERENAME, + UIERROR_FILECLOSE, UIERROR_FILESEEK, UIERROR_FILEREAD, UIERROR_FILEWRITE, + UIERROR_FILEDELETE, UIERROR_RECYCLEFAILED, UIERROR_FILERENAME, UIERROR_FILEATTR, UIERROR_FILECOPY, UIERROR_FILECOPYHINT, UIERROR_DIRCREATE, UIERROR_SLINKCREATE, UIERROR_HLINKCREATE, - UIERROR_NEEDADMIN, UIERROR_ARCBROKEN, UIERROR_HEADERBROKEN, - UIERROR_MHEADERBROKEN, UIERROR_FHEADERBROKEN, UIERROR_SUBHEADERBROKEN, - UIERROR_SUBHEADERUNKNOWN, UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, - UIERROR_UNKNOWNMETHOD, UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, - UIERROR_NEWERRAR, UIERROR_NOTSFX, UIERROR_OLDTOSFX, + UIERROR_NOLINKTARGET, UIERROR_NEEDADMIN, UIERROR_ARCBROKEN, + UIERROR_HEADERBROKEN, UIERROR_MHEADERBROKEN, UIERROR_FHEADERBROKEN, + UIERROR_SUBHEADERBROKEN, UIERROR_SUBHEADERUNKNOWN, + UIERROR_SUBHEADERDATABROKEN, UIERROR_RRDAMAGED, UIERROR_UNKNOWNMETHOD, + UIERROR_UNKNOWNENCMETHOD, UIERROR_RENAMING, UIERROR_NEWERRAR, UIERROR_NOTSFX, UIERROR_OLDTOSFX, UIERROR_WRONGSFXVER, UIERROR_ALREADYENC, UIERROR_DICTOUTMEM, UIERROR_USESMALLERDICT, UIERROR_MODIFYUNKNOWN, UIERROR_MODIFYOLD, UIERROR_MODIFYLOCKED, UIERROR_MODIFYVOLUME, UIERROR_NOTVOLUME, @@ -39,8 +39,8 @@ UIERROR_ULINKREAD, UIERROR_ULINKEXIST, UIMSG_FIRST, - UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_RRFOUND, - UIMSG_RRNOTFOUND, UIMSG_RRDAMAGED, UIMSG_BLOCKSRECOVERED, + UIMSG_STRING, UIMSG_BUILD, UIMSG_RRSEARCH, UIMSG_ANALYZEFILEDATA, + UIMSG_RRFOUND, UIMSG_RRNOTFOUND, UIMSG_RRDAMAGED, UIMSG_BLOCKSRECOVERED, UIMSG_COPYINGDATA, UIMSG_AREADAMAGED, UIMSG_SECTORDAMAGED, UIMSG_SECTORRECOVERED, UIMSG_SECTORNOTRECOVERED, UIMSG_FOUND, UIMSG_CORRECTINGNAME, UIMSG_BADARCHIVE, UIMSG_CREATING, UIMSG_RENAMING, diff -Nru unrar-nonfree-5.5.8/ulinks.cpp unrar-nonfree-5.6.6/ulinks.cpp --- unrar-nonfree-5.5.8/ulinks.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/ulinks.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -50,8 +50,11 @@ char Target[NM]; if (IsLink(Arc.FileHead.FileAttr)) { - size_t DataSize=Min(Arc.FileHead.PackSize,ASIZE(Target)-1); - DataIO.UnpRead((byte *)Target,DataSize); + size_t DataSize=(size_t)Arc.FileHead.PackSize; + if (DataSize>ASIZE(Target)-1) + return false; + if ((size_t)DataIO.UnpRead((byte *)Target,DataSize)!=DataSize) + return false; Target[DataSize]=0; DataIO.UnpHash.Init(Arc.FileHead.FileHash.Type,1); diff -Nru unrar-nonfree-5.5.8/unicode.cpp unrar-nonfree-5.6.6/unicode.cpp --- unrar-nonfree-5.5.8/unicode.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unicode.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -36,7 +36,25 @@ mbstate_t ps; // Use thread safe external state based functions. memset (&ps, 0, sizeof(ps)); const wchar *SrcParam=Src; // wcsrtombs can change the pointer. + + // Some implementations of wcsrtombs can cause memory analyzing tools + // like valgrind to report uninitialized data access. It happens because + // internally these implementations call SSE4 based wcslen function, + // which reads 16 bytes at once including those beyond of trailing 0. size_t ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps); + + if (ResultingSize==(size_t)-1 && errno==EILSEQ) + { + // Aborted on inconvertible character not zero terminating the result. + // EILSEQ helps to distinguish it from small output buffer abort. + // We want to convert as much as we can, so we clean the output buffer + // and repeat conversion. + memset (&ps, 0, sizeof(ps)); + SrcParam=Src; // wcsrtombs can change the pointer. + memset(Dest,0,DestSize); + ResultingSize=wcsrtombs(Dest,&SrcParam,DestSize,&ps); + } + if (ResultingSize==(size_t)-1) RetCode=false; if (ResultingSize==0 && *Src!=0) @@ -120,21 +138,21 @@ if (wcschr(Src,(wchar)MappedStringMark)==NULL) return false; + // Seems to be that wcrtomb in some memory analyzing libraries + // can produce uninitilized output while reporting success on garbage input. + // So we clean the destination to calm analyzers. + memset(Dest,0,DestSize); + Success=true; uint SrcPos=0,DestPos=0; - while (DestPos<DestSize-MB_CUR_MAX) + while (Src[SrcPos]!=0 && DestPos<DestSize-MB_CUR_MAX) { - if (Src[SrcPos]==0) - { - Dest[DestPos]=0; - break; - } if (uint(Src[SrcPos])==MappedStringMark) { SrcPos++; continue; } - // For security reasons do not retore low ASCII codes, so mapping cannot + // For security reasons do not restore low ASCII codes, so mapping cannot // be used to hide control codes like path separators. if (uint(Src[SrcPos])>=MapAreaStart+0x80 && uint(Src[SrcPos])<MapAreaStart+0x100) Dest[DestPos++]=char(uint(Src[SrcPos++])-MapAreaStart); @@ -142,14 +160,18 @@ { mbstate_t ps; memset(&ps,0,sizeof(ps)); - if (wcrtomb(Dest+DestPos,Src[SrcPos],&ps)==-1) + if (wcrtomb(Dest+DestPos,Src[SrcPos],&ps)==(size_t)-1) + { + Dest[DestPos]='_'; Success=false; + } SrcPos++; memset(&ps,0,sizeof(ps)); int Length=mbrlen(Dest+DestPos,MB_CUR_MAX,&ps); DestPos+=Max(Length,1); } } + Dest[Min(DestPos,DestSize-1)]=0; return true; } #endif @@ -170,13 +192,13 @@ { if (Src[SrcPos]==0) { - Dest[DestPos]=0; Success=true; break; } mbstate_t ps; memset(&ps,0,sizeof(ps)); - if (mbrtowc(Dest+DestPos,Src+SrcPos,MB_CUR_MAX,&ps)==-1) + size_t res=mbrtowc(Dest+DestPos,Src+SrcPos,MB_CUR_MAX,&ps); + if (res==(size_t)-1 || res==(size_t)-2) { // For security reasons we do not want to map low ASCII characters, // so we do not have additional .. and path separator codes. @@ -202,6 +224,7 @@ DestPos++; } } + Dest[Min(DestPos,DestSize-1)]=0; } #endif @@ -281,7 +304,7 @@ if (*Src<0x800) Size+=2; else - if (*Src<0x10000) + if ((uint)*Src<0x10000) //(uint) to avoid Clang/win "always true" warning for 16-bit wchar_t. { if (Src[0]>=0xd800 && Src[0]<=0xdbff && Src[1]>=0xdc00 && Src[1]<=0xdfff) { @@ -292,13 +315,12 @@ Size+=3; } else - if (*Src<0x200000) + if ((uint)*Src<0x200000) //(uint) to avoid Clang/win "always true" warning for 16-bit wchar_t. Size+=4; return Size+1; // Include terminating zero. } -// Dest can be NULL if we only need to check validity of Src. bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize) { bool Success=true; @@ -347,40 +369,56 @@ Success=false; break; } - if (Dest!=NULL && --dsize<0) + if (--dsize<0) break; if (d>0xffff) { - if (Dest!=NULL && --dsize<0) + if (--dsize<0) break; if (d>0x10ffff) // UTF-8 must end at 0x10ffff according to RFC 3629. { Success=false; continue; } - if (Dest!=NULL) - if (sizeof(*Dest)==2) // Use the surrogate pair. - { - *(Dest++)=((d-0x10000)>>10)+0xd800; - *(Dest++)=(d&0x3ff)+0xdc00; - } - else - *(Dest++)=d; + if (sizeof(*Dest)==2) // Use the surrogate pair. + { + *(Dest++)=((d-0x10000)>>10)+0xd800; + *(Dest++)=(d&0x3ff)+0xdc00; + } + else + *(Dest++)=d; } else - if (Dest!=NULL) - *(Dest++)=d; + *(Dest++)=d; } - if (Dest!=NULL) - *Dest=0; + *Dest=0; return Success; } +// For zero terminated strings. +bool IsTextUtf8(const byte *Src) +{ + return IsTextUtf8(Src,strlen((const char *)Src)); +} + + // Source data can be both with and without UTF-8 BOM. -bool IsTextUtf8(const char *Src) +bool IsTextUtf8(const byte *Src,size_t SrcSize) { - return UtfToWide(Src,NULL,0); + while (SrcSize-- > 0) + { + byte C=*(Src++); + int HighOne=0; // Number of leftmost '1' bits. + for (byte Mask=0x80;Mask!=0 && (C & Mask)!=0;Mask>>=1) + HighOne++; + if (HighOne==1 || HighOne>6) + return false; + while (--HighOne > 0) + if (SrcSize-- <= 0 || (*(Src++) & 0xc0)!=0x80) + return false; + } + return true; } @@ -511,7 +549,7 @@ int64 atoilw(const wchar *s) { bool sign=false; - if (*s=='-') + if (*s=='-') // We do use signed integers here, for example, in GUI SFX. { s++; sign=true; diff -Nru unrar-nonfree-5.5.8/unicode.hpp unrar-nonfree-5.6.6/unicode.hpp --- unrar-nonfree-5.5.8/unicode.hpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unicode.hpp 2018-09-03 19:21:43.000000000 +0900 @@ -12,7 +12,8 @@ void WideToUtf(const wchar *Src,char *Dest,size_t DestSize); size_t WideToUtfSize(const wchar *Src); bool UtfToWide(const char *Src,wchar *Dest,size_t DestSize); -bool IsTextUtf8(const char *Src); +bool IsTextUtf8(const byte *Src); +bool IsTextUtf8(const byte *Src,size_t SrcSize); int wcsicomp(const wchar *s1,const wchar *s2); int wcsnicomp(const wchar *s1,const wchar *s2,size_t n); diff -Nru unrar-nonfree-5.5.8/unpack20.cpp unrar-nonfree-5.6.6/unpack20.cpp --- unrar-nonfree-5.5.8/unpack20.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpack20.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -2,7 +2,8 @@ void Unpack::CopyString20(uint Length,uint Distance) { - LastDist=OldDist[OldDistPtr++ & 3]=Distance; + LastDist=OldDist[OldDistPtr++]=Distance; + OldDistPtr = OldDistPtr & 3; // Needed if RAR 1.5 file is called after RAR 2.0. LastLength=Length; DestUnpSize-=Length; CopyString(Length,Distance); @@ -248,7 +249,7 @@ MakeDecodeTables(&Table[NC20],&BlockTables.DD,DC20); MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20); } - memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20)); + memcpy(UnpOldTable20,Table,TableSize); return true; } diff -Nru unrar-nonfree-5.5.8/unpack30.cpp unrar-nonfree-5.6.6/unpack30.cpp --- unrar-nonfree-5.5.8/unpack30.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpack30.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -358,7 +358,7 @@ } -bool Unpack::AddVMCode(uint FirstByte,byte *Code,int CodeSize) +bool Unpack::AddVMCode(uint FirstByte,byte *Code,uint CodeSize) { VMCodeInp.InitBitInput(); memcpy(VMCodeInp.InBuf,Code,Min(BitInput::MAX_SIZE,CodeSize)); @@ -470,7 +470,7 @@ if (NewFilter) { uint VMCodeSize=RarVM::ReadData(VMCodeInp); - if (VMCodeSize>=0x10000 || VMCodeSize==0) + if (VMCodeSize>=0x10000 || VMCodeSize==0 || VMCodeInp.InAddr+VMCodeSize>CodeSize) return false; Array<byte> VMCode(VMCodeSize); for (uint I=0;I<VMCodeSize;I++) diff -Nru unrar-nonfree-5.5.8/unpack50.cpp unrar-nonfree-5.6.6/unpack50.cpp --- unrar-nonfree-5.5.8/unpack50.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpack50.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -42,7 +42,7 @@ break; } - if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr) + if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) diff -Nru unrar-nonfree-5.5.8/unpack50mt.cpp unrar-nonfree-5.6.6/unpack50mt.cpp --- unrar-nonfree-5.5.8/unpack50mt.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpack50mt.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -451,7 +451,7 @@ while (Item<Border) { UnpPtr&=MaxWinMask; - if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr) + if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) @@ -559,7 +559,7 @@ break; } } - if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_LZ_MATCH+3 && WriteBorder!=UnpPtr) + if (((WriteBorder-UnpPtr) & MaxWinMask)<MAX_INC_LZ_MATCH && WriteBorder!=UnpPtr) { UnpWriteBuf(); if (WrittenFileSize>DestUnpSize) diff -Nru unrar-nonfree-5.5.8/unpack.hpp unrar-nonfree-5.6.6/unpack.hpp --- unrar-nonfree-5.5.8/unpack.hpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpack.hpp 2018-09-03 19:21:43.000000000 +0900 @@ -329,7 +329,7 @@ bool ReadEndOfBlock(); bool ReadVMCode(); bool ReadVMCodePPM(); - bool AddVMCode(uint FirstByte,byte *Code,int CodeSize); + bool AddVMCode(uint FirstByte,byte *Code,uint CodeSize); int SafePPMDecodeChar(); bool ReadTables30(); bool UnpReadBuf30(); @@ -395,8 +395,12 @@ uint GetChar() { if (Inp.InAddr>BitInput::MAX_SIZE-30) + { UnpReadBuf(); - return(Inp.InBuf[Inp.InAddr++]); + if (Inp.InAddr>=BitInput::MAX_SIZE) // If nothing was read. + return 0; + } + return Inp.InBuf[Inp.InAddr++]; } }; diff -Nru unrar-nonfree-5.5.8/unpackinline.cpp unrar-nonfree-5.6.6/unpackinline.cpp --- unrar-nonfree-5.5.8/unpackinline.cpp 2017-08-11 22:56:26.000000000 +0900 +++ unrar-nonfree-5.6.6/unpackinline.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -13,7 +13,7 @@ _forceinline void Unpack::CopyString(uint Length,uint Distance) { size_t SrcPtr=UnpPtr-Distance; - if (SrcPtr<MaxWinSize-MAX_LZ_MATCH && UnpPtr<MaxWinSize-MAX_LZ_MATCH) + if (SrcPtr<MaxWinSize-MAX_INC_LZ_MATCH && UnpPtr<MaxWinSize-MAX_INC_LZ_MATCH) { // If we are not close to end of window, we do not need to waste time // to "& MaxWinMask" pointer protection. @@ -46,7 +46,7 @@ { // In theory we still could overlap here. // Supposing Distance == MaxWinSize - 1 we have memcpy(Src, Src + 1, 8). - // But for real RAR archives Distance <= MaxWinSize - MAX_LZ_MATCH + // But for real RAR archives Distance <= MaxWinSize - MAX_INC_LZ_MATCH // always, so overlap here is impossible. // This memcpy expanded inline by MSVC. We could also use uint64 diff -Nru unrar-nonfree-5.5.8/version.hpp unrar-nonfree-5.6.6/version.hpp --- unrar-nonfree-5.5.8/version.hpp 2017-08-11 22:56:27.000000000 +0900 +++ unrar-nonfree-5.6.6/version.hpp 2018-09-03 19:21:43.000000000 +0900 @@ -1,6 +1,6 @@ #define RARVER_MAJOR 5 -#define RARVER_MINOR 50 -#define RARVER_BETA 0 -#define RARVER_DAY 11 -#define RARVER_MONTH 8 -#define RARVER_YEAR 2017 +#define RARVER_MINOR 61 +#define RARVER_BETA 1 +#define RARVER_DAY 3 +#define RARVER_MONTH 9 +#define RARVER_YEAR 2018 diff -Nru unrar-nonfree-5.5.8/win32acl.cpp unrar-nonfree-5.6.6/win32acl.cpp --- unrar-nonfree-5.5.8/win32acl.cpp 2017-08-11 22:56:27.000000000 +0900 +++ unrar-nonfree-5.6.6/win32acl.cpp 2018-09-03 19:21:43.000000000 +0900 @@ -54,7 +54,10 @@ if (!SetCode) { uiMsg(UIERROR_ACLSET,Arc.FileName,FileName); + DWORD LastError=GetLastError(); ErrHandler.SysErrMsg(); + if (LastError==ERROR_ACCESS_DENIED && !IsUserAdmin()) + uiMsg(UIERROR_NEEDADMIN); ErrHandler.SetErrorCode(RARX_WARNING); } } @@ -86,7 +89,10 @@ if (!SetCode) { uiMsg(UIERROR_ACLSET,Arc.FileName,FileName); + DWORD LastError=GetLastError(); ErrHandler.SysErrMsg(); + if (LastError==ERROR_ACCESS_DENIED && !IsUserAdmin()) + uiMsg(UIERROR_NEEDADMIN); ErrHandler.SetErrorCode(RARX_WARNING); } }