Blob Blame History Raw
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;