Browse code

bb12356 - Improvement to overlapping zip files detection logic.

Increases zip overlapping file checking to equal the max scan files setting.

Micah Snyder authored on 2019/08/31 03:48:57
Showing 1 changed files
... ...
@@ -61,7 +61,7 @@
61 61
 #define ZIP_MAGIC_FILE_BEGIN_SPLIT_OR_SPANNED       (0x08074b50)
62 62
 // clang-format on
63 63
 
64
-#define ZIP_MAX_NUM_OVERLAPPING_FILES 5
64
+#define ZIP_MAX_NUM_OVERLAPPING_FILES 100
65 65
 
66 66
 #define ZIP_CRC32(r, c, b, l) \
67 67
     do {                      \
... ...
@@ -69,6 +69,13 @@
69 69
         r = ~r;               \
70 70
     } while (0)
71 71
 
72
+#define ZIP_RECORDS_CHECK_BLOCKSIZE 100
73
+struct zip_record {
74
+    uint32_t local_offset;
75
+    uint32_t local_header_size;
76
+    uint32_t local_data_size;
77
+};
78
+
72 79
 static int wrap_inflateinit2(void *a, int b)
73 80
 {
74 81
     return inflateInit2(a, b);
... ...
@@ -559,6 +566,8 @@ static inline cl_error_t zdecrypt(
559 559
 /**
560 560
  * @brief Parse, extract, and scan a file using the local file header.
561 561
  *
562
+ * Usage of the `record` parameter will alter behavior so it only collect file record metadata and does not extract or scan any files.
563
+ *
562 564
  * @param map                           fmap for the file
563 565
  * @param loff                          offset of the local file header
564 566
  * @param zsize                         size of the zip file
... ...
@@ -570,8 +579,7 @@ static inline cl_error_t zdecrypt(
570 570
  * @param tmpd                          temp directory path name
571 571
  * @param detect_encrypted              bool: if encrypted files should raise heuristic alert
572 572
  * @param zcb                           callback function to invoke after extraction (default: scan)
573
- * @param[out] file_local_header_size   (optional) size of the local file header
574
- * @param[out] file_local_data_size     (optional) size of the compressed local file data
573
+ * @param record                        (optional) a pointer to a struct to store file record information.
575 574
  * @return unsigned int                 returns the size of the file header + file data, so zip file can be indexed without the central directory
576 575
  */
577 576
 static unsigned int parse_local_file_header(
... ...
@@ -586,8 +594,7 @@ static unsigned int parse_local_file_header(
586 586
     char *tmpd,
587 587
     int detect_encrypted,
588 588
     zip_cb zcb,
589
-    uint32_t *file_local_header_size,
590
-    uint32_t *file_local_data_size)
589
+    struct zip_record *record)
591 590
 {
592 591
     const uint8_t *local_header, *zip;
593 592
     char name[256];
... ...
@@ -678,10 +685,10 @@ static unsigned int parse_local_file_header(
678 678
     zip += LOCAL_HEADER_elen;
679 679
     zsize -= LOCAL_HEADER_elen;
680 680
 
681
-    if (NULL != file_local_header_size)
682
-        *file_local_header_size = zip - local_header;
683
-    if (NULL != file_local_data_size)
684
-        *file_local_data_size = csize;
681
+    if (NULL != record) {
682
+        record->local_header_size = zip - local_header;
683
+        record->local_data_size   = csize;
684
+    }
685 685
 
686 686
     if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
687 687
         cli_dbgmsg("cli_unzip: local header - skipping empty file\n");
... ...
@@ -692,12 +699,15 @@ static unsigned int parse_local_file_header(
692 692
             return 0;
693 693
         }
694 694
 
695
-        if (LOCAL_HEADER_flags & F_ENCR) {
696
-            if (fmap_need_ptr_once(map, zip, csize))
697
-                *ret = zdecrypt(zip, csize, usize, local_header, num_files_unzipped, ctx, tmpd, zcb);
698
-        } else {
699
-            if (fmap_need_ptr_once(map, zip, csize))
700
-                *ret = unz(zip, csize, usize, LOCAL_HEADER_method, LOCAL_HEADER_flags, num_files_unzipped, ctx, tmpd, zcb);
695
+        /* Don't actually unzip if we're just collecting the file record information (offset, sizes) */
696
+        if (NULL == record) {
697
+            if (LOCAL_HEADER_flags & F_ENCR) {
698
+                if (fmap_need_ptr_once(map, zip, csize))
699
+                    *ret = zdecrypt(zip, csize, usize, local_header, num_files_unzipped, ctx, tmpd, zcb);
700
+            } else {
701
+                if (fmap_need_ptr_once(map, zip, csize))
702
+                    *ret = unz(zip, csize, usize, LOCAL_HEADER_method, LOCAL_HEADER_flags, num_files_unzipped, ctx, tmpd, zcb);
703
+            }
701 704
         }
702 705
         zip += csize;
703 706
         zsize -= csize;
... ...
@@ -730,6 +740,8 @@ static unsigned int parse_local_file_header(
730 730
 /**
731 731
  * @brief Parse, extract, and scan a file by iterating the central directory.
732 732
  *
733
+ * Usage of the `record` parameter will alter behavior so it only collect file record metadata and does not extract or scan any files.
734
+ *
733 735
  * @param map                           fmap for the file
734 736
  * @param coff                          offset of the file header in the central directory
735 737
  * @param zsize                         size of the zip file
... ...
@@ -740,12 +752,11 @@ static unsigned int parse_local_file_header(
740 740
  * @param tmpd                          temp directory path name
741 741
  * @param requests                      (optional) structure use to search the zip for files by name
742 742
  * @return unsigned int                 returns the size of the file header in the central directory, or 0 if no more files
743
- * @param[out] file_local_offset        (optional) offset of the local file header
744
- * @param[out] file_local_header_size   (optional) size of the local file header
745
- * @param[out] file_local_data_size     (optional) size of the compressed local file data
743
+ * @param record                        (optional) a pointer to a struct to store file record information.
746 744
  * @return unsigned int
747 745
  */
748
-static unsigned int parse_central_directory_file_header(
746
+static unsigned int
747
+parse_central_directory_file_header(
749 748
     fmap_t *map,
750 749
     uint32_t coff,
751 750
     uint32_t zsize,
... ...
@@ -755,22 +766,13 @@ static unsigned int parse_central_directory_file_header(
755 755
     cli_ctx *ctx,
756 756
     char *tmpd,
757 757
     struct zip_requests *requests,
758
-    uint32_t *file_local_offset,
759
-    uint32_t *file_local_header_size,
760
-    uint32_t *file_local_data_size)
758
+    struct zip_record *record)
761 759
 {
762 760
     char name[256];
763 761
     int last = 0;
764 762
     const uint8_t *central_header;
765 763
     int virus_found = 0;
766 764
 
767
-    if (NULL != file_local_offset)
768
-        *file_local_offset = 0;
769
-    if (NULL != file_local_header_size)
770
-        *file_local_header_size = 0;
771
-    if (NULL != file_local_data_size)
772
-        *file_local_data_size = 0;
773
-
774 765
     if (!(central_header = fmap_need_off(map, coff, SIZEOF_CENTRAL_HEADER)) || CENTRAL_HEADER_magic != ZIP_MAGIC_CENTRAL_DIRECTORY_RECORD_BEGIN) {
775 766
         if (central_header) fmap_unneed_ptr(map, central_header, SIZEOF_CENTRAL_HEADER);
776 767
         cli_dbgmsg("cli_unzip: central header - wrkcomplete\n");
... ...
@@ -816,8 +818,9 @@ static unsigned int parse_central_directory_file_header(
816 816
 
817 817
     if (!requests) {
818 818
         if (CENTRAL_HEADER_off < zsize - SIZEOF_LOCAL_HEADER) {
819
-            if (NULL != file_local_offset)
820
-                *file_local_offset = CENTRAL_HEADER_off;
819
+            if (NULL != record) {
820
+                record->local_offset = CENTRAL_HEADER_off;
821
+            }
821 822
             parse_local_file_header(map,
822 823
                                     CENTRAL_HEADER_off,
823 824
                                     zsize - CENTRAL_HEADER_off,
... ...
@@ -829,8 +832,7 @@ static unsigned int parse_central_directory_file_header(
829 829
                                     tmpd,
830 830
                                     1,
831 831
                                     zip_scan_cb,
832
-                                    file_local_header_size,
833
-                                    file_local_data_size);
832
+                                    record);
834 833
         } else {
835 834
             cli_dbgmsg("cli_unzip: central header - local hdr out of file\n");
836 835
         }
... ...
@@ -858,43 +860,212 @@ static unsigned int parse_central_directory_file_header(
858 858
     return (last ? 0 : coff);
859 859
 }
860 860
 
861
+/**
862
+ * @brief Sort zip_record structures based on local file offset.
863
+ *
864
+ * @param first
865
+ * @param second
866
+ * @return int 1 if first record's offset is higher than second's.
867
+ * @return int 0 if first and second reocrd offsets are equal.
868
+ * @return int -1 if first record's offset is less than second's.
869
+ */
870
+static int sort_by_file_offset(const void *first, const void *second)
871
+{
872
+    const struct zip_record *a = (const struct zip_record *)first;
873
+    const struct zip_record *b = (const struct zip_record *)second;
874
+
875
+    /* Avoid return x - y, which can cause undefined behaviour
876
+       because of signed integer overflow. */
877
+    if (a->local_offset < b->local_offset)
878
+        return -1;
879
+    else if (a->local_offset > b->local_offset)
880
+        return 1;
881
+
882
+    return 0;
883
+}
884
+
885
+/**
886
+ * @brief Search the central directory for overlapping files.
887
+ *
888
+ * This function indexes every file in the central directory and sorts them by file entry offset.
889
+ * Then it iterates the sorted file records looking for overlapping files.
890
+ *
891
+ * @param ctx
892
+ * @param map
893
+ * @param fsize
894
+ * @param coff
895
+ * @return cl_error_t  CL_CLEAN if no overlapping files
896
+ * @return cl_error_t  CL_VIRUS if overlapping files and heuristic alerts are enabled
897
+ * @return cl_error_t  CL_EFORMAT if overlapping files and heuristic alerts are disabled
898
+ * @return cl_error_t  CL_ETIMEOUT if the scan time limit is exceeded.
899
+ * @return cl_error_t  CL_EMEM for memory allocation errors.
900
+ */
901
+cl_error_t check_for_overlapping_files(cli_ctx *ctx,
902
+                                       fmap_t *map,
903
+                                       uint32_t fsize,
904
+                                       uint32_t coff)
905
+{
906
+    cl_error_t status = CL_CLEAN;
907
+    cl_error_t ret    = CL_CLEAN;
908
+
909
+    struct zip_record *zip_catalogue = NULL;
910
+    size_t num_record_blocks         = 0;
911
+    size_t index                     = 0;
912
+    size_t records_count             = 0;
913
+
914
+    struct zip_record *curr_record = NULL;
915
+    struct zip_record *prev_record = NULL;
916
+    uint32_t nOverlappingFiles     = 0;
917
+
918
+    zip_catalogue = (struct zip_record *)cli_malloc(sizeof(struct zip_record) * ZIP_RECORDS_CHECK_BLOCKSIZE);
919
+    if (NULL == zip_catalogue) {
920
+        status = CL_EMEM;
921
+        goto done;
922
+    }
923
+    num_record_blocks = 1;
924
+    memset(zip_catalogue, 0, sizeof(struct zip_record) * ZIP_RECORDS_CHECK_BLOCKSIZE);
925
+
926
+    cli_dbgmsg("cli_unzip: checking for non-recursive zip bombs...\n");
927
+
928
+    while (0 != (coff = parse_central_directory_file_header(map,
929
+                                                            coff,
930
+                                                            fsize,
931
+                                                            NULL, // num_files_unziped not required
932
+                                                            index + 1,
933
+                                                            &ret,
934
+                                                            ctx,
935
+                                                            NULL, // tmpd not required
936
+                                                            NULL,
937
+                                                            &zip_catalogue[records_count]))) {
938
+        index++;
939
+
940
+        if (cli_checktimelimit(ctx) != CL_SUCCESS) {
941
+            cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime);
942
+            status = CL_ETIMEOUT;
943
+            goto done;
944
+        }
945
+
946
+        /* stop checking file entries if we'll exceed maxfiles */
947
+        if (ctx->engine->maxfiles && records_count >= ctx->engine->maxfiles) {
948
+            cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
949
+            break;
950
+        }
951
+        records_count++;
952
+
953
+        if (records_count % ZIP_RECORDS_CHECK_BLOCKSIZE == 0) {
954
+            cli_dbgmsg("   cli_unzip: Exceeded zip record block size, allocating more space...\n");
955
+
956
+            /* allocate more space for zip records */
957
+            if (sizeof(struct zip_record) * ZIP_RECORDS_CHECK_BLOCKSIZE * (num_record_blocks + 1) <
958
+                sizeof(struct zip_record) * ZIP_RECORDS_CHECK_BLOCKSIZE * (num_record_blocks)) {
959
+                cli_errmsg("cli_unzip: Number of file records in zip will exceed the max for current architecture (integer overflow)\n");
960
+                status = CL_EFORMAT;
961
+                goto done;
962
+            }
963
+
964
+            zip_catalogue = cli_realloc2(zip_catalogue, sizeof(struct zip_record) * ZIP_RECORDS_CHECK_BLOCKSIZE * (num_record_blocks + 1));
965
+            if (NULL == zip_catalogue) {
966
+                status = CL_EMEM;
967
+                goto done;
968
+            }
969
+            num_record_blocks++;
970
+            /* zero out the memory for the new records */
971
+            memset(&zip_catalogue[records_count], 0, sizeof(struct zip_record) * (ZIP_RECORDS_CHECK_BLOCKSIZE * num_record_blocks - records_count));
972
+        }
973
+    }
974
+
975
+    if (records_count < 2) {
976
+        goto done;
977
+    }
978
+
979
+    /*
980
+     * Sort the records by local file offset
981
+     */
982
+    cli_qsort(zip_catalogue, records_count, sizeof(struct zip_record), sort_by_file_offset);
983
+
984
+    /*
985
+     * Detect overlapping files.
986
+     */
987
+    for (index = 1; index < records_count; index++) {
988
+        prev_record = &zip_catalogue[index - 1];
989
+        curr_record = &zip_catalogue[index];
990
+
991
+        /* Check for integer overflow in 32bit size & offset values */
992
+        if ((UINT32_MAX - (prev_record->local_header_size + prev_record->local_data_size) < prev_record->local_offset) ||
993
+            (UINT32_MAX - (curr_record->local_header_size + curr_record->local_data_size) < curr_record->local_offset)) {
994
+            cli_dbgmsg("cli_unzip: Integer overflow detected; invalid data sizes in zip file headers.\n");
995
+            status = CL_EFORMAT;
996
+            goto done;
997
+        }
998
+
999
+        if (((curr_record->local_offset >= prev_record->local_offset) && (curr_record->local_offset < prev_record->local_offset + prev_record->local_header_size + prev_record->local_data_size)) ||
1000
+            ((prev_record->local_offset >= curr_record->local_offset) && (prev_record->local_offset < curr_record->local_offset + curr_record->local_header_size + curr_record->local_data_size))) {
1001
+            /* Overlapping file detected */
1002
+            nOverlappingFiles++;
1003
+
1004
+            cli_dbgmsg("cli_unzip: Overlapping files detected.\n");
1005
+            cli_dbgmsg("    previous file end:  %u\n", prev_record->local_offset + prev_record->local_header_size + prev_record->local_data_size);
1006
+            cli_dbgmsg("    current file start: %u\n", curr_record->local_offset);
1007
+
1008
+            if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) {
1009
+                if (SCAN_HEURISTICS) {
1010
+                    status = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles");
1011
+                } else {
1012
+                    status = CL_EFORMAT;
1013
+                }
1014
+                break;
1015
+            }
1016
+        }
1017
+
1018
+        if (cli_checktimelimit(ctx) != CL_SUCCESS) {
1019
+            cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime);
1020
+            status = CL_ETIMEOUT;
1021
+            goto done;
1022
+        }
1023
+    }
1024
+
1025
+done:
1026
+
1027
+    if (NULL != zip_catalogue) {
1028
+        free(zip_catalogue);
1029
+    }
1030
+
1031
+    return status;
1032
+}
1033
+
861 1034
 cl_error_t cli_unzip(cli_ctx *ctx)
862 1035
 {
863 1036
     unsigned int file_count = 0, num_files_unzipped = 0;
864 1037
     cl_error_t ret = CL_CLEAN;
865 1038
     uint32_t fsize, lhoff = 0, coff = 0;
866 1039
     fmap_t *map = *ctx->fmap;
867
-    char *tmpd;
1040
+    char *tmpd  = NULL;
868 1041
     const char *ptr;
869 1042
     int virus_found = 0;
870 1043
 #if HAVE_JSON
871 1044
     int toval = 0;
872 1045
 #endif
873
-    int bZipBombDetected                 = 0;
874
-    uint32_t cur_file_local_offset       = 0;
875
-    uint32_t cur_file_local_header_size  = 0;
876
-    uint32_t cur_file_local_data_size    = 0;
877
-    uint32_t prev_file_local_offset      = 0;
878
-    uint32_t prev_file_local_header_size = 0;
879
-    uint32_t prev_file_local_data_size   = 0;
880 1046
 
881 1047
     cli_dbgmsg("in cli_unzip\n");
882 1048
     fsize = (uint32_t)map->len;
883 1049
     if (sizeof(off_t) != sizeof(uint32_t) && (size_t)fsize != map->len) {
884 1050
         cli_dbgmsg("cli_unzip: file too big\n");
885
-        return CL_CLEAN;
1051
+        ret = CL_CLEAN;
1052
+        goto done;
886 1053
     }
887 1054
     if (fsize < SIZEOF_CENTRAL_HEADER) {
888 1055
         cli_dbgmsg("cli_unzip: file too short\n");
889
-        return CL_CLEAN;
1056
+        ret = CL_CLEAN;
1057
+        goto done;
890 1058
     }
891 1059
     if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
892
-        return CL_ETMPDIR;
1060
+        ret = CL_ETMPDIR;
1061
+        goto done;
893 1062
     }
894 1063
     if (mkdir(tmpd, 0700)) {
895 1064
         cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
896
-        free(tmpd);
897
-        return CL_ETMPDIR;
1065
+        ret = CL_ETMPDIR;
1066
+        goto done;
898 1067
     }
899 1068
 
900 1069
     for (coff = fsize - 22; coff > 0; coff--) { /* sizeof(EOC)==22 */
... ...
@@ -909,9 +1080,13 @@ cl_error_t cli_unzip(cli_ctx *ctx)
909 909
     }
910 910
 
911 911
     if (coff) {
912
-        uint32_t nOverlappingFiles = 0;
913
-
914 912
         cli_dbgmsg("cli_unzip: central directory header offset: @%x\n", coff);
913
+
914
+        ret = check_for_overlapping_files(ctx, map, fsize, coff);
915
+        if (CL_SUCCESS != ret) {
916
+            goto done;
917
+        }
918
+
915 919
         while ((coff = parse_central_directory_file_header(map,
916 920
                                                            coff,
917 921
                                                            fsize,
... ...
@@ -921,9 +1096,7 @@ cl_error_t cli_unzip(cli_ctx *ctx)
921 921
                                                            ctx,
922 922
                                                            tmpd,
923 923
                                                            NULL,
924
-                                                           &cur_file_local_offset,
925
-                                                           &cur_file_local_header_size,
926
-                                                           &cur_file_local_data_size))) {
924
+                                                           NULL))) {
927 925
             file_count++;
928 926
             if (ctx->engine->maxfiles && num_files_unzipped >= ctx->engine->maxfiles) {
929 927
                 cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
... ...
@@ -935,50 +1108,27 @@ cl_error_t cli_unzip(cli_ctx *ctx)
935 935
                 ret = CL_ETIMEOUT;
936 936
             }
937 937
 
938
-            /*
939
-             * Detect overlapping files and zip bombs.
940
-             */
941
-            if ((((cur_file_local_offset > prev_file_local_offset) && (cur_file_local_offset < prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size)) ||
942
-                 ((prev_file_local_offset > cur_file_local_offset) && (prev_file_local_offset < cur_file_local_offset + cur_file_local_header_size + cur_file_local_data_size))) &&
943
-                (cur_file_local_header_size + cur_file_local_data_size > 0)) {
944
-                /* Overlapping file detected */
945
-                nOverlappingFiles++;
946
-
947
-                cli_dbgmsg("cli_unzip: Overlapping files detected.\n");
948
-                cli_dbgmsg("    previous file end:  %u\n", prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size);
949
-                cli_dbgmsg("    current file start: %u\n", cur_file_local_offset);
950
-
951
-                if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) {
952
-                    if (SCAN_HEURISTICS) {
953
-                        ret         = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles");
954
-                        virus_found = 1;
955
-                    } else {
956
-                        ret = CL_EFORMAT;
957
-                    }
958
-                    bZipBombDetected = 1;
959
-                }
960
-            }
961
-            prev_file_local_offset      = cur_file_local_offset;
962
-            prev_file_local_header_size = cur_file_local_header_size;
963
-            prev_file_local_data_size   = cur_file_local_data_size;
964
-
965 938
 #if HAVE_JSON
966 939
             if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
967 940
                 ret = CL_ETIMEOUT;
968 941
             }
969 942
 #endif
970 943
             if (ret != CL_CLEAN) {
971
-                if (ret == CL_VIRUS && SCAN_ALLMATCHES && !bZipBombDetected) {
944
+                if (ret == CL_VIRUS && SCAN_ALLMATCHES) {
972 945
                     ret         = CL_CLEAN;
973 946
                     virus_found = 1;
974
-                } else
947
+                } else {
975 948
                     break;
949
+                }
976 950
             }
977 951
         }
978
-    } else
952
+    } else {
979 953
         cli_dbgmsg("cli_unzip: central not found, using localhdrs\n");
980
-    if (virus_found == 1)
954
+    }
955
+
956
+    if (virus_found == 1) {
981 957
         ret = CL_VIRUS;
958
+    }
982 959
     if (num_files_unzipped <= (file_count / 4)) { /* FIXME: make up a sane ratio or remove the whole logic */
983 960
         file_count = 0;
984 961
         while ((ret == CL_CLEAN) &&
... ...
@@ -994,7 +1144,6 @@ cl_error_t cli_unzip(cli_ctx *ctx)
994 994
                                                      tmpd,
995 995
                                                      1,
996 996
                                                      zip_scan_cb,
997
-                                                     NULL,
998 997
                                                      NULL)))) {
999 998
             file_count++;
1000 999
             lhoff += coff;
... ...
@@ -1014,8 +1163,13 @@ cl_error_t cli_unzip(cli_ctx *ctx)
1014 1014
         }
1015 1015
     }
1016 1016
 
1017
-    if (!ctx->engine->keeptmp) cli_rmdirs(tmpd);
1018
-    free(tmpd);
1017
+done:
1018
+    if (NULL != tmpd) {
1019
+        if (!ctx->engine->keeptmp) {
1020
+            cli_rmdirs(tmpd);
1021
+        }
1022
+        free(tmpd);
1023
+    }
1019 1024
 
1020 1025
     if (ret == CL_CLEAN && virus_found)
1021 1026
         ret = CL_VIRUS;
... ...
@@ -1056,7 +1210,6 @@ cl_error_t unzip_single_internal(cli_ctx *ctx, off_t local_header_offset, zip_cb
1056 1056
                             NULL,
1057 1057
                             0,
1058 1058
                             zcb,
1059
-                            NULL,
1060 1059
                             NULL);
1061 1060
 
1062 1061
     return ret;
... ...
@@ -1137,8 +1290,6 @@ cl_error_t unzip_search(cli_ctx *ctx, fmap_t *map, struct zip_requests *requests
1137 1137
                                                                               ctx,
1138 1138
                                                                               NULL,
1139 1139
                                                                               requests,
1140
-                                                                              NULL,
1141
-                                                                              NULL,
1142 1140
                                                                               NULL))) {
1143 1141
             if (requests->match) {
1144 1142
                 ret = CL_VIRUS;