aboutsummaryrefslogtreecommitdiff
path: root/archivers/unace/files/patch-CVE-2015-2063
blob: 72c0fb38e707ba935c2e72c9402528e7a1bbdd24 (plain) (blame)
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
Description: Fixes a buffer overflow when reading bogus file headers
 The header parser was not checking if it had read enough data when trying
 to parse the header from memory, causing it to accept files with headers
 smaller than expected.
 .
 Fixes CVE-2015-2063.
Author: Guillem Jover <guillem@debian.org>
Origin: vendor
Bug-Debian: https://bugs.debian.org/775003
Forwarded: no
Last-Update: 2015-02-24

---
 unace.c |   25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

--- unace.c
+++ unace.c
@@ -113,6 +113,7 @@ INT  read_header(INT print_err)
 {
    USHORT rd,
         head_size,
+        need_size,
         crc_ok;
    LONG crc;
    UCHAR *tp=readbuf;
@@ -128,6 +129,9 @@ INT  read_header(INT print_err)
 #endif
                                         // read size_headrdb bytes into 
    head_size = head.HEAD_SIZE;          // header structure 
+   need_size = 3;
+   if (need_size > head.HEAD_SIZE)
+      return 0;
    rd = (head_size > size_headrdb) ? size_headrdb : head_size;
    if (read(archan, readbuf, rd) < rd)
       return 0;
@@ -147,7 +151,12 @@ INT  read_header(INT print_err)
    head.HEAD_FLAGS=BUFP2WORD(tp);
 
    if (head.HEAD_FLAGS & ACE_ADDSIZE)
+   {
+      need_size += 4;
+      if (need_size > head.HEAD_SIZE)
+         return 0;
       skipsize = head.ADDSIZE = BUF2LONG(tp);   // get ADDSIZE
+   }
    else
       skipsize = 0;
 
@@ -158,6 +167,9 @@ INT  read_header(INT print_err)
    switch (head.HEAD_TYPE)              // specific buffer to head conversion
    {
       case MAIN_BLK:
+         need_size += 24;
+         if (need_size > head.HEAD_SIZE)
+            return 0;
          memcpy(mhead.ACESIGN, tp, acesign_len); tp+=acesign_len;
          mhead.VER_MOD=*tp++;
          mhead.VER_CR =*tp++;
@@ -168,9 +180,15 @@ INT  read_header(INT print_err)
          mhead.RES2   =BUFP2WORD(tp);
          mhead.RES    =BUFP2LONG(tp);
          mhead.AV_SIZE=*tp++;
-         memcpy(mhead.AV, tp, rd-(USHORT)(tp-readbuf));
+         if (mhead.AV_SIZE > sizeof(mhead.AV) ||
+             mhead.AV_SIZE + need_size > head.HEAD_SIZE)
+            return 0;
+         memcpy(mhead.AV, tp, mhead.AV_SIZE);
          break;
       case FILE_BLK:
+         need_size += 28;
+         if (need_size > head.HEAD_SIZE)
+            return 0;
          fhead.PSIZE     =BUFP2LONG(tp);
          fhead.SIZE      =BUFP2LONG(tp);
          fhead.FTIME     =BUFP2LONG(tp);
@@ -181,7 +199,10 @@ INT  read_header(INT print_err)
          fhead.TECH.PARM =BUFP2WORD(tp);
          fhead.RESERVED  =BUFP2WORD(tp);
          fhead.FNAME_SIZE=BUFP2WORD(tp);
-         memcpy(fhead.FNAME, tp, rd-(USHORT)(tp-readbuf));
+         if (fhead.FNAME_SIZE > sizeof(fhead.FNAME) ||
+             fhead.FNAME_SIZE + need_size > head.HEAD_SIZE)
+            return 0;
+         memcpy(fhead.FNAME, tp, fhead.FNAME_SIZE);
          break;
 //    default: (REC_BLK and future things): 
 //              do nothing 'cause isn't needed for extraction