1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
See https://trac.kodi.tv/ticket/17510
diff --git a/lib/UnrarXLib/rarvm.cpp b/lib/UnrarXLib/rarvm.cpp
index 901c35dcb4..42df0a0110 100644
--- a/lib/UnrarXLib/rarvm.cpp
+++ b/lib/UnrarXLib/rarvm.cpp
@@ -873,14 +873,16 @@ void RarVM::ExecuteStandardFilter(VM_StandardFilters FilterType)
break;
case VMSF_DELTA:
{
- int DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
- SET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20],DataSize);
- if (DataSize>=VM_GLOBALMEMADDR/2)
- break;
- for (int CurChannel=0;CurChannel<Channels;CurChannel++)
+ uint DataSize=R[4],Channels=R[0],SrcPos=0,Border=DataSize*2;
+ if (DataSize>VM_MEMSIZE/2 || 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 (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++]);
}
}
diff --git a/lib/UnrarXLib/unpack.hpp b/lib/UnrarXLib/unpack.hpp
index 83fb0f0254..36ac30d181 100644
--- a/lib/UnrarXLib/unpack.hpp
+++ b/lib/UnrarXLib/unpack.hpp
@@ -1,6 +1,12 @@
#ifndef _RAR_UNPACK_
#define _RAR_UNPACK_
+// 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 BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM};
struct Decode
|