git-svn: trunk@2258
Trog authored on 2006/09/14 17:14:22... | ... |
@@ -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 |
} |