Hello community, here is the log from the commit of package unrar for openSUSE:Factory:NonFree checked in at 2017-08-01 09:25:47 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory:NonFree/unrar (Old) and /work/SRC/openSUSE:Factory:NonFree/.unrar.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "unrar" Tue Aug 1 09:25:47 2017 rev:67 rq:513151 version:5.5.7 Changes: -------- --- /work/SRC/openSUSE:Factory:NonFree/unrar/unrar.changes 2017-07-04 09:12:36.879874950 +0200 +++ /work/SRC/openSUSE:Factory:NonFree/.unrar.new/unrar.changes 2017-08-01 09:26:13.872493598 +0200 @@ -1,0 +2,7 @@ +Mon Jul 31 09:08:09 UTC 2017 - idonmez@suse.com + +- Update to version 5.5.7 + * "Checksum error" could be mistakenly reported for some valid + GZIP archives. + +------------------------------------------------------------------- Old: ---- unrarsrc-5.5.6.tar.gz New: ---- unrarsrc-5.5.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ unrar.spec ++++++ --- /var/tmp/diff_new_pack.bWIRWW/_old 2017-08-01 09:26:14.608389884 +0200 +++ /var/tmp/diff_new_pack.bWIRWW/_new 2017-08-01 09:26:14.612389321 +0200 @@ -18,10 +18,10 @@ # majorversion should match the major version number. %define majorversion 5 -%define libsuffix 5_5_6 +%define libsuffix 5_5_7 Name: unrar -Version: 5.5.6 +Version: 5.5.7 Release: 0 Summary: A program to extract, test, and view RAR archives License: SUSE-NonFree ++++++ unrarsrc-5.5.6.tar.gz -> unrarsrc-5.5.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/arccmt.cpp new/unrar/arccmt.cpp --- old/unrar/arccmt.cpp 2017-07-02 09:52:34.000000000 +0200 +++ new/unrar/arccmt.cpp 2017-07-25 11:04:29.000000000 +0200 @@ -7,7 +7,7 @@ SaveFilePos SavePos(*this); #ifndef SFX_MODULE - ushort CmtLength; + uint CmtLength; if (Format==RARFMT14) { Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET); @@ -52,7 +52,7 @@ if (Format==RARFMT14) { #ifdef RAR_NOCRYPT - return(false); + return false; #else UnpCmtLength=GetByte(); UnpCmtLength+=(GetByte()<<8); @@ -96,6 +96,8 @@ } else { + if (CmtLength==0) + return false; Array<byte> CmtRaw(CmtLength); Read(&CmtRaw[0],CmtLength); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/arcread.cpp new/unrar/arcread.cpp --- old/unrar/arcread.cpp 2017-07-02 09:52:34.000000000 +0200 +++ new/unrar/arcread.cpp 2017-07-25 11:04:29.000000000 +0200 @@ -308,17 +308,17 @@ if (FileBlock) { + *hd->FileName=0; if ((hd->Flags & LHD_UNICODE)!=0) { EncodeFileName NameCoder; size_t Length=strlen(FileName); Length++; - NameCoder.Decode(FileName,(byte *)FileName+Length, - NameSize-Length,hd->FileName, - ASIZE(hd->FileName)); + if (ReadNameSize>Length) + NameCoder.Decode(FileName,(byte *)FileName+Length, + ReadNameSize-Length,hd->FileName, + ASIZE(hd->FileName)); } - else - *hd->FileName=0; if (*hd->FileName==0) ArcCharToWide(FileName,hd->FileName,ASIZE(hd->FileName),ACTW_OEM); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/dll.rc new/unrar/dll.rc --- old/unrar/dll.rc 2017-07-02 09:48:59.000000000 +0200 +++ new/unrar/dll.rc 2017-07-25 10:58:41.000000000 +0200 @@ -2,8 +2,8 @@ #include <commctrl.h> VS_VERSION_INFO VERSIONINFO -FILEVERSION 5, 50, 5, 2378 -PRODUCTVERSION 5, 50, 5, 2378 +FILEVERSION 5, 50, 6, 2401 +PRODUCTVERSION 5, 50, 6, 2401 FILEOS VOS__WINDOWS32 FILETYPE VFT_APP { @@ -14,8 +14,8 @@ VALUE "CompanyName", "Alexander Roshal\0" VALUE "ProductName", "RAR decompression library\0" VALUE "FileDescription", "RAR decompression library\0" - VALUE "FileVersion", "5.50.5\0" - VALUE "ProductVersion", "5.50.5\0" + VALUE "FileVersion", "5.50.6\0" + VALUE "ProductVersion", "5.50.6\0" VALUE "LegalCopyright", "Copyright � Alexander Roshal 1993-2017\0" VALUE "OriginalFilename", "Unrar.dll\0" } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/encname.cpp new/unrar/encname.cpp --- old/unrar/encname.cpp 2017-07-02 09:52:35.000000000 +0200 +++ new/unrar/encname.cpp 2017-07-25 11:04:30.000000000 +0200 @@ -15,31 +15,43 @@ size_t MaxDecSize) { size_t EncPos=0,DecPos=0; - byte HighByte=EncName[EncPos++]; + byte HighByte=EncPos<EncSize ? EncName[EncPos++] : 0; while (EncPos<EncSize && DecPos<MaxDecSize) { if (FlagBits==0) { + if (EncPos>=EncSize) + break; Flags=EncName[EncPos++]; FlagBits=8; } switch(Flags>>6) { case 0: + if (EncPos>=EncSize) + break; NameW[DecPos++]=EncName[EncPos++]; break; case 1: + if (EncPos>=EncSize) + break; NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8); break; case 2: + if (EncPos+1>=EncSize) + break; NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8); EncPos+=2; break; case 3: { + if (EncPos>=EncSize) + break; int Length=EncName[EncPos++]; - if (Length & 0x80) + if ((Length & 0x80)!=0) { + if (EncPos>=EncSize) + break; byte Correction=EncName[EncPos++]; for (Length=(Length&0x7f)+2;Length>0 && DecPos<MaxDecSize;Length--,DecPos++) NameW[DecPos]=((Name[DecPos]+Correction)&0xff)+(HighByte<<8); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/extinfo.cpp new/unrar/extinfo.cpp --- old/unrar/extinfo.cpp 2017-07-02 09:52:35.000000000 +0200 +++ new/unrar/extinfo.cpp 2017-07-25 11:04:30.000000000 +0200 @@ -93,6 +93,25 @@ } +// Check if all existing path components are directories and not links. +static bool LinkInPath(const wchar *Name) +{ + wchar Path[NM]; + if (wcslen(Name)>=ASIZE(Path)) + return true; // It should not be that long, skip. + wcsncpyz(Path,Name,ASIZE(Path)); + for (wchar *s=Path+wcslen(Path)-1;s>Path;s--) + if (IsPathDiv(*s)) + { + *s=0; + FindData FD; + if (FindFile::FastFind(Path,&FD,true) && (FD.IsLink || !FD.IsDir)) + return true; + } + return false; +} + + bool IsRelativeSymlinkSafe(CommandData *Cmd,const wchar *SrcName,const wchar *PrepSrcName,const wchar *TargetName) { // Catch root dir based /path/file paths also as stuff like \\?\. @@ -100,7 +119,25 @@ // is a root based. if (IsFullRootPath(SrcName) || IsFullRootPath(TargetName)) return false; - + + // Number of ".." in link target. + int UpLevels=0; + for (int Pos=0;*TargetName!=0;Pos++) + { + bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && + (IsPathDiv(TargetName[2]) || TargetName[2]==0) && + (Pos==0 || IsPathDiv(*(TargetName-1))); + if (Dot2) + UpLevels++; + TargetName++; + } + // If link target includes "..", it must not have another links + // in the path, because they can bypass our safety check. For example, + // suppose we extracted "lnk1" -> "." first and "lnk1/lnk2" -> ".." next + // or "dir/lnk1" -> ".." first and "dir/lnk1/lnk2" -> ".." next. + if (UpLevels>0 && LinkInPath(PrepSrcName)) + return false; + // We could check just prepared src name, but for extra safety // we check both original (as from archive header) and prepared // (after applying the destination path and -ep switches) names. @@ -119,17 +156,6 @@ } int PrepAllowedDepth=CalcAllowedDepth(PrepSrcName); - // Number of ".." in link target. - int UpLevels=0; - for (int Pos=0;*TargetName!=0;Pos++) - { - bool Dot2=TargetName[0]=='.' && TargetName[1]=='.' && - (IsPathDiv(TargetName[2]) || TargetName[2]==0) && - (Pos==0 || IsPathDiv(*(TargetName-1))); - if (Dot2) - UpLevels++; - TargetName++; - } return AllowedDepth>=UpLevels && PrepAllowedDepth>=UpLevels; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/file.cpp new/unrar/file.cpp --- old/unrar/file.cpp 2017-07-02 09:52:35.000000000 +0200 +++ new/unrar/file.cpp 2017-07-25 11:04:30.000000000 +0200 @@ -173,7 +173,7 @@ wchar *LastChar=PointToLastChar(Name); bool Special=*LastChar=='.' || *LastChar==' '; - if (Special) + if (Special && (Mode & FMF_STANDARDNAMES)==0) hFile=FILE_BAD_HANDLE; else hFile=CreateFile(Name,Access,ShareMode,NULL,CREATE_ALWAYS,0,NULL); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/file.hpp new/unrar/file.hpp --- old/unrar/file.hpp 2017-07-02 09:52:35.000000000 +0200 +++ new/unrar/file.hpp 2017-07-25 11:04:30.000000000 +0200 @@ -39,6 +39,9 @@ // Provide read access to created file for other programs. FMF_SHAREREAD=16, + // Use standard NTFS names without trailing dots and spaces. + FMF_STANDARDNAMES=32, + // Mode flags are not defined yet. FMF_UNDEFINED=256 }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/rarvm.cpp new/unrar/rarvm.cpp --- old/unrar/rarvm.cpp 2017-07-02 09:52:36.000000000 +0200 +++ new/unrar/rarvm.cpp 2017-07-25 11:04:32.000000000 +0200 @@ -22,6 +22,7 @@ void RarVM::Execute(VM_PreparedProgram *Prg) { memcpy(R,Prg->InitR,sizeof(Prg->InitR)); + Prg->FilteredData=NULL; if (Prg->Type!=VMSF_NONE) { bool Success=ExecuteStandardFilter(Prg->Type); @@ -107,7 +108,14 @@ void RarVM::SetMemory(size_t Pos,byte *Data,size_t DataSize) { if (Pos<VM_MEMSIZE && Data!=Mem+Pos) - memmove(Mem+Pos,Data,Min(DataSize,VM_MEMSIZE-Pos)); + { + // We can have NULL Data for invalid filters with DataSize==0. While most + // sensible memmove implementations do not care about data if size is 0, + // let's follow the standard and check the size first. + size_t CopySize=Min(DataSize,VM_MEMSIZE-Pos); + if (CopySize!=0) + memmove(Mem+Pos,Data,CopySize); + } } @@ -279,7 +287,10 @@ PrevDelta=(signed char)(Predicted-PrevByte); PrevByte=Predicted; - int D=((signed char)CurByte)<<3; + int D=(signed char)CurByte; + // Left shift of negative value is undefined behavior in C++, + // so we cast it to unsigned to follow the standard. + D=(uint)D<<3; Dif[0]+=abs(D); Dif[1]+=abs(D-D1); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/rawread.cpp new/unrar/rawread.cpp --- old/unrar/rawread.cpp 2017-07-02 09:52:36.000000000 +0200 +++ new/unrar/rawread.cpp 2017-07-25 11:04:32.000000000 +0200 @@ -115,7 +115,9 @@ uint64 RawRead::GetV() { uint64 Result=0; - for (uint Shift=0;ReadPos<DataSize;Shift+=7) + // Need to check Shift<64, because for shift greater than or equal to + // the width of the promoted left operand, the behavior is undefined. + for (uint Shift=0;ReadPos<DataSize && Shift<64;Shift+=7) { byte CurByte=Data[ReadPos++]; Result+=uint64(CurByte & 0x7f)<<Shift; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unicode.cpp new/unrar/unicode.cpp --- old/unrar/unicode.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unicode.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -510,19 +510,23 @@ int64 atoilw(const wchar *s) { - int sign=1; + bool sign=false; if (*s=='-') { s++; - sign=-1; + sign=true; } - int64 n=0; + // Use unsigned type here, since long string can overflow the variable + // and signed integer overflow is undefined behavior in C++. + uint64 n=0; while (*s>='0' && *s<='9') { n=n*10+(*s-'0'); s++; } - return sign*n; + // Check int64(n)>=0 to avoid the signed overflow with undefined behavior + // when negating 0x8000000000000000. + return sign && int64(n)>=0 ? -int64(n) : int64(n); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack.cpp new/unrar/unpack.cpp --- old/unrar/unpack.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -135,7 +135,7 @@ } -void Unpack::DoUnpack(int Method,bool Solid) +void Unpack::DoUnpack(uint Method,bool Solid) { // Methods <50 will crash in Fragmented mode when accessing NULL Window. // They cannot be called in such mode now, but we check it below anyway @@ -206,6 +206,7 @@ UnpInitData20(Solid); #endif UnpInitData30(Solid); + UnpInitData50(Solid); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack.hpp new/unrar/unpack.hpp --- old/unrar/unpack.hpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack.hpp 2017-07-25 11:04:34.000000000 +0200 @@ -211,6 +211,7 @@ void UnpWriteArea(size_t StartPtr,size_t EndPtr); void UnpWriteData(byte *Data,size_t Size); _forceinline uint SlotToLength(BitInput &Inp,uint Slot); + void UnpInitData50(bool Solid); bool ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header); bool ReadTables(BitInput &Inp,UnpackBlockHeader &Header,UnpackBlockTables &Tables); void MakeDecodeTables(byte *LengthTable,DecodeTable *Dec,uint Size); @@ -307,7 +308,9 @@ DecodeTable MD[4]; // Decode multimedia data, up to 4 channels. unsigned char UnpOldTable20[MC20*4]; - int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta; + bool UnpAudioBlock; + uint UnpChannels,UnpCurChannel; + int UnpChannelDelta; void CopyString20(uint Length,uint Distance); bool ReadTables20(); void UnpWriteBuf20(); @@ -341,7 +344,12 @@ byte UnpOldTable[HUFF_TABLE_SIZE30]; int UnpBlockType; - bool TablesRead; + // If we already read decoding tables for Unpack v2,v3,v5. + // We should not use a single variable for all algorithm versions, + // because we can have a corrupt archive with one algorithm file + // followed by another algorithm file with "solid" flag and we do not + // want to reuse tables from one algorithm in another. + bool TablesRead2,TablesRead3,TablesRead5; // Virtual machine to execute filters code. RarVM VM; @@ -368,7 +376,7 @@ Unpack(ComprDataIO *DataIO); ~Unpack(); void Init(size_t WinSize,bool Solid); - void DoUnpack(int Method,bool Solid); + void DoUnpack(uint Method,bool Solid); bool IsFileExtracted() {return(FileExtracted);} void SetDestSize(int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} void SetSuspended(bool Suspended) {Unpack::Suspended=Suspended;} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack15.cpp new/unrar/unpack15.cpp --- old/unrar/unpack15.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack15.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -285,7 +285,7 @@ break; } - ChSetB[DistancePlace]=ChSetB[NewDistancePlace]; + ChSetB[DistancePlace & 0xff]=ChSetB[NewDistancePlace]; ChSetB[NewDistancePlace]=Distance; Distance=((Distance & 0xff00) | (Inp.fgetbits() >> 8)) >> 1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack20.cpp new/unrar/unpack20.cpp --- old/unrar/unpack20.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack20.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -13,11 +13,11 @@ { static unsigned char LDecode[]={0,1,2,3,4,5,6,7,8,10,12,14,16,20,24,28,32,40,48,56,64,80,96,112,128,160,192,224}; static unsigned char LBits[]= {0,0,0,0,0,0,0,0,1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5}; - static int DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; + static uint DDecode[]={0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,1536,2048,3072,4096,6144,8192,12288,16384,24576,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; static unsigned char DBits[]= {0,0,0,0,1,1,2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; - unsigned int Bits; + uint Bits; if (Suspended) UnpPtr=WrPtr; @@ -26,9 +26,8 @@ UnpInitData(Solid); if (!UnpReadBuf()) return; - if (!Solid) - if (!ReadTables20()) - return; + if ((!Solid || !TablesRead2) && !ReadTables20()) + return; --DestUnpSize; } @@ -47,7 +46,7 @@ } if (UnpAudioBlock) { - int AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]); + uint AudioNumber=DecodeNumber(Inp,&MD[UnpCurChannel]); if (AudioNumber==256) { @@ -55,14 +54,14 @@ break; continue; } - Window[UnpPtr++]=DecodeAudio(AudioNumber); + Window[UnpPtr++]=DecodeAudio((int)AudioNumber); if (++UnpCurChannel==UnpChannels) UnpCurChannel=0; --DestUnpSize; continue; } - int Number=DecodeNumber(Inp,&BlockTables.LD); + uint Number=DecodeNumber(Inp,&BlockTables.LD); if (Number<256) { Window[UnpPtr++]=(byte)Number; @@ -71,15 +70,15 @@ } if (Number>269) { - int Length=LDecode[Number-=270]+3; + uint Length=LDecode[Number-=270]+3; if ((Bits=LBits[Number])>0) { Length+=Inp.getbits()>>(16-Bits); Inp.addbits(Bits); } - int DistNumber=DecodeNumber(Inp,&BlockTables.DD); - unsigned int Distance=DDecode[DistNumber]+1; + uint DistNumber=DecodeNumber(Inp,&BlockTables.DD); + uint Distance=DDecode[DistNumber]+1; if ((Bits=DBits[DistNumber])>0) { Distance+=Inp.getbits()>>(16-Bits); @@ -109,9 +108,9 @@ } if (Number<261) { - unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; - int LengthNumber=DecodeNumber(Inp,&BlockTables.RD); - int Length=LDecode[LengthNumber]+2; + uint Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; + uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD); + uint Length=LDecode[LengthNumber]+2; if ((Bits=LBits[LengthNumber])>0) { Length+=Inp.getbits()>>(16-Bits); @@ -132,7 +131,7 @@ } if (Number<270) { - unsigned int Distance=SDDecode[Number-=261]+1; + uint Distance=SDDecode[Number-=261]+1; if ((Bits=SDBits[Number])>0) { Distance+=Inp.getbits()>>(16-Bits); @@ -167,17 +166,17 @@ { byte BitLength[BC20]; byte Table[MC20*4]; - int TableSize,N,I; if (Inp.InAddr>ReadTop-25) if (!UnpReadBuf()) - return(false); + return false; uint BitField=Inp.getbits(); - UnpAudioBlock=(BitField & 0x8000); + UnpAudioBlock=(BitField & 0x8000)!=0; if (!(BitField & 0x4000)) memset(UnpOldTable20,0,sizeof(UnpOldTable20)); Inp.addbits(2); + uint TableSize; if (UnpAudioBlock) { UnpChannels=((BitField>>12) & 3)+1; @@ -189,19 +188,18 @@ else TableSize=NC20+DC20+RC20; - for (I=0;I<BC20;I++) + for (uint I=0;I<BC20;I++) { BitLength[I]=(byte)(Inp.getbits() >> 12); Inp.addbits(4); } MakeDecodeTables(BitLength,&BlockTables.BD,BC20); - I=0; - while (I<TableSize) + for (uint I=0;I<TableSize;) { if (Inp.InAddr>ReadTop-5) if (!UnpReadBuf()) return false; - int Number=DecodeNumber(Inp,&BlockTables.BD); + uint Number=DecodeNumber(Inp,&BlockTables.BD); if (Number<16) { Table[I]=(Number+UnpOldTable20[I]) & 0xf; @@ -210,9 +208,11 @@ else if (Number==16) { - N=(Inp.getbits() >> 14)+3; + uint N=(Inp.getbits() >> 14)+3; Inp.addbits(2); - if (I>0) + if (I==0) + return false; // We cannot have "repeat previous" code at the first position. + else while (N-- > 0 && I<TableSize) { Table[I]=Table[I-1]; @@ -221,6 +221,7 @@ } else { + uint N; if (Number==17) { N=(Inp.getbits() >> 13)+3; @@ -235,10 +236,11 @@ Table[I++]=0; } } + TablesRead2=true; if (Inp.InAddr>ReadTop) - return(true); + return true; if (UnpAudioBlock) - for (I=0;I<UnpChannels;I++) + for (uint I=0;I<UnpChannels;I++) MakeDecodeTables(&Table[I*MC20],&MD[I],MC20); else { @@ -247,7 +249,7 @@ MakeDecodeTables(&Table[NC20+DC20],&BlockTables.RD,RC20); } memcpy(UnpOldTable20,Table,sizeof(UnpOldTable20)); - return(true); + return true; } @@ -269,7 +271,10 @@ { if (!Solid) { - UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0; + TablesRead2=false; + UnpAudioBlock=false; + UnpChannelDelta=0; + UnpCurChannel=0; UnpChannels=1; memset(AudV,0,sizeof(AudV)); @@ -290,9 +295,12 @@ int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta; PCh=(PCh>>3) & 0xFF; - unsigned int Ch=PCh-Delta; + uint Ch=PCh-Delta; - int D=((signed char)Delta)<<3; + int D=(signed char)Delta; + // Left shift of negative value is undefined behavior in C++, + // so we cast it to unsigned to follow the standard. + D=(uint)D<<3; V->Dif[0]+=abs(D); V->Dif[1]+=abs(D-V->D1); @@ -311,9 +319,9 @@ if ((V->ByteCount & 0x1F)==0) { - unsigned int MinDif=V->Dif[0],NumMinDif=0; + uint MinDif=V->Dif[0],NumMinDif=0; V->Dif[0]=0; - for (int I=1;I<sizeof(V->Dif)/sizeof(V->Dif[0]);I++) + for (uint I=1;I<ASIZE(V->Dif);I++) { if (V->Dif[I]<MinDif) { @@ -366,5 +374,5 @@ break; } } - return((byte)Ch); + return (byte)Ch; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack30.cpp new/unrar/unpack30.cpp --- old/unrar/unpack30.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack30.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -42,7 +42,7 @@ UnpInitData(Solid); if (!UnpReadBuf30()) return; - if ((!Solid || !TablesRead) && !ReadTables30()) + if ((!Solid || !TablesRead3) && !ReadTables30()) return; } @@ -133,7 +133,7 @@ continue; } - int Number=DecodeNumber(Inp,&BlockTables.LD); + uint Number=DecodeNumber(Inp,&BlockTables.LD); if (Number<256) { Window[UnpPtr++]=(byte)Number; @@ -141,15 +141,15 @@ } if (Number>=271) { - int Length=LDecode[Number-=271]+3; + uint Length=LDecode[Number-=271]+3; if ((Bits=LBits[Number])>0) { Length+=Inp.getbits()>>(16-Bits); Inp.addbits(Bits); } - int DistNumber=DecodeNumber(Inp,&BlockTables.DD); - unsigned int Distance=DDecode[DistNumber]+1; + uint DistNumber=DecodeNumber(Inp,&BlockTables.DD); + uint Distance=DDecode[DistNumber]+1; if ((Bits=DBits[DistNumber])>0) { if (DistNumber>9) @@ -166,7 +166,7 @@ } else { - int LowDist=DecodeNumber(Inp,&BlockTables.LDD); + uint LowDist=DecodeNumber(Inp,&BlockTables.LDD); if (LowDist==16) { LowDistRepCount=LOW_DIST_REP_COUNT-1; @@ -189,7 +189,7 @@ if (Distance>=0x2000) { Length++; - if (Distance>=0x40000L) + if (Distance>=0x40000) Length++; } @@ -218,13 +218,13 @@ } if (Number<263) { - int DistNum=Number-259; - unsigned int Distance=OldDist[DistNum]; - for (int I=DistNum;I>0;I--) + uint DistNum=Number-259; + uint Distance=OldDist[DistNum]; + for (uint I=DistNum;I>0;I--) OldDist[I]=OldDist[I-1]; OldDist[0]=Distance; - int LengthNumber=DecodeNumber(Inp,&BlockTables.RD); + uint LengthNumber=DecodeNumber(Inp,&BlockTables.RD); int Length=LDecode[LengthNumber]+2; if ((Bits=LBits[LengthNumber])>0) { @@ -237,7 +237,7 @@ } if (Number<272) { - unsigned int Distance=SDDecode[Number-=263]+1; + uint Distance=SDDecode[Number-=263]+1; if ((Bits=SDBits[Number])>0) { Distance+=Inp.getbits()>>(16-Bits); @@ -274,11 +274,11 @@ NewTable=(BitField & 0x4000)!=0; Inp.addbits(2); } - TablesRead=!NewTable; + TablesRead3=!NewTable; // Quit immediately if "new file" flag is set. If "new table" flag // is present, we'll read the table in beginning of next file - // based on 'TablesRead' 'false' value. + // based on 'TablesRead3' 'false' value. if (NewFile) return false; return ReadTables30(); // Quit only if we failed to read tables. @@ -290,9 +290,9 @@ // Entire VM code is guaranteed to fully present in block defined // by current Huffman table. Compressor checks that VM code does not cross // Huffman block boundaries. - unsigned int FirstByte=Inp.getbits()>>8; + uint FirstByte=Inp.getbits()>>8; Inp.addbits(8); - int Length=(FirstByte & 7)+1; + uint Length=(FirstByte & 7)+1; if (Length==7) { Length=(Inp.getbits()>>8)+7; @@ -304,8 +304,10 @@ Length=Inp.getbits(); Inp.addbits(16); } + if (Length==0) + return false; Array<byte> VMCode(Length); - for (int I=0;I<Length;I++) + for (uint I=0;I<Length;I++) { // Try to read the new buffer if only one byte is left. // But if we read all bytes except the last, one byte is enough. @@ -320,15 +322,15 @@ bool Unpack::ReadVMCodePPM() { - unsigned int FirstByte=SafePPMDecodeChar(); + uint FirstByte=SafePPMDecodeChar(); if ((int)FirstByte==-1) return false; - int Length=(FirstByte & 7)+1; + uint Length=(FirstByte & 7)+1; if (Length==7) { int B1=SafePPMDecodeChar(); if (B1==-1) - return(false); + return false; Length=B1+7; } else @@ -342,12 +344,14 @@ return false; Length=B1*256+B2; } + if (Length==0) + return false; Array<byte> VMCode(Length); - for (int I=0;I<Length;I++) + for (uint I=0;I<Length;I++) { int Ch=SafePPMDecodeChar(); if (Ch==-1) - return(false); + return false; VMCode[I]=Ch; } return AddVMCode(FirstByte,&VMCode[0],Length); @@ -405,7 +409,7 @@ StackFilter->ParentFilter=FiltPos; } - int EmptyCount=0; + uint EmptyCount=0; for (uint I=0;I<PrgStack.Size();I++) { PrgStack[I-EmptyCount]=PrgStack[I]; @@ -424,7 +428,7 @@ PrgStack.Add(1); EmptyCount=1; } - int StackPos=(int)(PrgStack.Size()-EmptyCount); + size_t StackPos=PrgStack.Size()-EmptyCount; PrgStack[StackPos]=StackFilter; uint BlockStart=RarVM::ReadData(VMCodeInp); @@ -458,7 +462,7 @@ { uint InitMask=VMCodeInp.fgetbits()>>9; VMCodeInp.faddbits(7); - for (int I=0;I<7;I++) + for (uint I=0;I<7;I++) if (InitMask & (1<<I)) StackFilter->Prg.InitR[I]=RarVM::ReadData(VMCodeInp); } @@ -644,13 +648,13 @@ memset(UnpOldTable,0,sizeof(UnpOldTable)); Inp.faddbits(2); - for (int I=0;I<BC;I++) + for (uint I=0;I<BC;I++) { - int Length=(byte)(Inp.fgetbits() >> 12); + uint Length=(byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (Length==15) { - int ZeroCount=(byte)(Inp.fgetbits() >> 12); + uint ZeroCount=(byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (ZeroCount==0) BitLength[I]=15; @@ -667,13 +671,13 @@ } MakeDecodeTables(BitLength,&BlockTables.BD,BC30); - const int TableSize=HUFF_TABLE_SIZE30; - for (int I=0;I<TableSize;) + const uint TableSize=HUFF_TABLE_SIZE30; + for (uint I=0;I<TableSize;) { if (Inp.InAddr>ReadTop-5) if (!UnpReadBuf30()) return(false); - int Number=DecodeNumber(Inp,&BlockTables.BD); + uint Number=DecodeNumber(Inp,&BlockTables.BD); if (Number<16) { Table[I]=(Number+UnpOldTable[I]) & 0xf; @@ -682,7 +686,7 @@ else if (Number<18) { - int N; + uint N; if (Number==16) { N=(Inp.fgetbits() >> 13)+3; @@ -693,7 +697,9 @@ N=(Inp.fgetbits() >> 9)+11; Inp.faddbits(7); } - if (I>0) + if (I==0) + return false; // We cannot have "repeat previous" code at the first position. + else while (N-- > 0 && I<TableSize) { Table[I]=Table[I-1]; @@ -702,7 +708,7 @@ } else { - int N; + uint N; if (Number==18) { N=(Inp.fgetbits() >> 13)+3; @@ -717,7 +723,7 @@ Table[I++]=0; } } - TablesRead=true; + TablesRead3=true; if (Inp.InAddr>ReadTop) return false; MakeDecodeTables(&Table[0],&BlockTables.LD,NC30); @@ -733,7 +739,7 @@ { if (!Solid) { - TablesRead=false; + TablesRead3=false; memset(UnpOldTable,0,sizeof(UnpOldTable)); PPMEscChar=2; UnpBlockType=BLOCK_LZ; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack50.cpp new/unrar/unpack50.cpp --- old/unrar/unpack50.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack50.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -7,7 +7,12 @@ UnpInitData(Solid); if (!UnpReadBuf()) return; - if (!ReadBlockHeader(Inp,BlockHeader) || !ReadTables(Inp,BlockHeader,BlockTables)) + + // Check TablesRead5 to be sure that we read tables at least once + // regardless of current block header TablePresent flag. + // So we can safefly use these tables below. + if (!ReadBlockHeader(Inp,BlockHeader) || + !ReadTables(Inp,BlockHeader,BlockTables) || !TablesRead5) return; } @@ -516,6 +521,13 @@ } +void Unpack::UnpInitData50(bool Solid) +{ + if (!Solid) + TablesRead5=false; +} + + bool Unpack::ReadBlockHeader(BitInput &Inp,UnpackBlockHeader &Header) { Header.HeaderSize=0; @@ -570,13 +582,13 @@ return false; byte BitLength[BC]; - for (int I=0;I<BC;I++) + for (uint I=0;I<BC;I++) { - int Length=(byte)(Inp.fgetbits() >> 12); + uint Length=(byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (Length==15) { - int ZeroCount=(byte)(Inp.fgetbits() >> 12); + uint ZeroCount=(byte)(Inp.fgetbits() >> 12); Inp.faddbits(4); if (ZeroCount==0) BitLength[I]=15; @@ -595,13 +607,13 @@ MakeDecodeTables(BitLength,&Tables.BD,BC); byte Table[HUFF_TABLE_SIZE]; - const int TableSize=HUFF_TABLE_SIZE; - for (int I=0;I<TableSize;) + const uint TableSize=HUFF_TABLE_SIZE; + for (uint I=0;I<TableSize;) { if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop-5) if (!UnpReadBuf()) return false; - int Number=DecodeNumber(Inp,&Tables.BD); + uint Number=DecodeNumber(Inp,&Tables.BD); if (Number<16) { Table[I]=Number; @@ -610,7 +622,7 @@ else if (Number<18) { - int N; + uint N; if (Number==16) { N=(Inp.fgetbits() >> 13)+3; @@ -621,7 +633,16 @@ N=(Inp.fgetbits() >> 9)+11; Inp.faddbits(7); } - if (I>0) + if (I==0) + { + // We cannot have "repeat previous" code at the first position. + // Multiple such codes would shift Inp position without changing I, + // which can lead to reading beyond of Inp boundary in mutithreading + // mode, where Inp.ExternalBuffer disables bounds check and we just + // reserve a lot of buffer space to not need such check normally. + return false; + } + else while (N-- > 0 && I<TableSize) { Table[I]=Table[I-1]; @@ -630,7 +651,7 @@ } else { - int N; + uint N; if (Number==18) { N=(Inp.fgetbits() >> 13)+3; @@ -645,6 +666,7 @@ Table[I++]=0; } } + TablesRead5=true; if (!Inp.ExternalBuffer && Inp.InAddr>ReadTop) return false; MakeDecodeTables(&Table[0],&Tables.LD,NC); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpack50mt.cpp new/unrar/unpack50mt.cpp --- old/unrar/unpack50mt.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpack50mt.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -133,11 +133,13 @@ if (!CurData->HeaderRead) { CurData->HeaderRead=true; - if (!ReadBlockHeader(CurData->Inp,CurData->BlockHeader)) + if (!ReadBlockHeader(CurData->Inp,CurData->BlockHeader) || + !CurData->BlockHeader.TablePresent && !TablesRead5) { Done=true; break; } + TablesRead5=true; } // To prevent too high memory use we switch to single threaded mode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/unpackinline.cpp new/unrar/unpackinline.cpp --- old/unrar/unpackinline.cpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/unpackinline.cpp 2017-07-25 11:04:34.000000000 +0200 @@ -120,7 +120,7 @@ // Convert the position in the code list to position in alphabet // and return it. - return(Dec->DecodeNum[Pos]); + return Dec->DecodeNum[Pos]; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/unrar/version.hpp new/unrar/version.hpp --- old/unrar/version.hpp 2017-07-02 09:52:37.000000000 +0200 +++ new/unrar/version.hpp 2017-07-25 11:04:34.000000000 +0200 @@ -1,6 +1,6 @@ #define RARVER_MAJOR 5 #define RARVER_MINOR 50 -#define RARVER_BETA 5 -#define RARVER_DAY 2 +#define RARVER_BETA 6 +#define RARVER_DAY 25 #define RARVER_MONTH 7 #define RARVER_YEAR 2017