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);
   }
 }

Reply via email to