Browse code

libclamunrar, libclamav: don't depend on the uncompressed size field in RAR headers (bb#1467)

git-svn: trunk@4977

Tomasz Kojm authored on 2009/03/23 21:55:23
Showing 6 changed files
... ...
@@ -1,3 +1,9 @@
1
+Mon Mar 23 13:52:31 CET 2009 (tk)
2
+---------------------------------
3
+ * libclamunrar, libclamav: don't depend on the uncompressed size field
4
+			    in RAR headers (bb#1467)
5
+			    Reported by Thierry Zoller
6
+
1 7
 Mon Mar 23 13:12:08 EET 2009 (edwin)
2 8
 ------------------------------------
3 9
  * libclamav/mbox.c: fix extraction of embedded images (bb #1384).
... ...
@@ -319,12 +319,17 @@ static int cli_scanrar(int desc, cli_ctx *ctx, off_t sfx_offset, uint32_t *sfx_c
319 319
 		ret = CL_EUNPACK;
320 320
 	    break;
321 321
 	}
322
-	if((ret=cli_checklimits("RAR", ctx, rar_state.metadata_tail->unpack_size, rar_state.metadata_tail->pack_size, 0)!=CL_CLEAN)) {
322
+	if(ctx->engine->maxscansize && ctx->scansize >= ctx->engine->maxscansize) {
323 323
 	    free(rar_state.file_header->filename);
324 324
 	    free(rar_state.file_header);
325 325
 	    ret = CL_CLEAN;
326
-	    continue;
326
+	    break;
327 327
 	}
328
+	if(ctx->engine->maxscansize && ctx->scansize + ctx->engine->maxfilesize >= ctx->engine->maxscansize)
329
+	    rar_state.maxfilesize = ctx->engine->maxscansize - ctx->scansize;
330
+	else
331
+	    rar_state.maxfilesize = ctx->engine->maxfilesize;
332
+
328 333
 	ret = cli_unrar_extract_next(&rar_state,dir);
329 334
 	if(ret == UNRAR_OK)
330 335
 	    ret = CL_SUCCESS;
... ...
@@ -153,9 +153,18 @@ static void unp_write_data(unpack_data_t *unpack_data, uint8_t *data, int size)
153 153
 {
154 154
 	int ret;
155 155
 	rar_dbgmsg("in unp_write_data length=%d\n", size);
156
+
157
+	unpack_data->true_size += size;
158
+	unpack_data->unp_crc = rar_crc(unpack_data->unp_crc, data, size);
159
+	if(unpack_data->max_size) {
160
+	    if(unpack_data->written_size >= unpack_data->max_size)
161
+		return;
162
+
163
+	    if(unpack_data->written_size + size > unpack_data->max_size)
164
+		size = unpack_data->max_size - unpack_data->written_size;
165
+	}
156 166
 	if((ret = write(unpack_data->ofd, data, size)) > 0)
157 167
 	    unpack_data->written_size += ret;
158
-	unpack_data->unp_crc = rar_crc(unpack_data->unp_crc, data, size);
159 168
 }
160 169
 
161 170
 static void unp_write_area(unpack_data_t *unpack_data, unsigned int start_ptr, unsigned int end_ptr)
... ...
@@ -827,6 +836,7 @@ void rar_unpack_init_data(int solid, unpack_data_t *unpack_data)
827 827
 	unpack_data->read_top = 0;
828 828
 	unpack_data->read_border = 0;
829 829
 	unpack_data->written_size = 0;
830
+	unpack_data->true_size = 0;
830 831
 	rarvm_init(&unpack_data->rarvm_data);
831 832
 	unpack_data->unp_crc = 0xffffffff;
832 833
 	
... ...
@@ -1067,7 +1077,6 @@ static int rar_unpack29(int fd, int solid, unpack_data_t *unpack_data)
1067 1067
 	if (retval) {
1068 1068
 		unp_write_buf(unpack_data);
1069 1069
 	}
1070
-	rar_dbgmsg("Finished length: %ld\n", unpack_data->written_size);
1071 1070
 	return retval;
1072 1071
 }
1073 1072
 
... ...
@@ -1094,5 +1103,8 @@ int rar_unpack(int fd, int method, int solid, unpack_data_t *unpack_data)
1094 1094
 		}
1095 1095
 		break;
1096 1096
 	}
1097
+	rar_dbgmsg("Written size: %ld\n", unpack_data->written_size);
1098
+	rar_dbgmsg("True size: %ld\n", unpack_data->true_size);
1099
+
1097 1100
 	return retval;
1098 1101
 }
... ...
@@ -217,6 +217,8 @@ typedef struct unpack_data_tag
217 217
 	int *old_filter_lengths;
218 218
 	int last_filter, old_filter_lengths_size;
219 219
 	int64_t written_size;
220
+	int64_t true_size;
221
+	int64_t max_size;
220 222
 	int64_t dest_unp_size;
221 223
 	rarvm_data_t rarvm_data;
222 224
 	unsigned int unp_crc;
... ...
@@ -308,6 +308,7 @@ int unrar_open(int fd, const char *dirname, unrar_state_t *state)
308 308
     unpack_data->PrgStack.array = unpack_data->Filters.array = NULL;
309 309
     unpack_data->PrgStack.num_items = unpack_data->Filters.num_items = 0;
310 310
     unpack_data->unp_crc = 0xffffffff;
311
+    unpack_data->max_size = 0;
311 312
 
312 313
     ppm_constructor(&unpack_data->ppm_data);
313 314
 
... ...
@@ -391,6 +392,7 @@ int unrar_extract_next_prepare(unrar_state_t *state, const char *dirname)
391 391
 
392 392
     new_metadata->pack_size = state->file_header->high_pack_size * 0x100000000ULL + state->file_header->pack_size;
393 393
     new_metadata->unpack_size = state->file_header->high_unpack_size * 0x100000000ULL + state->file_header->unpack_size;
394
+    new_metadata->unpack_size = state->file_header->unpack_size;
394 395
     new_metadata->crc = state->file_header->file_crc;
395 396
     new_metadata->method = state->file_header->method;
396 397
     new_metadata->filename = strdup((const char*)state->file_header->filename);
... ...
@@ -473,6 +475,7 @@ int unrar_extract_next(unrar_state_t *state, const char *dirname)
473 473
 	}
474 474
 	unpack_data = (unpack_data_t *) state->unpack_data;
475 475
 	state->ofd = unpack_data->ofd = ofd;
476
+	unpack_data->max_size = state->maxfilesize;
476 477
 	if(state->file_header->method == 0x30) {
477 478
 	    unrar_dbgmsg("UNRAR: Copying stored file (not packed)\n");
478 479
 	    copy_file_data(state->fd, ofd, state->file_header->pack_size);
... ...
@@ -110,6 +110,7 @@ typedef struct unrar_state_tag {
110 110
     unrar_main_header_t *main_hdr;
111 111
     char *comment_dir;
112 112
     unsigned long file_count;
113
+    uint64_t maxfilesize;
113 114
     int fd, ofd;
114 115
     char filename[1024];
115 116
 } unrar_state_t;