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
|