Browse code

improve handling of corrupted files.

git-svn: trunk@2258

Trog authored on 2006/09/14 17:14:22
Showing 4 changed files
... ...
@@ -1,3 +1,8 @@
1
+Thu Sep 14 09:12:03 BST 2006 (trog)
2
+-----------------------------------
3
+  * libclamav/unrar/unrar.c, unrar20.c, unrarppm.c: improve handling of
4
+		corrupted files.
5
+
1 6
 Thu Sep 14 00:35:56 CEST 2006 (acab)
2 7
 ------------------------------------
3 8
   * docs: Added preliminary documentation related to Edvin phishing module.
... ...
@@ -395,7 +395,10 @@ int unp_read_buf(int fd, unpack_data_t *unpack_data)
395 395
 unsigned int rar_get_char(int fd, unpack_data_t *unpack_data)
396 396
 {
397 397
 	if (unpack_data->in_addr > MAX_BUF_SIZE-30) {
398
-		unp_read_buf(fd, unpack_data);
398
+		if (!unp_read_buf(fd, unpack_data)) {
399
+			cli_errmsg("rar_get_char: unp_read_buf FAILED\n");
400
+			return -1;
401
+		}
399 402
 	}
400 403
 	rar_dbgmsg("rar_get_char = %u\n", unpack_data->in_buf[unpack_data->in_addr]);
401 404
 	return(unpack_data->in_buf[unpack_data->in_addr++]);
... ...
@@ -1100,7 +1103,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1100 1100
 	unsigned char sddecode[]={0,4,8,16,32,64,128,192};
1101 1101
 	unsigned char sdbits[]=  {2,2,3, 4, 5, 6,  6,  6};
1102 1102
 	unsigned int bits, distance;
1103
-	int i, number, length, dist_number, low_dist, ch, next_ch;
1103
+	int retval=TRUE, i, number, length, dist_number, low_dist, ch, next_ch;
1104 1104
 	int length_number, failed;
1105 1105
 
1106 1106
 	cli_dbgmsg("Offset: %ld\n", lseek(fd, 0, SEEK_CUR));
... ...
@@ -1124,6 +1127,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1124 1124
 		rar_dbgmsg("UnpPtr = %d\n", unpack_data->unp_ptr);
1125 1125
 		if (unpack_data->in_addr > unpack_data->read_border) {
1126 1126
 			if (!unp_read_buf(fd, unpack_data)) {
1127
+				retval = FALSE;
1127 1128
 				break;
1128 1129
 			}
1129 1130
 		}
... ...
@@ -1135,6 +1139,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1135 1135
 			ch = ppm_decode_char(&unpack_data->ppm_data, fd, unpack_data);
1136 1136
 			rar_dbgmsg("PPM char: %d\n", ch);
1137 1137
 			if (ch == -1) {
1138
+				retval = FALSE;
1138 1139
 				unpack_data->ppm_error = TRUE;
1139 1140
 				break;
1140 1141
 			}
... ...
@@ -1142,8 +1147,14 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1142 1142
 				next_ch = ppm_decode_char(&unpack_data->ppm_data,
1143 1143
 							fd, unpack_data);
1144 1144
 				rar_dbgmsg("PPM next char: %d\n", next_ch);
1145
+				if (next_ch == -1) {
1146
+					retval = FALSE;
1147
+					unpack_data->ppm_error = TRUE;
1148
+					break;
1149
+				}
1145 1150
 				if (next_ch == 0) {
1146 1151
 					if (!read_tables(fd, unpack_data)) {
1152
+						retval = FALSE;
1147 1153
 						break;
1148 1154
 					}
1149 1155
 					continue;
... ...
@@ -1153,6 +1164,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1153 1153
 				}
1154 1154
 				if (next_ch == 3) {
1155 1155
 					if (!read_vm_code_PPM(unpack_data, fd)) {
1156
+						retval = FALSE;
1156 1157
 						break;
1157 1158
 					}
1158 1159
 					continue;
... ...
@@ -1176,6 +1188,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1176 1176
 						}
1177 1177
 					}
1178 1178
 					if (failed) {
1179
+						retval = FALSE;
1179 1180
 						break;
1180 1181
 					}
1181 1182
 					copy_string(unpack_data, length+32, distance+2);
... ...
@@ -1186,6 +1199,7 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1186 1186
 								fd, unpack_data);
1187 1187
 					rar_dbgmsg("PPM length: %d\n", length);
1188 1188
 					if (length == -1) {
1189
+						retval = FALSE;
1189 1190
 						break;
1190 1191
 					}
1191 1192
 					copy_string(unpack_data, length+4, 1);
... ...
@@ -1252,12 +1266,14 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1252 1252
 			}
1253 1253
 			if (number == 256) {
1254 1254
 				if (!read_end_of_block(fd, unpack_data)) {
1255
+					retval = FALSE;
1255 1256
 					break;
1256 1257
 				}
1257 1258
 				continue;
1258 1259
 			}
1259 1260
 			if (number == 257) {
1260 1261
 				if (!read_vm_code(unpack_data, fd)) {
1262
+					retval = FALSE;
1261 1263
 					break;
1262 1264
 				}
1263 1265
 				continue;
... ...
@@ -1302,10 +1318,11 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1302 1302
 	
1303 1303
 		}
1304 1304
 	}
1305
-	unp_write_buf(unpack_data);
1305
+	if (retval) {
1306
+		unp_write_buf(unpack_data);
1307
+	}
1306 1308
 	cli_dbgmsg("Finished length: %ld\n", unpack_data->written_size);
1307
-	/*cli_writen(unpack_data->ofd, unpack_data->window, unpack_data->unp_ptr);*/
1308
-	return TRUE;
1309
+	return retval;
1309 1310
 }
1310 1311
 
1311 1312
 static int rar_unpack(int fd, int method, int solid, unpack_data_t *unpack_data)
... ...
@@ -1323,7 +1340,7 @@ static int rar_unpack(int fd, int method, int solid, unpack_data_t *unpack_data)
1323 1323
 		retval = rar_unpack29(fd, solid, unpack_data);
1324 1324
 		break;
1325 1325
 	default:
1326
-		printf("ERROR: Unknown pack method: %d\n", method);
1326
+		cli_errmsg("ERROR: Unknown RAR pack method: %d\n", method);
1327 1327
 		break;
1328 1328
 	}
1329 1329
 	return retval;
... ...
@@ -1332,7 +1349,7 @@ static int rar_unpack(int fd, int method, int solid, unpack_data_t *unpack_data)
1332 1332
 rar_metadata_t *cli_unrar(int fd, const char *dirname, const struct cl_limits *limits)
1333 1333
 {
1334 1334
 	main_header_t *main_hdr;
1335
-	int ofd;
1335
+	int ofd, retval;
1336 1336
 	unsigned long file_count=1;
1337 1337
 	file_header_t *file_header;
1338 1338
 	unsigned char filename[1024];
... ...
@@ -1450,18 +1467,19 @@ rar_metadata_t *cli_unrar(int fd, const char *dirname, const struct cl_limits *l
1450 1450
 			}
1451 1451
 			unpack_data->ofd = ofd;
1452 1452
 			if (file_header->method == 0x30) {
1453
+				cli_dbgmsg("Copying stored file (not packed)\n");
1453 1454
 				copy_file_data(fd, ofd, file_header->pack_size);
1454 1455
 			} else {
1455 1456
 				unpack_data->dest_unp_size = file_header->unpack_size;
1456 1457
 				if (file_header->unpack_ver <= 15) {
1457
-					rar_unpack(fd, 15, (file_count>1) &&
1458
+					retval = rar_unpack(fd, 15, (file_count>1) &&
1458 1459
 						((main_hdr->flags&MHD_SOLID)!=0), unpack_data);
1459 1460
 				} else {
1460 1461
 					if ((file_count == 1) && (file_header->flags & LHD_SOLID)) {
1461 1462
 						cli_warnmsg("RAR: First file can't be SOLID.\n");
1462 1463
 						break;
1463 1464
 					} else {
1464
-						rar_unpack(fd, file_header->unpack_ver,
1465
+						retval = rar_unpack(fd, file_header->unpack_ver,
1465 1466
 							file_header->flags & LHD_SOLID,	unpack_data);
1466 1467
 					}
1467 1468
 				}
... ...
@@ -1472,6 +1490,13 @@ rar_metadata_t *cli_unrar(int fd, const char *dirname, const struct cl_limits *l
1472 1472
 						cli_warnmsg("RAR CRC error. Please report the bug at https://bugs.clamav.net/\n");
1473 1473
 					}
1474 1474
 				}
1475
+				if (!retval) {
1476
+					cli_dbgmsg("Corrupt file detected\n");
1477
+					if (file_header->flags & LHD_SOLID) {
1478
+						cli_dbgmsg("SOLID archive, can't continue\n");
1479
+						break;
1480
+					}
1481
+				}
1475 1482
 			}
1476 1483
 		
1477 1484
 			close(ofd);
... ...
@@ -285,7 +285,7 @@ int rar_unpack20(int fd, int solid, unpack_data_t *unpack_data)
285 285
 	unsigned char sddecode[]={0,4,8,16,32,64,128,192};
286 286
 	unsigned char sdbits[]={2,2,3,4,5,6,6,6};
287 287
 	unsigned int bits, distance;
288
-	int audio_number, number, length, dist_number, length_number;
288
+	int retval=TRUE, audio_number, number, length, dist_number, length_number;
289 289
 	
290 290
 	rar_dbgmsg("in rar_unpack20\n");
291 291
 
... ...
@@ -321,6 +321,7 @@ int rar_unpack20(int fd, int solid, unpack_data_t *unpack_data)
321 321
 				(struct Decode *)&unpack_data->MD[unpack_data->unp_cur_channel]);
322 322
 			if (audio_number == 256) {
323 323
 				if (!read_tables20(fd, unpack_data)) {
324
+					retval = FALSE;
324 325
 					break;
325 326
 				}
326 327
 				continue;
... ...
@@ -366,6 +367,7 @@ int rar_unpack20(int fd, int solid, unpack_data_t *unpack_data)
366 366
 		}
367 367
 		if (number == 269) {
368 368
 			if (!read_tables20(fd, unpack_data)) {
369
+				retval = FALSE;
369 370
 				break;
370 371
 			}
371 372
 			continue;
... ...
@@ -404,7 +406,9 @@ int rar_unpack20(int fd, int solid, unpack_data_t *unpack_data)
404 404
 			continue;
405 405
 		}
406 406
 	}
407
-	read_last_tables(fd, unpack_data);
408
-	unp_write_buf_old(unpack_data);
409
-	return TRUE;
407
+	if (retval) {
408
+		read_last_tables(fd, unpack_data);
409
+		unp_write_buf_old(unpack_data);
410
+	}
411
+	return retval;
410 412
 }
... ...
@@ -162,7 +162,7 @@ static void rar_mem_blk_insertAt(rar_mem_blk_t *a, rar_mem_blk_t *p)
162 162
 	p->next = a->next->prev = a;
163 163
 }
164 164
 
165
-static void rar_mem_blk_remove(rar_mem_blk_t *a)
165
+static int rar_mem_blk_remove(rar_mem_blk_t *a)
166 166
 {
167 167
 	a->prev->next = a->next;
168 168
 	a->next->prev = a->prev;
... ...
@@ -390,7 +390,7 @@ static int restart_model_rare(ppm_data_t *ppm_data)
390 390
 		(struct ppm_context *) sub_allocator_alloc_context(&ppm_data->sub_alloc);
391 391
 	if(!ppm_data->min_context) {
392 392
 	    cli_errmsg("unrar: restart_model_rare: sub_allocator_alloc_context failed\n");
393
-	    return -1;
393
+	    return FALSE;
394 394
 	}
395 395
 	ppm_data->min_context->suffix = NULL;
396 396
 	ppm_data->order_fall = ppm_data->max_order;
... ...
@@ -399,7 +399,7 @@ static int restart_model_rare(ppm_data_t *ppm_data)
399 399
 		(struct state_tag *)sub_allocator_alloc_units(&ppm_data->sub_alloc, 256/2);
400 400
 	if(!ppm_data->found_state) {
401 401
 	    cli_errmsg("unrar: restart_model_rare: sub_allocator_alloc_units failed\n");
402
-	    return -1;
402
+	    return FALSE;
403 403
 	}
404 404
 	for (ppm_data->run_length = ppm_data->init_rl, ppm_data->prev_success=i=0; i < 256 ; i++) {
405 405
 		ppm_data->min_context->con_ut.u.stats[i].symbol = i;
... ...
@@ -420,7 +420,7 @@ static int restart_model_rare(ppm_data_t *ppm_data)
420 420
 		}
421 421
 	}
422 422
 
423
-	return 0;
423
+	return TRUE;
424 424
 }
425 425
 	
426 426
 static int start_model_rare(ppm_data_t *ppm_data, int max_order)
... ...
@@ -430,9 +430,9 @@ static int start_model_rare(ppm_data_t *ppm_data, int max_order)
430 430
 	ppm_data->esc_count = 1;
431 431
 	ppm_data->max_order = max_order;
432 432
 	
433
-	if((ret = restart_model_rare(ppm_data))) {
433
+	if (!restart_model_rare(ppm_data)) {
434 434
 	    cli_dbgmsg("unrar: start_model_rare: restart_model_rare failed\n");
435
-	    return ret;
435
+	    return FALSE;
436 436
 	}
437 437
 	
438 438
 	ppm_data->ns2bsindx[0] = 2*0;
... ...
@@ -454,7 +454,7 @@ static int start_model_rare(ppm_data_t *ppm_data, int max_order)
454 454
 	memset(ppm_data->hb2flag, 0, 0x40);
455 455
 	memset(ppm_data->hb2flag+0x40, 0x08, 0x100-0x40);
456 456
 	ppm_data->dummy_sse2cont.shift = PERIOD_BITS;
457
-	return 0;
457
+	return TRUE;
458 458
 }
459 459
 
460 460
 	
... ...
@@ -650,7 +650,7 @@ static int update_model(ppm_data_t *ppm_data)
650 650
 		if (!ppm_data->min_context) {
651 651
 			goto RESTART_MODEL;
652 652
 		}
653
-		return 0;
653
+		return TRUE;
654 654
 	}
655 655
 	*ppm_data->sub_alloc.ptext++ = fs.symbol;
656 656
 	successor = (struct ppm_context *) ppm_data->sub_alloc.ptext;
... ...
@@ -712,15 +712,15 @@ static int update_model(ppm_data_t *ppm_data)
712 712
 		pc->num_stats = ++ns1;
713 713
 	}
714 714
 	ppm_data->max_context = ppm_data->min_context = fs.successor;
715
-	return 0;
715
+	return TRUE;
716 716
 	
717 717
 RESTART_MODEL:
718
-	if((ret = restart_model_rare(ppm_data))) {
718
+	if (!restart_model_rare(ppm_data)) {
719 719
 	    cli_dbgmsg("unrar: update_model: restart_model_rare: failed\n");
720
-	    return ret;
720
+	    return FALSE;
721 721
 	}
722 722
 	ppm_data->esc_count = 0;
723
-	return 0;
723
+	return TRUE;
724 724
 }
725 725
 
726 726
 static void update1(ppm_data_t *ppm_data, struct state_tag *p, struct ppm_context *context)
... ...
@@ -951,7 +951,7 @@ int ppm_decode_init(ppm_data_t *ppm_data, int fd, unpack_data_t *unpack_data, in
951 951
 		    sub_allocator_stop_sub_allocator(&ppm_data->sub_alloc);
952 952
 		    return FALSE;
953 953
 		}
954
-		if(start_model_rare(ppm_data, max_order) < 0) {
954
+		if (!start_model_rare(ppm_data, max_order)) {
955 955
 		    sub_allocator_stop_sub_allocator(&ppm_data->sub_alloc);
956 956
 		    return FALSE;
957 957
 		}
... ...
@@ -963,7 +963,7 @@ int ppm_decode_init(ppm_data_t *ppm_data, int fd, unpack_data_t *unpack_data, in
963 963
 int ppm_decode_char(ppm_data_t *ppm_data, int fd, unpack_data_t *unpack_data)
964 964
 {
965 965
 	int symbol;
966
-	
966
+
967 967
 	if ((uint8_t *) ppm_data->min_context <= ppm_data->sub_alloc.ptext ||
968 968
 			(uint8_t *)ppm_data->min_context > ppm_data->sub_alloc.heap_end) {
969 969
 		return -1;
... ...
@@ -999,7 +999,7 @@ int ppm_decode_char(ppm_data_t *ppm_data, int fd, unpack_data_t *unpack_data)
999 999
 	if (!ppm_data->order_fall && (uint8_t *) ppm_data->found_state->successor > ppm_data->sub_alloc.ptext) {
1000 1000
 		ppm_data->min_context = ppm_data->max_context = ppm_data->found_state->successor;
1001 1001
 	} else {
1002
-		if(update_model(ppm_data)) {
1002
+		if(!update_model(ppm_data)) {
1003 1003
 		    cli_dbgmsg("unrar: ppm_decode_char: update_model failed\n");
1004 1004
 		    return -1;
1005 1005
 		}