...
|
...
|
@@ -464,20 +464,18 @@ static void ole2_read_property_tree(int fd, ole2_header_t *hdr, const char *dir,
|
464
|
464
|
|
465
|
465
|
static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir, int32_t prop_index,
|
466
|
466
|
int (*handler)(int fd, ole2_header_t *hdr, property_t *prop, const char *dir),
|
467
|
|
- unsigned int rec_level, unsigned int *file_count, const struct cl_limits *limits)
|
|
467
|
+ unsigned int rec_level, unsigned int *file_count, cli_ctx *ctx, unsigned long *scansize)
|
468
|
468
|
{
|
469
|
469
|
property_t prop_block[4];
|
470
|
470
|
int32_t idx, current_block, i;
|
471
|
471
|
char *dirname;
|
|
472
|
+ const struct cl_limits *limits = ctx->limits;
|
472
|
473
|
|
473
|
474
|
current_block = hdr->prop_start;
|
474
|
475
|
|
475
|
476
|
if ((prop_index < 0) || (prop_index > (int32_t) hdr->max_block_no) || (rec_level > 100) || (*file_count > 100000)) {
|
476
|
477
|
return;
|
477
|
478
|
}
|
478
|
|
- /* FIXMELIMITS
|
479
|
|
- * DOES recursion on virtual object make sense ?
|
480
|
|
- * WHY no size checking ? */
|
481
|
479
|
if (limits && limits->maxfiles && (*file_count > limits->maxfiles)) {
|
482
|
480
|
cli_dbgmsg("OLE2: File limit reached (max: %d)\n", limits->maxfiles);
|
483
|
481
|
return;
|
...
|
...
|
@@ -537,28 +535,37 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
|
537
|
537
|
}
|
538
|
538
|
hdr->sbat_root_start = prop_block[idx].start_block;
|
539
|
539
|
ole2_walk_property_tree(fd, hdr, dir,
|
540
|
|
- prop_block[idx].prev, handler, rec_level+1, file_count, limits);
|
|
540
|
+ prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize);
|
541
|
541
|
ole2_walk_property_tree(fd, hdr, dir,
|
542
|
|
- prop_block[idx].next, handler, rec_level+1, file_count, limits);
|
|
542
|
+ prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize);
|
543
|
543
|
ole2_walk_property_tree(fd, hdr, dir,
|
544
|
|
- prop_block[idx].child, handler, rec_level+1, file_count, limits);
|
|
544
|
+ prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize);
|
545
|
545
|
break;
|
546
|
546
|
case 2: /* File */
|
547
|
|
- (*file_count)++;
|
548
|
|
- if (!handler(fd, hdr, &prop_block[idx], dir)) {
|
549
|
|
- cli_dbgmsg("ERROR: handler failed\n");
|
550
|
|
- /* If we don't return on this error then
|
551
|
|
- we can sometimes pull VBA code
|
552
|
|
- from corrupted files.
|
553
|
|
- */
|
|
547
|
+ if (limits && limits->maxfiles && ctx->scannedfiles + *file_count > limits->maxfiles) {
|
|
548
|
+ cli_dbgmsg("ole2: files limit reached (max: %u)\n", ctx->limits->maxfiles);
|
|
549
|
+ break;
|
|
550
|
+ }
|
|
551
|
+ if (!limits || !limits->maxfilesize || prop_block[idx].size <= limits->maxfilesize || *scansize == -1 || prop_block[idx].size <= *scansize) {
|
|
552
|
+ (*file_count)++;
|
|
553
|
+ *scansize-=prop_block[idx].size;
|
|
554
|
+ if (!handler(fd, hdr, &prop_block[idx], dir)) {
|
|
555
|
+ cli_dbgmsg("ERROR: handler failed\n");
|
|
556
|
+ /* If we don't return on this error then
|
|
557
|
+ we can sometimes pull VBA code
|
|
558
|
+ from corrupted files.
|
|
559
|
+ */
|
554
|
560
|
|
|
561
|
+ }
|
|
562
|
+ } else {
|
|
563
|
+ cli_dbgmsg("ole2: filesize exceeded\n");
|
555
|
564
|
}
|
556
|
565
|
ole2_walk_property_tree(fd, hdr, dir,
|
557
|
|
- prop_block[idx].prev, handler, rec_level, file_count, limits);
|
|
566
|
+ prop_block[idx].prev, handler, rec_level, file_count, ctx, scansize);
|
558
|
567
|
ole2_walk_property_tree(fd, hdr, dir,
|
559
|
|
- prop_block[idx].next, handler, rec_level, file_count, limits);
|
|
568
|
+ prop_block[idx].next, handler, rec_level, file_count, ctx, scansize);
|
560
|
569
|
ole2_walk_property_tree(fd, hdr, dir,
|
561
|
|
- prop_block[idx].child, handler, rec_level, file_count, limits);
|
|
570
|
+ prop_block[idx].child, handler, rec_level, file_count, ctx, scansize);
|
562
|
571
|
break;
|
563
|
572
|
case 1: /* Directory */
|
564
|
573
|
dirname = (char *) cli_malloc(strlen(dir)+8);
|
...
|
...
|
@@ -572,11 +579,11 @@ static void ole2_walk_property_tree(int fd, ole2_header_t *hdr, const char *dir,
|
572
|
572
|
}
|
573
|
573
|
cli_dbgmsg("OLE2 dir entry: %s\n",dirname);
|
574
|
574
|
ole2_walk_property_tree(fd, hdr, dir,
|
575
|
|
- prop_block[idx].prev, handler, rec_level+1, file_count, limits);
|
|
575
|
+ prop_block[idx].prev, handler, rec_level+1, file_count, ctx, scansize);
|
576
|
576
|
ole2_walk_property_tree(fd, hdr, dir,
|
577
|
|
- prop_block[idx].next, handler, rec_level+1, file_count, limits);
|
|
577
|
+ prop_block[idx].next, handler, rec_level+1, file_count, ctx, scansize);
|
578
|
578
|
ole2_walk_property_tree(fd, hdr, dirname,
|
579
|
|
- prop_block[idx].child, handler, rec_level+1, file_count, limits);
|
|
579
|
+ prop_block[idx].child, handler, rec_level+1, file_count, ctx, scansize);
|
580
|
580
|
free(dirname);
|
581
|
581
|
break;
|
582
|
582
|
default:
|
...
|
...
|
@@ -786,8 +793,16 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx)
|
786
|
786
|
int hdr_size;
|
787
|
787
|
struct stat statbuf;
|
788
|
788
|
unsigned int file_count=0;
|
789
|
|
-
|
|
789
|
+ unsigned long scansize;
|
|
790
|
+
|
790
|
791
|
cli_dbgmsg("in cli_ole2_extract()\n");
|
|
792
|
+
|
|
793
|
+ if (ctx->limits && ctx->limits->maxscansize) {
|
|
794
|
+ if (ctx->limits->maxscansize > ctx->scansize)
|
|
795
|
+ scansize = ctx->limits->maxscansize - ctx->scansize;
|
|
796
|
+ else
|
|
797
|
+ return CL_EMAXSIZE;
|
|
798
|
+ } else scansize = -1;
|
791
|
799
|
|
792
|
800
|
/* size of header - size of other values in struct */
|
793
|
801
|
hdr_size = sizeof(struct ole2_header_tag) - sizeof(int32_t) -
|
...
|
...
|
@@ -880,7 +895,7 @@ int cli_ole2_extract(int fd, const char *dirname, cli_ctx *ctx)
|
880
|
880
|
|
881
|
881
|
/* OR */
|
882
|
882
|
|
883
|
|
- ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx->limits);
|
|
883
|
+ ole2_walk_property_tree(fd, &hdr, dirname, 0, handler_writefile, 0, &file_count, ctx, &scansize);
|
884
|
884
|
|
885
|
885
|
abort:
|
886
|
886
|
#ifdef HAVE_MMAP
|