diff -pruN clamav-0.92.1.orig/libclamav/unarj.c clamav-0.92.1/libclamav/unarj.c
--- clamav-0.92.1.orig/libclamav/unarj.c 2008-02-06 16:14:24.000000000 +0100
+++ clamav-0.92.1/libclamav/unarj.c 2008-04-24 19:20:59.000000000 +0200
@@ -160,6 +160,7 @@ typedef struct arj_decode_tag {
uint16_t c_table[CTABLESIZE];
unsigned char pt_len[NPT];
uint16_t pt_table[PTABLESIZE];
+ int status;
} arj_decode_t;
static int fill_buf(arj_decode_t *decode_data, int n)
@@ -170,6 +171,7 @@ static int fill_buf(arj_decode_t *decode
if (decode_data->comp_size != 0) {
decode_data->comp_size--;
if (cli_readn(decode_data->fd, &decode_data->sub_bit_buf, 1) != 1) {
+ decode_data->status = CL_EIO;
return CL_EIO;
}
} else {
@@ -228,6 +230,7 @@ static int make_table(arj_decode_t *deco
for (i = 0; (int)i < nchar; i++) {
if (bitlen[i] >= 17) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
count[bitlen[i]]++;
@@ -238,12 +241,14 @@ static int make_table(arj_decode_t *deco
start[i+1] = start[i] + (count[i] << (16 - i));
}
if (start[17] != (unsigned short) (1 << 16)) {
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
jutbits = 16 - tablebits;
if (tablebits >= 17) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
for (i = 1; (int)i <= tablebits; i++) {
@@ -261,6 +266,7 @@ static int make_table(arj_decode_t *deco
while (i != k) {
if (i >= tablesize) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
table[i++] = 0;
@@ -275,12 +281,14 @@ static int make_table(arj_decode_t *deco
}
if (len >= 17) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
k = start[len];
nextcode = k + weight[len];
if ((int)len <= tablebits) {
if (nextcode > (unsigned int) tablesize) {
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
for (i = start[len]; i < nextcode; i++) {
@@ -293,6 +301,7 @@ static int make_table(arj_decode_t *deco
if (*p == 0) {
if (avail >= (2 * NC - 1)) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
decode_data->right[avail] = decode_data->left[avail] = 0;
@@ -300,6 +309,7 @@ static int make_table(arj_decode_t *deco
}
if (*p >= (2 * NC - 1)) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
if (k & mask) {
@@ -317,7 +327,7 @@ static int make_table(arj_decode_t *deco
return CL_SUCCESS;
}
-static void read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special)
+static int read_pt_len(arj_decode_t *decode_data, int nn, int nbit, int i_special)
{
int i, n;
short c;
@@ -327,7 +337,8 @@ static void read_pt_len(arj_decode_t *de
if (n == 0) {
if (nn > NPT) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
- return;
+ decode_data->status = CL_EARJ;
+ return CL_EARJ;
}
c = arj_getbits(decode_data, nbit);
for (i = 0; i < nn; i++) {
@@ -348,9 +359,15 @@ static void read_pt_len(arj_decode_t *de
}
}
fill_buf(decode_data, (c < 7) ? 3 : (int)(c - 3));
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
decode_data->pt_len[i++] = (unsigned char) c;
if (i == i_special) {
c = arj_getbits(decode_data, 2);
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
while ((--c >= 0) && (i < NPT)) {
decode_data->pt_len[i++] = 0;
}
@@ -359,8 +376,11 @@ static void read_pt_len(arj_decode_t *de
while ((i < nn) && (i < NPT)) {
decode_data->pt_len[i++] = 0;
}
- make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE);
+ if (make_table(decode_data, nn, decode_data->pt_len, 8, decode_data->pt_table, PTABLESIZE) != CL_SUCCESS) {
+ return CL_EARJ;
+ }
}
+ return CL_SUCCESS;
}
static int read_c_len(arj_decode_t *decode_data)
@@ -369,8 +389,14 @@ static int read_c_len(arj_decode_t *deco
unsigned short mask;
n = arj_getbits(decode_data, CBIT);
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
if (n == 0) {
c = arj_getbits(decode_data, CBIT);
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
for (i = 0; i < NC; i++) {
decode_data->c_len[i] = 0;
}
@@ -386,6 +412,7 @@ static int read_c_len(arj_decode_t *deco
do {
if (c >= (2 * NC - 1)) {
cli_warnmsg("ERROR: bounds exceeded\n");
+ decode_data->status = CL_EFORMAT;
return CL_EFORMAT;
}
if (decode_data->bit_buf & mask) {
@@ -398,9 +425,13 @@ static int read_c_len(arj_decode_t *deco
}
if (c >= 19) {
cli_dbgmsg("UNARJ: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return CL_EARJ;
}
fill_buf(decode_data, (int)(decode_data->pt_len[c]));
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
if (c <= 2) {
if (c == 0) {
c = 1;
@@ -409,9 +440,13 @@ static int read_c_len(arj_decode_t *deco
} else {
c = arj_getbits(decode_data, CBIT) + 20;
}
+ if (decode_data->status != CL_SUCCESS) {
+ return decode_data->status;
+ }
while (--c >= 0) {
if (i >= NC) {
cli_warnmsg("ERROR: bounds exceeded\n");
+ decode_data->status = CL_EFORMAT;
return CL_EFORMAT;
}
decode_data->c_len[i++] = 0;
@@ -419,6 +454,7 @@ static int read_c_len(arj_decode_t *deco
} else {
if (i >= NC) {
cli_warnmsg("ERROR: bounds exceeded\n");
+ decode_data->status = CL_EFORMAT;
return CL_EFORMAT;
}
decode_data->c_len[i++] = (unsigned char) (c - 2);
@@ -427,7 +463,9 @@ static int read_c_len(arj_decode_t *deco
while (i < NC) {
decode_data->c_len[i++] = 0;
}
- make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE);
+ if (make_table(decode_data, NC, decode_data->c_len, 12, decode_data->c_table, CTABLESIZE) != CL_SUCCESS) {
+ return CL_EARJ;
+ }
}
return CL_SUCCESS;
}
@@ -450,6 +488,7 @@ static uint16_t decode_c(arj_decode_t *d
do {
if (j >= (2 * NC - 1)) {
cli_warnmsg("ERROR: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return 0;
}
if (decode_data->bit_buf & mask) {
@@ -474,6 +513,7 @@ static uint16_t decode_p(arj_decode_t *d
do {
if (j >= (2 * NC - 1)) {
cli_warnmsg("ERROR: bounds exceeded\n");
+ decode_data->status = CL_EARJ;
return 0;
}
if (decode_data->bit_buf & mask) {
@@ -508,8 +548,10 @@ static int decode(int fd, arj_metadata_t
decode_data.comp_size = metadata->comp_size;
ret = decode_start(&decode_data);
if (ret != CL_SUCCESS) {
+ free(decode_data.text);
return ret;
}
+ decode_data.status = CL_SUCCESS;
while (count < metadata->orig_size) {
if ((chr = decode_c(&decode_data)) <= UCHAR_MAX) {
@@ -517,7 +559,10 @@ static int decode(int fd, arj_metadata_t
count++;
if (++out_ptr >= DDICSIZ) {
out_ptr = 0;
- write_text(metadata->ofd, decode_data.text, DDICSIZ);
+ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
+ free(decode_data.text);
+ return CL_EIO;
+ }
}
} else {
j = chr - (UCHAR_MAX + 1 - THRESHOLD);
@@ -539,7 +584,10 @@ static int decode(int fd, arj_metadata_t
decode_data.text[out_ptr] = decode_data.text[i];
if (++out_ptr >= DDICSIZ) {
out_ptr = 0;
- write_text(metadata->ofd, decode_data.text, DDICSIZ);
+ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
+ free(decode_data.text);
+ return CL_EIO;
+ }
}
if (++i >= DDICSIZ) {
i = 0;
@@ -547,6 +595,10 @@ static int decode(int fd, arj_metadata_t
}
}
}
+ if (decode_data.status != CL_SUCCESS) {
+ free(decode_data.text);
+ return decode_data.status;
+ }
}
if (out_ptr != 0) {
write_text(metadata->ofd, decode_data.text, out_ptr);
@@ -623,21 +675,37 @@ static int decode_f(int fd, arj_metadata
return ret;
}
decode_data.getlen = decode_data.getbuf = 0;
-
+ decode_data.status = CL_SUCCESS;
+
while (count < metadata->orig_size) {
chr = decode_len(&decode_data);
+ if (decode_data.status != CL_SUCCESS) {
+ free(decode_data.text);
+ return decode_data.status;
+ }
if (chr == 0) {
ARJ_GETBITS(dd, chr, CHAR_BIT);
+ if (decode_data.status != CL_SUCCESS) {
+ free(decode_data.text);
+ return decode_data.status;
+ }
decode_data.text[out_ptr] = (unsigned char) chr;
count++;
if (++out_ptr >= DDICSIZ) {
out_ptr = 0;
- write_text(metadata->ofd, decode_data.text, DDICSIZ);
+ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
+ free(decode_data.text);
+ return CL_EIO;
+ }
}
} else {
j = chr - 1 + THRESHOLD;
count += j;
pos = decode_ptr(&decode_data);
+ if (decode_data.status != CL_SUCCESS) {
+ free(decode_data.text);
+ return decode_data.status;
+ }
if ((i = out_ptr - pos - 1) < 0) {
i += DDICSIZ;
}
@@ -649,7 +717,10 @@ static int decode_f(int fd, arj_metadata
decode_data.text[out_ptr] = decode_data.text[i];
if (++out_ptr >= DDICSIZ) {
out_ptr = 0;
- write_text(metadata->ofd, decode_data.text, DDICSIZ);
+ if (write_text(metadata->ofd, decode_data.text, DDICSIZ) != CL_SUCCESS) {
+ free(decode_data.text);
+ return CL_EIO;
+ }
}
if (++i >= DDICSIZ) {
i = 0;
@@ -1010,10 +1081,10 @@ int cli_unarj_extract_file(int fd, const
case 1:
case 2:
case 3:
- decode(fd, metadata);
+ ret = decode(fd, metadata);
break;
case 4:
- decode_f(fd, metadata);
+ ret = decode_f(fd, metadata);
break;
default:
ret = CL_EFORMAT;