Description: Backport fix for CVE-2012-6706 VMSF_DELTA arbitrary memory write
 A VMSF_DELTA memory corruption was discovered in unrar before 5.5.5,
 as used in Sophos Anti-Virus Threat Detection Engine before 3.37.2 and other products,
 that can lead to arbitrary code execution. An integer overflow can be caused in DataSize+CurChannel.
 The result is a negative value of the "DestPos" variable, which allows the attacker to write
 out of bounds when setting Mem[DestPos]. 
 .
 unrar-nonfree (1:4.1.4-1+deb7u2) wheezy-security; urgency=low
 .
   * Backport fix for CVE-2012-6706 VMSF_DELTA arbitrary memory write
Author: Damian Lukowski <damian.lukowski@credativ.de>
Bug-Debian: http://bugs.debian.org/865461
Reviewed-By: Felix Geyer <fgeyer@debian.org>

--- unrar-nonfree-4.1.4.orig/rarvm.cpp
+++ unrar-nonfree-4.1.4/rarvm.cpp
@@ -960,15 +960,15 @@ void RarVM::ExecuteStandardFilter(VM_Sta
       {
         int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
         SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
-        if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
+        if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || (uint)Channels>MAX3_UNPACK_CHANNELS || Channels==0)
           break;
 
         // Bytes from same channels are grouped to continual data blocks,
         // so we need to place them back to their interleaving positions.
-        for (int CurChannel=0;CurChannel<Channels;CurChannel++)
+        for (uint CurChannel=0;CurChannel<Channels;CurChannel++)
         {
           byte PrevByte=0;
-          for (int DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)
+          for (uint DestPos=DataSize+CurChannel;DestPos<Border;DestPos+=Channels)
             Mem[DestPos]=(PrevByte-=Mem[SrcPos++]);
         }
       }
@@ -979,7 +979,7 @@ void RarVM::ExecuteStandardFilter(VM_Sta
         byte *SrcData=Mem,*DestData=SrcData+DataSize;
         const int Channels=3;
         SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
-        if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || PosR<0)
+        if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || Width<0 || PosR<0 || DataSize<3 || Width>DataSize || PosR>2)
           break;
         for (int CurChannel=0;CurChannel<Channels;CurChannel++)
         {
@@ -1024,7 +1024,7 @@ void RarVM::ExecuteStandardFilter(VM_Sta
         int DataSize=R[4],Channels=R[0];
         byte *SrcData=Mem,*DestData=SrcData+DataSize;
         SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
-        if ((uint)DataSize>=VM_GLOBALMEMADDR/2)
+        if ((uint)DataSize>=VM_GLOBALMEMADDR/2 || (uint)Channels>128 || Channels==0)
           break;
         for (int CurChannel=0;CurChannel<Channels;CurChannel++)
         {
--- unrar-nonfree-4.1.4.orig/rarvm.hpp
+++ unrar-nonfree-4.1.4/rarvm.hpp
@@ -14,6 +14,12 @@
 #define VM_GLOBALMEMSIZE             0x2000
 #define VM_FIXEDGLOBALSIZE               64
 
+// Limit maximum number of channels in RAR3 delta filter to some reasonable
+// value to prevent too slow processing of corrupt archives with invalid
+// channels number. Must be equal or larger than v3_MAX_FILTER_CHANNELS.
+// No need to provide it for RAR5, which uses only 5 bits to store channels.
+#define MAX3_UNPACK_CHANNELS      1024
+
 enum VM_Commands
 {
   VM_MOV,  VM_CMP,  VM_ADD,  VM_SUB,  VM_JZ,   VM_JNZ,  VM_INC,  VM_DEC,
