summaryrefslogtreecommitdiff
path: root/unzip/cumulative.patch
blob: 6b42955e10174b325563f54fb2669b344c51ff00 (plain)
    1 diff -up unzip60/crc_i386.S.exec-shield unzip60/crc_i386.S
    2 --- unzip60/crc_i386.S.exec-shield	2007-01-07 06:02:58.000000000 +0100
    3 +++ unzip60/crc_i386.S	2009-11-18 11:16:39.630389312 +0100
    4 @@ -302,3 +302,6 @@ _crc32:                         /* ulg c
    5  #endif /* i386 || _i386 || _I386 || __i386 */
    6  
    7  #endif /* !USE_ZLIB && !CRC_TABLE_ONLY */
    8 +
    9 +.section .note.GNU-stack, "", @progbits
   10 +.previous
   11 diff -up unzip60/extract.c.close unzip60/extract.c
   12 --- unzip60/extract.c.close	2009-03-14 02:32:52.000000000 +0100
   13 +++ unzip60/extract.c	2009-11-19 08:17:23.481263496 +0100
   14 @@ -1924,24 +1924,21 @@ static int extract_or_test_member(__G)  
   15  
   16  #ifdef VMS                  /* VMS:  required even for stdout! (final flush) */
   17      if (!uO.tflag)           /* don't close NULL file */
   18 -        close_outfile(__G);
   19 +        error = close_outfile(__G);
   20  #else
   21  #ifdef DLL
   22      if (!uO.tflag && (!uO.cflag || G.redirect_data)) {
   23          if (G.redirect_data)
   24              FINISH_REDIRECT();
   25          else
   26 -            close_outfile(__G);
   27 +            error = close_outfile(__G);
   28      }
   29  #else
   30      if (!uO.tflag && !uO.cflag)   /* don't close NULL file or stdout */
   31 -        close_outfile(__G);
   32 +        error = close_outfile(__G);
   33  #endif
   34  #endif /* VMS */
   35  
   36 -            /* GRR: CONVERT close_outfile() TO NON-VOID:  CHECK FOR ERRORS! */
   37 -
   38 -
   39      if (G.disk_full) {            /* set by flush() */
   40          if (G.disk_full > 1) {
   41  #if (defined(DELETE_IF_FULL) && defined(HAVE_UNLINK))
   42 diff -up unzip60/unix/unix.c.close unzip60/unix/unix.c
   43 --- unzip60/unix/unix.c.close	2009-01-24 00:31:26.000000000 +0100
   44 +++ unzip60/unix/unix.c	2009-11-19 08:33:25.568389171 +0100
   45 @@ -1096,10 +1096,41 @@ static int get_extattribs(__G__ pzt, z_u
   46  #ifndef MTS
   47  
   48  /****************************/
   49 +/* Function CloseError()    */
   50 +/***************************/
   51 +
   52 +int CloseError(__G)
   53 +    __GDEF
   54 +{
   55 +    int errval = PK_OK;
   56 +    
   57 +    if (fclose(G.outfile) < 0) {
   58 +          switch (errno) {
   59 +                case ENOSPC:
   60 +                    /* Do we need this on fileio.c? */
   61 +                    Info(slide, 0x4a1, ((char *)slide, "%s: write error (disk full?).   Continue? (y/n/^C) ",
   62 +                          FnFilter1(G.filename)));
   63 +                    fgets(G.answerbuf, 9, stdin);
   64 +                    if (*G.answerbuf == 'y')     /* stop writing to this file */
   65 +                        G.disk_full = 1;         /* pass to next */
   66 +                    else
   67 +                        G.disk_full = 2;         /* no: exit program */
   68 +          
   69 +                    errval = PK_DISK;
   70 +                    break;
   71 +
   72 +                default:
   73 +                    errval = PK_WARN;
   74 +          }
   75 +     }
   76 +     return errval;
   77 +} /* End of CloseError() */
   78 +
   79 +/****************************/
   80  /* Function close_outfile() */
   81  /****************************/
   82  
   83 -void close_outfile(__G)    /* GRR: change to return PK-style warning level */
   84 +int close_outfile(__G) 
   85      __GDEF
   86  {
   87      union {
   88 @@ -1108,6 +1139,7 @@ void close_outfile(__G)    /* GRR: chang
   89      } zt;
   90      ulg z_uidgid[2];
   91      int have_uidgid_flg;
   92 +    int errval = PK_OK;
   93  
   94      have_uidgid_flg = get_extattribs(__G__ &(zt.t3), z_uidgid);
   95  
   96 @@ -1141,16 +1173,16 @@ void close_outfile(__G)    /* GRR: chang
   97              Info(slide, 0x201, ((char *)slide,
   98                "warning:  symbolic link (%s) failed: mem alloc overflow\n",
   99                FnFilter1(G.filename)));
  100 -            fclose(G.outfile);
  101 -            return;
  102 +            errval = CloseError(G.outfile, G.filename);
  103 +            return errval ? errval : PK_WARN;
  104          }
  105  
  106          if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) {
  107              Info(slide, 0x201, ((char *)slide,
  108                "warning:  symbolic link (%s) failed: no mem\n",
  109                FnFilter1(G.filename)));
  110 -            fclose(G.outfile);
  111 -            return;
  112 +            errval = CloseError(G.outfile, G.filename);
  113 +            return errval ? errval : PK_WARN;
  114          }
  115          slnk_entry->next = NULL;
  116          slnk_entry->targetlen = ucsize;
  117 @@ -1174,10 +1206,10 @@ void close_outfile(__G)    /* GRR: chang
  118                "warning:  symbolic link (%s) failed\n",
  119                FnFilter1(G.filename)));
  120              free(slnk_entry);
  121 -            fclose(G.outfile);
  122 -            return;
  123 +            errval = CloseError(G.outfile, G.filename);
  124 +            return errval ? errval : PK_WARN;
  125          }
  126 -        fclose(G.outfile);                  /* close "link" file for good... */
  127 +        errval = CloseError(G.outfile, G.filename); /* close "link" file for good... */
  128          slnk_entry->target[ucsize] = '\0';
  129          if (QCOND2)
  130              Info(slide, 0, ((char *)slide, "-> %s ",
  131 @@ -1188,7 +1220,7 @@ void close_outfile(__G)    /* GRR: chang
  132          else
  133              G.slink_head = slnk_entry;
  134          G.slink_last = slnk_entry;
  135 -        return;
  136 +        return errval;
  137      }
  138  #endif /* SYMLINKS */
  139  
  140 @@ -1201,7 +1233,7 @@ void close_outfile(__G)    /* GRR: chang
  141  #endif
  142  
  143  #if (defined(NO_FCHOWN))
  144 -    fclose(G.outfile);
  145 +    errval = CloseError(G.outfile, G.filename);
  146  #endif
  147  
  148      /* if -X option was specified and we have UID/GID info, restore it */
  149 @@ -1227,7 +1259,7 @@ void close_outfile(__G)    /* GRR: chang
  150      }
  151  
  152  #if (!defined(NO_FCHOWN) && defined(NO_FCHMOD))
  153 -    fclose(G.outfile);
  154 +    errval = CloseError(G.outfile, G.filename);
  155  #endif
  156  
  157  #if (!defined(NO_FCHOWN) && !defined(NO_FCHMOD))
  158 @@ -1239,7 +1271,7 @@ void close_outfile(__G)    /* GRR: chang
  159      if (fchmod(fileno(G.outfile), filtattr(__G__ G.pInfo->file_attr)))
  160          perror("fchmod (file attributes) error");
  161  
  162 -    fclose(G.outfile);
  163 +    errval = CloseError(G.outfile, G.filename);
  164  #endif /* !NO_FCHOWN && !NO_FCHMOD */
  165  
  166      /* skip restoring time stamps on user's request */
  167 @@ -1267,6 +1299,7 @@ void close_outfile(__G)    /* GRR: chang
  168  #endif
  169  #endif /* NO_FCHOWN || NO_FCHMOD */
  170  
  171 +    return errval;
  172  } /* end function close_outfile() */
  173  
  174  #endif /* !MTS */
  175 diff -up unzip60/unzpriv.h.close unzip60/unzpriv.h
  176 --- unzip60/unzpriv.h.close	2009-04-20 01:59:26.000000000 +0200
  177 +++ unzip60/unzpriv.h	2009-11-19 08:19:08.610388618 +0100
  178 @@ -2604,7 +2604,7 @@ char    *GetLoadPath     OF((__GPRO));  
  179     int   SetFileSize     OF((FILE *file, zusz_t filesize));         /* local */
  180  #endif
  181  #ifndef MTS /* macro in MTS */
  182 -   void  close_outfile   OF((__GPRO));                              /* local */
  183 +   int  close_outfile   OF((__GPRO));                              /* local */
  184  #endif
  185  #ifdef SET_SYMLINK_ATTRIBS
  186     int  set_symlnk_attribs  OF((__GPRO__ slinkentry *slnk_entry));  /* local */
  187 diff -up unzip60/zipinfo.c.attribs-overflow unzip60/zipinfo.c
  188 --- unzip60/zipinfo.c.attribs-overflow	2009-11-30 09:55:39.000000000 +0100
  189 +++ unzip60/zipinfo.c	2009-11-30 09:56:42.844263244 +0100
  190 @@ -1881,7 +1881,7 @@ static int zi_short(__G)   /* return PK-
  191  #endif
  192      int         k, error, error_in_archive=PK_COOL;
  193      unsigned    hostnum, hostver, methid, methnum, xattr;
  194 -    char        *p, workspace[12], attribs[16];
  195 +    char        *p, workspace[12], attribs[17];
  196      char        methbuf[5];
  197      static ZCONST char dtype[5]="NXFS"; /* normal, maximum, fast, superfast */
  198      static ZCONST char Far os[NUM_HOSTS+1][4] = {
  199 diff --git a/process.c b/process.c
  200 index 1e9a1e1..905732b 100644
  201 --- a/process.c
  202 +++ b/process.c
  203 @@ -1751,6 +1751,12 @@ int process_cdir_file_hdr(__G)    /* return PK-type error code */
  204          = (G.crec.general_purpose_bit_flag & (1 << 11)) == (1 << 11);
  205  #endif
  206  
  207 +#ifdef SYMLINKS
  208 +    /* Initialize the symlink flag, may be set by the platform-specific
  209 +       mapattr function.  */
  210 +    G.pInfo->symlink = 0;
  211 +#endif
  212 +
  213      return PK_COOL;
  214  
  215  } /* end function process_cdir_file_hdr() */
  216 diff --git a/extract.c b/extract.c
  217 index eeb2f57..a0a4929 100644
  218 --- a/extract.c
  219 +++ b/extract.c
  220 @@ -472,8 +472,8 @@ int extract_or_test_files(__G)    /* return PK-type error code */
  221                       */
  222                      Info(slide, 0x401, ((char *)slide,
  223                        LoadFarString(CentSigMsg), j + blknum*DIR_BLKSIZ + 1));
  224 -                    Info(slide, 0x401, ((char *)slide,
  225 -                      LoadFarString(ReportMsg)));
  226 +                    Info(slide, 0x401,
  227 +                         ((char *)slide,"%s", LoadFarString(ReportMsg)));
  228                      error_in_archive = PK_BADERR;
  229                  }
  230                  reached_end = TRUE;     /* ...so no more left to do */
  231 @@ -752,8 +752,8 @@ int extract_or_test_files(__G)    /* return PK-type error code */
  232  
  233  #ifndef SFX
  234      if (no_endsig_found) {                      /* just to make sure */
  235 -        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  236 -        Info(slide, 0x401, ((char *)slide, LoadFarString(ReportMsg)));
  237 +        Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
  238 +        Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(ReportMsg)));
  239          if (!error_in_archive)       /* don't overwrite stronger error */
  240              error_in_archive = PK_WARN;
  241      }
  242 diff --git a/list.c b/list.c
  243 index 15e0011..f7359c3 100644
  244 --- a/list.c
  245 +++ b/list.c
  246 @@ -181,7 +181,7 @@ int list_files(__G)    /* return PK-type error code */
  247                  Info(slide, 0x401,
  248                       ((char *)slide, LoadFarString(CentSigMsg), j));
  249                  Info(slide, 0x401,
  250 -                     ((char *)slide, LoadFarString(ReportMsg)));
  251 +                     ((char *)slide,"%s", LoadFarString(ReportMsg)));
  252                  return PK_BADERR;   /* sig not found */
  253              }
  254          }
  255 @@ -507,7 +507,8 @@ int list_files(__G)    /* return PK-type error code */
  256              && (!G.ecrec.is_zip64_archive)
  257              && (memcmp(G.sig, end_central_sig, 4) != 0)
  258             ) {          /* just to make sure again */
  259 -            Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  260 +            Info(slide, 0x401, 
  261 +                 ((char *)slide,"%s", LoadFarString(EndSigMsg)));
  262              error_in_archive = PK_WARN;   /* didn't find sig */
  263          }
  264  
  265 @@ -591,7 +592,7 @@ int get_time_stamp(__G__ last_modtime, nmember)  /* return PK-type error code */
  266                  Info(slide, 0x401,
  267                       ((char *)slide, LoadFarString(CentSigMsg), j));
  268                  Info(slide, 0x401,
  269 -                     ((char *)slide, LoadFarString(ReportMsg)));
  270 +                     ((char *)slide,"%s", LoadFarString(ReportMsg)));
  271                  return PK_BADERR;   /* sig not found */
  272              }
  273          }
  274 @@ -674,7 +675,7 @@ int get_time_stamp(__G__ last_modtime, nmember)  /* return PK-type error code */
  275    ---------------------------------------------------------------------------*/
  276  
  277      if (memcmp(G.sig, end_central_sig, 4)) {    /* just to make sure again */
  278 -        Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  279 +        Info(slide, 0x401, ((char *)slide,"%s", LoadFarString(EndSigMsg)));
  280          error_in_archive = PK_WARN;
  281      }
  282      if (*nmember == 0L && error_in_archive <= PK_WARN)
  283 diff --git a/zipinfo.c b/zipinfo.c
  284 index 6e22cc8..ac5c61b 100644
  285 --- a/zipinfo.c
  286 +++ b/zipinfo.c
  287 @@ -771,7 +771,7 @@ int zipinfo(__G)   /* return PK-type error code */
  288                  Info(slide, 0x401,
  289                       ((char *)slide, LoadFarString(CentSigMsg), j));
  290                  Info(slide, 0x401,
  291 -                     ((char *)slide, LoadFarString(ReportMsg)));
  292 +                     ((char *)slide,"%s", LoadFarString(ReportMsg)));
  293                  error_in_archive = PK_BADERR;   /* sig not found */
  294                  break;
  295              }
  296 @@ -960,7 +960,8 @@ int zipinfo(__G)   /* return PK-type error code */
  297              && (!G.ecrec.is_zip64_archive)
  298              && (memcmp(G.sig, end_central_sig, 4) != 0)
  299             ) {          /* just to make sure again */
  300 -            Info(slide, 0x401, ((char *)slide, LoadFarString(EndSigMsg)));
  301 +            Info(slide, 0x401, 
  302 +                 ((char *)slide,"%s", LoadFarString(EndSigMsg)));
  303              error_in_archive = PK_WARN;   /* didn't find sig */
  304          }
  305  
  306 diff --git a/fileio.c b/fileio.c
  307 index ba0a1d0..03fc4be 100644
  308 --- a/fileio.c
  309 +++ b/fileio.c
  310 @@ -2006,6 +2006,7 @@ int do_string(__G__ length, option)   /* return PK-type error code */
  311      unsigned comment_bytes_left;
  312      unsigned int block_len;
  313      int error=PK_OK;
  314 +    unsigned int length2;
  315  #ifdef AMIGA
  316      char tmp_fnote[2 * AMIGA_FILENOTELEN];   /* extra room for squozen chars */
  317  #endif
  318 @@ -2292,8 +2293,12 @@ int do_string(__G__ length, option)   /* return PK-type error code */
  319              seek_zipf(__G__ G.cur_zipfile_bufstart - G.extra_bytes +
  320                        (G.inptr-G.inbuf) + length);
  321          } else {
  322 -            if (readbuf(__G__ (char *)G.extra_field, length) == 0)
  323 +            if ((length2 = readbuf(__G__ (char *)G.extra_field, length)) == 0)
  324                  return PK_EOF;
  325 +            if(length2 < length) {
  326 +              memset (__G__ (char *)G.extra_field+length2, 0 , length-length2);
  327 +              length = length2;
  328 +            }
  329              /* Looks like here is where extra fields are read */
  330              getZip64Data(__G__ G.extra_field, length);
  331  #ifdef UNICODE_SUPPORT
  332 --- ./process.c.orig    2009-03-06 02:25:10.000000000 +0100
  333 +++ ./process.c 2013-09-12 10:51:16.000000000 +0200
  334 @@ -2901,9 +2901,9 @@
  335          */
  336  
  337  #ifdef IZ_HAVE_UXUIDGID
  338 -            if (eb_len >= EB_UX3_MINLEN
  339 -                && z_uidgid != NULL
  340 -                && (*((EB_HEADSIZE + 0) + ef_buf) == 1)
  341 +            if ((eb_len >= EB_UX3_MINLEN)
  342 +                && (z_uidgid != NULL)
  343 +                && ((*((EB_HEADSIZE + 0) + ef_buf) == 1)))
  344                      /* only know about version 1 */
  345              {
  346                  uch uid_size;
  347 @@ -2915,10 +2915,10 @@
  348                  flags &= ~0x0ff;      /* ignore any previous UNIX field */
  349  
  350                  if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,
  351 -                                    uid_size, z_uidgid[0])
  352 +                                    uid_size, &z_uidgid[0])
  353                      &&
  354                       read_ux3_value((EB_HEADSIZE + uid_size + 3) + ef_buf,
  355 -                                    gid_size, z_uidgid[1]) )
  356 +                                    gid_size, &z_uidgid[1]) )
  357                  {
  358                      flags |= EB_UX2_VALID;   /* signal success */
  359                  }
  360 diff --git a/extract.c b/extract.c
  361 index a0a4929..9ef80b3 100644
  362 --- a/extract.c
  363 +++ b/extract.c
  364 @@ -2214,6 +2214,7 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  365      ulg eb_ucsize;
  366      uch *eb_ucptr;
  367      int r;
  368 +    ush method;
  369  
  370      if (compr_offset < 4)                /* field is not compressed: */
  371          return PK_OK;                    /* do nothing and signal OK */
  372 @@ -2223,6 +2224,12 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  373           eb_size <= (compr_offset + EB_CMPRHEADLEN)))
  374          return IZ_EF_TRUNC;               /* no compressed data! */
  375  
  376 +    method = makeword(eb + (EB_HEADSIZE + compr_offset));
  377 +    if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
  378 +        return PK_ERR;            /* compressed & uncompressed
  379 +                                   * should match in STORED
  380 +                                   * method */
  381 +
  382      if (
  383  #ifdef INT_16BIT
  384          (((ulg)(extent)eb_ucsize) != eb_ucsize) ||
  385 diff --git a/extract.c b/extract.c
  386 index 9ef80b3..c741b5f 100644
  387 --- a/extract.c
  388 +++ b/extract.c
  389 @@ -1,5 +1,5 @@
  390  /*
  391 -  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
  392 +  Copyright (c) 1990-2014 Info-ZIP.  All rights reserved.
  393  
  394    See the accompanying file LICENSE, version 2009-Jan-02 or later
  395    (the contents of which are also included in unzip.h) for terms of use.
  396 @@ -298,6 +298,8 @@ char ZCONST Far TruncNTSD[] =
  397  #ifndef SFX
  398     static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
  399       EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
  400 +   static ZCONST char Far TooSmallEBlength[] = "bad extra-field entry:\n \
  401 +     EF block length (%u bytes) invalid (< %d)\n";
  402     static ZCONST char Far InvalidComprDataEAs[] =
  403       " invalid compressed data for EAs\n";
  404  #  if (defined(WIN32) && defined(NTSD_EAS))
  405 @@ -2020,7 +2022,8 @@ static int TestExtraField(__G__ ef, ef_len)
  406          ebID = makeword(ef);
  407          ebLen = (unsigned)makeword(ef+EB_LEN);
  408  
  409 -        if (ebLen > (ef_len - EB_HEADSIZE)) {
  410 +        if (ebLen > (ef_len - EB_HEADSIZE))
  411 +        {
  412             /* Discovered some extra field inconsistency! */
  413              if (uO.qflag)
  414                  Info(slide, 1, ((char *)slide, "%-22s ",
  415 @@ -2155,11 +2158,29 @@ static int TestExtraField(__G__ ef, ef_len)
  416                  }
  417                  break;
  418              case EF_PKVMS:
  419 -                if (makelong(ef+EB_HEADSIZE) !=
  420 -                    crc32(CRCVAL_INITIAL, ef+(EB_HEADSIZE+4),
  421 -                          (extent)(ebLen-4)))
  422 -                    Info(slide, 1, ((char *)slide,
  423 -                      LoadFarString(BadCRC_EAs)));
  424 +                /* 2015-01-30 SMS.  Added sufficient-bytes test/message
  425 +                 * here.  (Removed defective ebLen test above.)
  426 +                 *
  427 +                 * If sufficient bytes (EB_PKVMS_MINLEN) are available,
  428 +                 * then compare the stored CRC value with the calculated
  429 +                 * CRC for the remainder of the data (and complain about
  430 +                 * a mismatch).
  431 +                 */
  432 +                if (ebLen < EB_PKVMS_MINLEN)
  433 +                {
  434 +                    /* Insufficient bytes available. */
  435 +                    Info( slide, 1,
  436 +                     ((char *)slide, LoadFarString( TooSmallEBlength),
  437 +                     ebLen, EB_PKVMS_MINLEN));
  438 +                }
  439 +                else if (makelong(ef+ EB_HEADSIZE) !=
  440 +                 crc32(CRCVAL_INITIAL,
  441 +                 (ef+ EB_HEADSIZE+ EB_PKVMS_MINLEN),
  442 +                 (extent)(ebLen- EB_PKVMS_MINLEN)))
  443 +                {
  444 +                     Info(slide, 1, ((char *)slide,
  445 +                       LoadFarString(BadCRC_EAs)));
  446 +                }
  447                  break;
  448              case EF_PKW32:
  449              case EF_PKUNIX:
  450 diff --git a/unzpriv.h b/unzpriv.h
  451 index 005cee0..5c83a6e 100644
  452 --- a/unzpriv.h
  453 +++ b/unzpriv.h
  454 @@ -1806,6 +1806,8 @@
  455  #define EB_NTSD_VERSION   4    /* offset of NTSD version byte */
  456  #define EB_NTSD_MAX_VER   (0)  /* maximum version # we know how to handle */
  457  
  458 +#define EB_PKVMS_MINLEN   4    /* minimum data length of PKVMS extra block */
  459 +
  460  #define EB_ASI_CRC32      0    /* offset of ASI Unix field's crc32 checksum */
  461  #define EB_ASI_MODE       4    /* offset of ASI Unix permission mode field */
  462  
  463 
  464 diff --git a/extract.c b/extract.c
  465 index c741b5f..e4a4c7b 100644
  466 --- a/extract.c
  467 +++ b/extract.c
  468 @@ -2240,10 +2240,17 @@ static int test_compr_eb(__G__ eb, eb_size, compr_offset, test_uc_ebdata)
  469      if (compr_offset < 4)                /* field is not compressed: */
  470          return PK_OK;                    /* do nothing and signal OK */
  471  
  472 +    /* Return no/bad-data error status if any problem is found:
  473 +     *    1. eb_size is too small to hold the uncompressed size
  474 +     *       (eb_ucsize).  (Else extract eb_ucsize.)
  475 +     *    2. eb_ucsize is zero (invalid).  2014-12-04 SMS.
  476 +     *    3. eb_ucsize is positive, but eb_size is too small to hold
  477 +     *       the compressed data header.
  478 +     */
  479      if ((eb_size < (EB_UCSIZE_P + 4)) ||
  480 -        ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
  481 -         eb_size <= (compr_offset + EB_CMPRHEADLEN)))
  482 -        return IZ_EF_TRUNC;               /* no compressed data! */
  483 +     ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
  484 +     ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
  485 +        return IZ_EF_TRUNC;             /* no/bad compressed data! */
  486  
  487      method = makeword(eb + (EB_HEADSIZE + compr_offset));
  488      if ((method == STORED) && (eb_size != compr_offset + EB_CMPRHEADLEN + eb_ucsize))
  489 diff --git a/fileio.c b/fileio.c
  490 index 03fc4be..2a61a30 100644
  491 --- a/fileio.c
  492 +++ b/fileio.c
  493 @@ -176,6 +176,8 @@ static ZCONST char Far FilenameTooLongTrunc[] =
  494  #endif
  495  static ZCONST char Far ExtraFieldTooLong[] =
  496    "warning:  extra field too long (%d).  Ignoring...\n";
  497 +static ZCONST char Far ExtraFieldCorrupt[] =
  498 +  "warning:  extra field (type: 0x%04x) corrupt.  Continuing...\n";
  499  
  500  #ifdef WINDLL
  501     static ZCONST char Far DiskFullQuery[] =
  502 @@ -2300,7 +2302,13 @@ int do_string(__G__ length, option)   /* return PK-type error code */
  503                length = length2;
  504              }
  505              /* Looks like here is where extra fields are read */
  506 -            getZip64Data(__G__ G.extra_field, length);
  507 +            if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
  508 +            {
  509 +                Info(slide, 0x401, ((char *)slide,
  510 +                 LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
  511 +                error = PK_WARN;
  512 +            }
  513 +
  514  #ifdef UNICODE_SUPPORT
  515              G.unipath_filename = NULL;
  516              if (G.UzO.U_flag < 2) {
  517 diff --git a/process.c b/process.c
  518 index be6e006..0d57ab4 100644
  519 --- a/process.c
  520 +++ b/process.c
  521 @@ -1,5 +1,5 @@
  522  /*
  523 -  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
  524 +  Copyright (c) 1990-2014 Info-ZIP.  All rights reserved.
  525  
  526    See the accompanying file LICENSE, version 2009-Jan-02 or later
  527    (the contents of which are also included in unzip.h) for terms of use.
  528 @@ -1894,48 +1894,83 @@ int getZip64Data(__G__ ef_buf, ef_len)
  529      and a 4-byte version of disk start number.
  530      Sets both local header and central header fields.  Not terribly clever,
  531      but it means that this procedure is only called in one place.
  532 +
  533 +    2014-12-05 SMS.
  534 +    Added checks to ensure that enough data are available before calling
  535 +    makeint64() or makelong().  Replaced various sizeof() values with
  536 +    simple ("4" or "8") constants.  (The Zip64 structures do not depend
  537 +    on our variable sizes.)  Error handling is crude, but we should now
  538 +    stay within the buffer.
  539    ---------------------------------------------------------------------------*/
  540  
  541 +#define Z64FLGS 0xffff
  542 +#define Z64FLGL 0xffffffff
  543 +
  544      if (ef_len == 0 || ef_buf == NULL)
  545          return PK_COOL;
  546  
  547      Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
  548        ef_len));
  549  
  550 -    while (ef_len >= EB_HEADSIZE) {
  551 +    while (ef_len >= EB_HEADSIZE)
  552 +    {
  553          eb_id = makeword(EB_ID + ef_buf);
  554          eb_len = makeword(EB_LEN + ef_buf);
  555  
  556 -        if (eb_len > (ef_len - EB_HEADSIZE)) {
  557 -            /* discovered some extra field inconsistency! */
  558 +        if (eb_len > (ef_len - EB_HEADSIZE))
  559 +        {
  560 +            /* Extra block length exceeds remaining extra field length. */
  561              Trace((stderr,
  562                "getZip64Data: block length %u > rest ef_size %u\n", eb_len,
  563                ef_len - EB_HEADSIZE));
  564              break;
  565          }
  566 -        if (eb_id == EF_PKSZ64) {
  567  
  568 +        if (eb_id == EF_PKSZ64)
  569 +        {
  570            int offset = EB_HEADSIZE;
  571  
  572 -          if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
  573 -            G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
  574 -            offset += sizeof(G.crec.ucsize);
  575 +          if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
  576 +          {
  577 +            if (offset+ 8 > ef_len)
  578 +              return PK_ERR;
  579 +
  580 +            G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
  581 +            offset += 8;
  582            }
  583 -          if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
  584 -            G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
  585 -            offset += sizeof(G.crec.csize);
  586 +
  587 +          if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
  588 +          {
  589 +            if (offset+ 8 > ef_len)
  590 +              return PK_ERR;
  591 +
  592 +            G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
  593 +            offset += 8;
  594            }
  595 -          if (G.crec.relative_offset_local_header == 0xffffffff){
  596 +
  597 +          if (G.crec.relative_offset_local_header == Z64FLGL)
  598 +          {
  599 +            if (offset+ 8 > ef_len)
  600 +              return PK_ERR;
  601 +
  602              G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
  603 -            offset += sizeof(G.crec.relative_offset_local_header);
  604 +            offset += 8;
  605            }
  606 -          if (G.crec.disk_number_start == 0xffff){
  607 +
  608 +          if (G.crec.disk_number_start == Z64FLGS)
  609 +          {
  610 +            if (offset+ 4 > ef_len)
  611 +              return PK_ERR;
  612 +
  613              G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
  614 -            offset += sizeof(G.crec.disk_number_start);
  615 +            offset += 4;
  616            }
  617 +#if 0
  618 +          break;                /* Expect only one EF_PKSZ64 block. */
  619 +#endif /* 0 */
  620          }
  621  
  622 -        /* Skip this extra field block */
  623 +        /* Skip this extra field block. */
  624          ef_buf += (eb_len + EB_HEADSIZE);
  625          ef_len -= (eb_len + EB_HEADSIZE);
  626      }
  627 diff --git a/list.c b/list.c
  628 index f7359c3..4c3d703 100644
  629 --- a/list.c
  630 +++ b/list.c
  631 @@ -97,7 +97,7 @@ int list_files(__G)    /* return PK-type error code */
  632  {
  633      int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
  634  #ifndef WINDLL
  635 -    char sgn, cfactorstr[10];
  636 +    char sgn, cfactorstr[13];
  637      int longhdr=(uO.vflag>1);
  638  #endif
  639      int date_format;
  640 @@ -339,7 +339,19 @@ int list_files(__G)    /* return PK-type error code */
  641                  G.crec.compression_method == ENHDEFLATED) {
  642                  methbuf[5] = dtype[(G.crec.general_purpose_bit_flag>>1) & 3];
  643              } else if (methnum >= NUM_METHODS) {
  644 -                sprintf(&methbuf[4], "%03u", G.crec.compression_method);
  645 +                /* 2013-02-26 SMS.
  646 +                 * http://sourceforge.net/tracker/?func=detail
  647 +                 *  &aid=2861648&group_id=118012&atid=679786
  648 +                 * Unexpectedly large compression methods overflow
  649 +                 * &methbuf[].  Use the old, three-digit decimal format
  650 +                 * for values which fit.  Otherwise, sacrifice the
  651 +                 * colon, and use four-digit hexadecimal.
  652 +                 */
  653 +                if (G.crec.compression_method <= 999) {
  654 +                    sprintf( &methbuf[ 4], "%03u", G.crec.compression_method);
  655 +                } else {
  656 +                    sprintf( &methbuf[ 3], "%04X", G.crec.compression_method);
  657 +                }
  658              }
  659  
  660  #if 0       /* GRR/Euro:  add this? */
  661 From bdd4a0cecd745cb4825e4508b5bdf2579731086a Mon Sep 17 00:00:00 2001
  662 From: Petr Stodulka <pstodulk@redhat.com>
  663 Date: Mon, 14 Sep 2015 18:23:17 +0200
  664 Subject: [PATCH 1/3] upstream fix for heap overflow
  665 
  666 https://bugzilla.redhat.com/attachment.cgi?id=1073002
  667 ---
  668  crypt.c | 12 +++++++++++-
  669  1 file changed, 11 insertions(+), 1 deletion(-)
  670 
  671 diff --git a/crypt.c b/crypt.c
  672 index 784e411..a8975f2 100644
  673 --- a/crypt.c
  674 +++ b/crypt.c
  675 @@ -465,7 +465,17 @@ int decrypt(__G__ passwrd)
  676      GLOBAL(pInfo->encrypted) = FALSE;
  677      defer_leftover_input(__G);
  678      for (n = 0; n < RAND_HEAD_LEN; n++) {
  679 -        b = NEXTBYTE;
  680 +        /* 2012-11-23 SMS.  (OUSPG report.)
  681 +         * Quit early if compressed size < HEAD_LEN.  The resulting
  682 +         * error message ("unable to get password") could be improved,
  683 +         * but it's better than trying to read nonexistent data, and
  684 +         * then continuing with a negative G.csize.  (See
  685 +         * fileio.c:readbyte()).
  686 +         */
  687 +        if ((b = NEXTBYTE) == (ush)EOF)
  688 +        {
  689 +            return PK_ERR;
  690 +        }
  691          h[n] = (uch)b;
  692          Trace((stdout, " (%02x)", h[n]));
  693      }
  694 -- 
  695 2.4.6
  696 
  697 
  698 From 4b48844661ff9569f2ecf582a387d46a5775b5d8 Mon Sep 17 00:00:00 2001
  699 From: Kamil Dudka <kdudka@redhat.com>
  700 Date: Mon, 14 Sep 2015 18:24:56 +0200
  701 Subject: [PATCH 2/3] fix infinite loop when extracting empty bzip2 data
  702 
  703 Bug: https://sourceforge.net/p/infozip/patches/23/
  704 ---
  705  extract.c | 6 ++++++
  706  1 file changed, 6 insertions(+)
  707 
  708 diff --git a/extract.c b/extract.c
  709 index 7134bfe..29db027 100644
  710 --- a/extract.c
  711 +++ b/extract.c
  712 @@ -2733,6 +2733,12 @@ __GDEF
  713      int repeated_buf_err;
  714      bz_stream bstrm;
  715  
  716 +    if (G.incnt <= 0 && G.csize <= 0L) {
  717 +        /* avoid an infinite loop */
  718 +        Trace((stderr, "UZbunzip2() got empty input\n"));
  719 +        return 2;
  720 +    }
  721 +
  722  #if (defined(DLL) && !defined(NO_SLIDE_REDIR))
  723      if (G.redirect_slide)
  724          wsize = G.redirect_size, redirSlide = G.redirect_buffer;
  725 -- 
  726 2.4.6
  727 
  728 
  729 From bd150334fb4084f5555a6be26b015a0671cb5b74 Mon Sep 17 00:00:00 2001
  730 From: Kamil Dudka <kdudka@redhat.com>
  731 Date: Tue, 22 Sep 2015 18:52:23 +0200
  732 Subject: [PATCH 3/3] extract: prevent unsigned overflow on invalid input
  733 
  734 Suggested-by: Stefan Cornelius
  735 ---
  736  extract.c | 11 ++++++++++-
  737  1 file changed, 10 insertions(+), 1 deletion(-)
  738 
  739 diff --git a/extract.c b/extract.c
  740 index 29db027..b9ae667 100644
  741 --- a/extract.c
  742 +++ b/extract.c
  743 @@ -1257,8 +1257,17 @@ static int extract_or_test_entrylist(__G__ numchunk,
  744          if (G.lrec.compression_method == STORED) {
  745              zusz_t csiz_decrypted = G.lrec.csize;
  746  
  747 -            if (G.pInfo->encrypted)
  748 +            if (G.pInfo->encrypted) {
  749 +                if (csiz_decrypted < 12) {
  750 +                    /* handle the error now to prevent unsigned overflow */
  751 +                    Info(slide, 0x401, ((char *)slide,
  752 +                      LoadFarStringSmall(ErrUnzipNoFile),
  753 +                      LoadFarString(InvalidComprData),
  754 +                      LoadFarStringSmall2(Inflate)));
  755 +                    return PK_ERR;
  756 +                }
  757                  csiz_decrypted -= 12;
  758 +            }
  759              if (G.lrec.ucsize != csiz_decrypted) {
  760                  Info(slide, 0x401, ((char *)slide,
  761                    LoadFarStringSmall2(WrnStorUCSizCSizDiff),
  762 -- 
  763 2.5.2
  764 
  765 From: Giovanni Scafora <giovanni.archlinux.org>
  766 Subject: unzip files encoded with non-latin, non-unicode file names
  767 Last-Update: 2015-02-11
  768 
  769 Updated 2015-02-11 by Marc Deslauriers <marc.deslauriers@canonical.com>
  770 to fix buffer overflow in charset_to_intern()
  771 
  772 Index: unzip-6.0/unix/unix.c
  773 ===================================================================
  774 --- unzip-6.0.orig/unix/unix.c	2015-02-11 08:46:43.675324290 -0500
  775 +++ unzip-6.0/unix/unix.c	2015-02-11 09:18:04.902081319 -0500
  776 @@ -30,6 +30,9 @@
  777  #define UNZIP_INTERNAL
  778  #include "unzip.h"
  779  
  780 +#include <iconv.h>
  781 +#include <langinfo.h>
  782 +
  783  #ifdef SCO_XENIX
  784  #  define SYSNDIR
  785  #else  /* SCO Unix, AIX, DNIX, TI SysV, Coherent 4.x, ... */
  786 @@ -1874,3 +1877,102 @@
  787      }
  788  }
  789  #endif /* QLZIP */
  790 +
  791 +
  792 +typedef struct {
  793 +    char *local_charset;
  794 +    char *archive_charset;
  795 +} CHARSET_MAP;
  796 +
  797 +/* A mapping of local <-> archive charsets used by default to convert filenames
  798 + * of DOS/Windows Zip archives. Currently very basic. */
  799 +static CHARSET_MAP dos_charset_map[] = {
  800 +    { "ANSI_X3.4-1968", "CP850" },
  801 +    { "ISO-8859-1", "CP850" },
  802 +    { "CP1252", "CP850" },
  803 +    { "UTF-8", "CP866" },
  804 +    { "KOI8-R", "CP866" },
  805 +    { "KOI8-U", "CP866" },
  806 +    { "ISO-8859-5", "CP866" }
  807 +};
  808 +
  809 +char OEM_CP[MAX_CP_NAME] = "";
  810 +char ISO_CP[MAX_CP_NAME] = "";
  811 +
  812 +/* Try to guess the default value of OEM_CP based on the current locale.
  813 + * ISO_CP is left alone for now. */
  814 +void init_conversion_charsets()
  815 +{
  816 +    const char *local_charset;
  817 +    int i;
  818 +
  819 +    /* Make a guess only if OEM_CP not already set. */ 
  820 +    if(*OEM_CP == '\0') {
  821 +    	local_charset = nl_langinfo(CODESET);
  822 +    	for(i = 0; i < sizeof(dos_charset_map)/sizeof(CHARSET_MAP); i++)
  823 +    		if(!strcasecmp(local_charset, dos_charset_map[i].local_charset)) {
  824 +    			strncpy(OEM_CP, dos_charset_map[i].archive_charset,
  825 +    					sizeof(OEM_CP));
  826 +    			break;
  827 +    		}
  828 +    }
  829 +}
  830 +
  831 +/* Convert a string from one encoding to the current locale using iconv().
  832 + * Be as non-intrusive as possible. If error is encountered during covertion
  833 + * just leave the string intact. */
  834 +static void charset_to_intern(char *string, char *from_charset)
  835 +{
  836 +    iconv_t cd;
  837 +    char *s,*d, *buf;
  838 +    size_t slen, dlen, buflen;
  839 +    const char *local_charset;
  840 +
  841 +    if(*from_charset == '\0')
  842 +    	return;
  843 +
  844 +    buf = NULL;
  845 +    local_charset = nl_langinfo(CODESET);
  846 +
  847 +    if((cd = iconv_open(local_charset, from_charset)) == (iconv_t)-1)
  848 +        return;
  849 +
  850 +    slen = strlen(string);
  851 +    s = string;
  852 +
  853 +    /*  Make sure OUTBUFSIZ + 1 never ends up smaller than FILNAMSIZ
  854 +     *  as this function also gets called with G.outbuf in fileio.c
  855 +     */
  856 +    buflen = FILNAMSIZ;
  857 +    if (OUTBUFSIZ + 1 < FILNAMSIZ)
  858 +    {
  859 +        buflen = OUTBUFSIZ + 1;
  860 +    }
  861 +
  862 +    d = buf = malloc(buflen);
  863 +    if(!d)
  864 +    	goto cleanup;
  865 +
  866 +    bzero(buf,buflen);
  867 +    dlen = buflen - 1;
  868 +
  869 +    if(iconv(cd, &s, &slen, &d, &dlen) == (size_t)-1)
  870 +    	goto cleanup;
  871 +    strncpy(string, buf, buflen);
  872 +
  873 +    cleanup:
  874 +    free(buf);
  875 +    iconv_close(cd);
  876 +}
  877 +
  878 +/* Convert a string from OEM_CP to the current locale charset. */
  879 +inline void oem_intern(char *string)
  880 +{
  881 +    charset_to_intern(string, OEM_CP);
  882 +}
  883 +
  884 +/* Convert a string from ISO_CP to the current locale charset. */
  885 +inline void iso_intern(char *string)
  886 +{
  887 +    charset_to_intern(string, ISO_CP);
  888 +}
  889 Index: unzip-6.0/unix/unxcfg.h
  890 ===================================================================
  891 --- unzip-6.0.orig/unix/unxcfg.h	2015-02-11 08:46:43.675324290 -0500
  892 +++ unzip-6.0/unix/unxcfg.h	2015-02-11 08:46:43.671324260 -0500
  893 @@ -228,4 +228,30 @@
  894  /* wild_dir, dirname, wildname, matchname[], dirnamelen, have_dirname, */
  895  /*    and notfirstcall are used by do_wild().                          */
  896  
  897 +
  898 +#define MAX_CP_NAME 25 
  899 +   
  900 +#ifdef SETLOCALE
  901 +#  undef SETLOCALE
  902 +#endif
  903 +#define SETLOCALE(category, locale) setlocale(category, locale)
  904 +#include <locale.h>
  905 +   
  906 +#ifdef _ISO_INTERN
  907 +#  undef _ISO_INTERN
  908 +#endif
  909 +#define _ISO_INTERN(str1) iso_intern(str1)
  910 +
  911 +#ifdef _OEM_INTERN
  912 +#  undef _OEM_INTERN
  913 +#endif
  914 +#ifndef IZ_OEM2ISO_ARRAY
  915 +#  define IZ_OEM2ISO_ARRAY
  916 +#endif
  917 +#define _OEM_INTERN(str1) oem_intern(str1)
  918 +
  919 +void iso_intern(char *);
  920 +void oem_intern(char *);
  921 +void init_conversion_charsets(void);
  922 +   
  923  #endif /* !__unxcfg_h */
  924 Index: unzip-6.0/unzip.c
  925 ===================================================================
  926 --- unzip-6.0.orig/unzip.c	2015-02-11 08:46:43.675324290 -0500
  927 +++ unzip-6.0/unzip.c	2015-02-11 08:46:43.675324290 -0500
  928 @@ -327,11 +327,21 @@
  929    -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
  930                                           -v  verbose, multi-page format\n";
  931  
  932 +#ifndef UNIX
  933  static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
  934    -h  print header line       -t  print totals for listed files or for all\n\
  935    -z  print zipfile comment   -T  print file times in sortable decimal format\
  936  \n  -C  be case-insensitive   %s\
  937    -x  exclude filenames that follow from listing\n";
  938 +#else /* UNIX */
  939 +static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
  940 +  -h  print header line       -t  print totals for listed files or for all\n\
  941 +  -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
  942 +\n %c-C%c be case-insensitive   %s\
  943 +  -x  exclude filenames that follow from listing\n\
  944 +  -O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives\n\
  945 +  -I CHARSET  specify a character encoding for UNIX and other archives\n";
  946 +#endif /* !UNIX */
  947  #ifdef MORE
  948     static ZCONST char Far ZipInfoUsageLine4[] =
  949       "  -M  page output through built-in \"more\"\n";
  950 @@ -664,6 +674,17 @@
  951    -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\n\
  952    -C  match filenames case-insensitively     -L  make (some) names \
  953  lowercase\n %-42s  -V  retain VMS version numbers\n%s";
  954 +#elif (defined UNIX)
  955 +static ZCONST char Far UnzipUsageLine4[] = "\
  956 +modifiers:\n\
  957 +  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)\n\
  958 +  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files\n\
  959 +  -j  junk paths (do not make directories)   -aa treat ALL files as text\n\
  960 +  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\n\
  961 +  -C  match filenames case-insensitively     -L  make (some) names \
  962 +lowercase\n %-42s  -V  retain VMS version numbers\n%s\
  963 +  -O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives\n\
  964 +  -I CHARSET  specify a character encoding for UNIX and other archives\n\n";
  965  #else /* !VMS */
  966  static ZCONST char Far UnzipUsageLine4[] = "\
  967  modifiers:\n\
  968 @@ -802,6 +823,10 @@
  969  #endif /* UNICODE_SUPPORT */
  970  
  971  
  972 +#ifdef UNIX
  973 +    init_conversion_charsets();
  974 +#endif
  975 +
  976  #if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
  977      extern void DebugMalloc(void);
  978  
  979 @@ -1335,6 +1360,11 @@
  980      argc = *pargc;
  981      argv = *pargv;
  982  
  983 +#ifdef UNIX
  984 +    extern char OEM_CP[MAX_CP_NAME];
  985 +    extern char ISO_CP[MAX_CP_NAME];
  986 +#endif
  987 +    
  988      while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
  989          s = *argv + 1;
  990          while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  991 @@ -1516,6 +1546,35 @@
  992                      }
  993                      break;
  994  #endif  /* MACOS */
  995 +#ifdef UNIX
  996 +    			case ('I'):
  997 +                    if (negative) {
  998 +                        Info(slide, 0x401, ((char *)slide,
  999 +                          "error:  encodings can't be negated"));
 1000 +                        return(PK_PARAM);
 1001 +    				} else {
 1002 +    					if(*s) { /* Handle the -Icharset case */
 1003 +    						/* Assume that charsets can't start with a dash to spot arguments misuse */
 1004 +    						if(*s == '-') { 
 1005 +    	                        Info(slide, 0x401, ((char *)slide,
 1006 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1007 +    	                        return(PK_PARAM); 
 1008 +    						}
 1009 +    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1010 +    					} else { /* -I charset */
 1011 +    						++argv;
 1012 +    						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1013 +    	                        Info(slide, 0x401, ((char *)slide,
 1014 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1015 +    	                        return(PK_PARAM); 
 1016 +    						}
 1017 +    						s = *argv;
 1018 +    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1019 +    					}
 1020 +    					while(*(++s)); /* No params straight after charset name */
 1021 +    				}
 1022 +    				break;
 1023 +#endif /* ?UNIX */
 1024                  case ('j'):    /* junk pathnames/directory structure */
 1025                      if (negative)
 1026                          uO.jflag = FALSE, negative = 0;
 1027 @@ -1591,6 +1650,35 @@
 1028                      } else
 1029                          ++uO.overwrite_all;
 1030                      break;
 1031 +#ifdef UNIX
 1032 +    			case ('O'):
 1033 +                    if (negative) {
 1034 +                        Info(slide, 0x401, ((char *)slide,
 1035 +                          "error:  encodings can't be negated"));
 1036 +                        return(PK_PARAM);
 1037 +    				} else {
 1038 +    					if(*s) { /* Handle the -Ocharset case */
 1039 +    						/* Assume that charsets can't start with a dash to spot arguments misuse */
 1040 +    						if(*s == '-') { 
 1041 +    	                        Info(slide, 0x401, ((char *)slide,
 1042 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1043 +    	                        return(PK_PARAM); 
 1044 +    						}
 1045 +    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1046 +    					} else { /* -O charset */
 1047 +    						++argv;
 1048 +    						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1049 +    	                        Info(slide, 0x401, ((char *)slide,
 1050 +        		                  "error:  a valid character encoding should follow the -O argument"));
 1051 +    	                        return(PK_PARAM); 
 1052 +    						}
 1053 +    						s = *argv;
 1054 +    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1055 +    					}
 1056 +    					while(*(++s)); /* No params straight after charset name */
 1057 +    				}
 1058 +    				break;
 1059 +#endif /* ?UNIX */
 1060                  case ('p'):    /* pipes:  extract to stdout, no messages */
 1061                      if (negative) {
 1062                          uO.cflag = FALSE;
 1063 Index: unzip-6.0/unzpriv.h
 1064 ===================================================================
 1065 --- unzip-6.0.orig/unzpriv.h	2015-02-11 08:46:43.675324290 -0500
 1066 +++ unzip-6.0/unzpriv.h	2015-02-11 08:46:43.675324290 -0500
 1067 @@ -3008,7 +3008,7 @@
 1068           !(((islochdr) || (isuxatt)) && \
 1069             ((hostver) == 25 || (hostver) == 26 || (hostver) == 40))) || \
 1070          (hostnum) == FS_HPFS_ || \
 1071 -        ((hostnum) == FS_NTFS_ && (hostver) == 50)) { \
 1072 +        ((hostnum) == FS_NTFS_ /* && (hostver) == 50 */ )) { \
 1073          _OEM_INTERN((string)); \
 1074      } else { \
 1075          _ISO_INTERN((string)); \
 1076 Index: unzip-6.0/zipinfo.c
 1077 ===================================================================
 1078 --- unzip-6.0.orig/zipinfo.c	2015-02-11 08:46:43.675324290 -0500
 1079 +++ unzip-6.0/zipinfo.c	2015-02-11 08:46:43.675324290 -0500
 1080 @@ -457,6 +457,10 @@
 1081      int    tflag_slm=TRUE, tflag_2v=FALSE;
 1082      int    explicit_h=FALSE, explicit_t=FALSE;
 1083  
 1084 +#ifdef UNIX
 1085 +    extern char OEM_CP[MAX_CP_NAME];
 1086 +    extern char ISO_CP[MAX_CP_NAME];
 1087 +#endif
 1088  
 1089  #ifdef MACOS
 1090      uO.lflag = LFLAG;         /* reset default on each call */
 1091 @@ -501,6 +505,35 @@
 1092                              uO.lflag = 0;
 1093                      }
 1094                      break;
 1095 +#ifdef UNIX
 1096 +    			case ('I'):
 1097 +                    if (negative) {
 1098 +                        Info(slide, 0x401, ((char *)slide,
 1099 +                          "error:  encodings can't be negated"));
 1100 +                        return(PK_PARAM);
 1101 +    				} else {
 1102 +    					if(*s) { /* Handle the -Icharset case */
 1103 +    						/* Assume that charsets can't start with a dash to spot arguments misuse */
 1104 +    						if(*s == '-') { 
 1105 +    	                        Info(slide, 0x401, ((char *)slide,
 1106 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1107 +    	                        return(PK_PARAM); 
 1108 +    						}
 1109 +    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1110 +    					} else { /* -I charset */
 1111 +    						++argv;
 1112 +    						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1113 +    	                        Info(slide, 0x401, ((char *)slide,
 1114 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1115 +    	                        return(PK_PARAM); 
 1116 +    						}
 1117 +    						s = *argv;
 1118 +    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1119 +    					}
 1120 +    					while(*(++s)); /* No params straight after charset name */
 1121 +    				}
 1122 +    				break;
 1123 +#endif /* ?UNIX */
 1124                  case 'l':      /* longer form of "ls -l" type listing */
 1125                      if (negative)
 1126                          uO.lflag = -2, negative = 0;
 1127 @@ -521,6 +554,35 @@
 1128                          G.M_flag = TRUE;
 1129                      break;
 1130  #endif
 1131 +#ifdef UNIX
 1132 +    			case ('O'):
 1133 +                    if (negative) {
 1134 +                        Info(slide, 0x401, ((char *)slide,
 1135 +                          "error:  encodings can't be negated"));
 1136 +                        return(PK_PARAM);
 1137 +    				} else {
 1138 +    					if(*s) { /* Handle the -Ocharset case */
 1139 +    						/* Assume that charsets can't start with a dash to spot arguments misuse */
 1140 +    						if(*s == '-') { 
 1141 +    	                        Info(slide, 0x401, ((char *)slide,
 1142 +        		                  "error:  a valid character encoding should follow the -I argument"));
 1143 +    	                        return(PK_PARAM); 
 1144 +    						}
 1145 +    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1146 +    					} else { /* -O charset */
 1147 +    						++argv;
 1148 +    						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1149 +    	                        Info(slide, 0x401, ((char *)slide,
 1150 +        		                  "error:  a valid character encoding should follow the -O argument"));
 1151 +    	                        return(PK_PARAM); 
 1152 +    						}
 1153 +    						s = *argv;
 1154 +    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1155 +    					}
 1156 +    					while(*(++s)); /* No params straight after charset name */
 1157 +    				}
 1158 +    				break;
 1159 +#endif /* ?UNIX */
 1160                  case 's':      /* default:  shorter "ls -l" type listing */
 1161                      if (negative)
 1162                          uO.lflag = -2, negative = 0;
 1163 From ca0212ba19b64488b9e8459a762c11ecd6e7d0bd Mon Sep 17 00:00:00 2001
 1164 From: Petr Stodulka <pstodulk@redhat.com>
 1165 Date: Tue, 24 Nov 2015 17:56:11 +0100
 1166 Subject: [PATCH] print correctly non-ascii filenames
 1167 
 1168 ---
 1169  extract.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++--------------
 1170  unzpriv.h |   7 ++
 1171  2 files changed, 233 insertions(+), 63 deletions(-)
 1172 
 1173 diff --git a/extract.c b/extract.c
 1174 index 0ee4e93..741b7e0 100644
 1175 --- a/extract.c
 1176 +++ b/extract.c
 1177 @@ -2648,8 +2648,21 @@ static void set_deferred_symlink(__G__ slnk_entry)
 1178  } /* end function set_deferred_symlink() */
 1179  #endif /* SYMLINKS */
 1180  
 1181 +/*
 1182 + * If Unicode is supported, assume we have what we need to do this
 1183 + * check using wide characters, avoiding MBCS issues.
 1184 + */
 1185  
 1186 -
 1187 +#ifndef UZ_FNFILTER_REPLACECHAR
 1188 +        /* A convenient choice for the replacement of unprintable char codes is
 1189 +         * the "single char wildcard", as this character is quite unlikely to
 1190 +         * appear in filenames by itself.  The following default definition
 1191 +         * sets the replacement char to a question mark as the most common
 1192 +         * "single char wildcard"; this setting should be overridden in the
 1193 +         * appropiate system-specific configuration header when needed.
 1194 +         */
 1195 +# define UZ_FNFILTER_REPLACECHAR      '?'
 1196 +#endif
 1197  
 1198  /*************************/
 1199  /*  Function fnfilter()  */        /* here instead of in list.c for SFX */
 1200 @@ -2661,48 +2674,168 @@ char *fnfilter(raw, space, size)   /* convert name to safely printable form */
 1201      extent size;
 1202  {
 1203  #ifndef NATIVE   /* ASCII:  filter ANSI escape codes, etc. */
 1204 -    ZCONST uch *r=(ZCONST uch *)raw;
 1205 +    ZCONST uch *r; // =(ZCONST uch *)raw;
 1206      uch *s=space;
 1207      uch *slim=NULL;
 1208      uch *se=NULL;
 1209      int have_overflow = FALSE;
 1210  
 1211 -    if (size > 0) {
 1212 -        slim = space + size
 1213 -#ifdef _MBCS
 1214 -                     - (MB_CUR_MAX - 1)
 1215 -#endif
 1216 -                     - 4;
 1217 +# if defined( UNICODE_SUPPORT) && defined( _MBCS)
 1218 +/* If Unicode support is enabled, and we have multi-byte characters,
 1219 + * then do the isprint() checks by first converting to wide characters
 1220 + * and checking those.  This avoids our having to parse multi-byte
 1221 + * characters for ourselves.  After the wide-char replacements have been
 1222 + * made, the wide string is converted back to the local character set.
 1223 + */
 1224 +    wchar_t *wstring;    /* wchar_t version of raw */
 1225 +    size_t wslen;        /* length of wstring */
 1226 +    wchar_t *wostring;   /* wchar_t version of output string */
 1227 +    size_t woslen;       /* length of wostring */
 1228 +    char *newraw;        /* new raw */
 1229 +
 1230 +    /* 2012-11-06 SMS.
 1231 +     * Changed to check the value returned by mbstowcs(), and bypass the
 1232 +     * Unicode processing if it fails.  This seems to fix a problem
 1233 +     * reported in the SourceForge forum, but it's not clear that we
 1234 +     * should be doing any Unicode processing without some evidence that
 1235 +     * the name actually is Unicode.  (Check bit 11 in the flags before
 1236 +     * coming here?)
 1237 +     * http://sourceforge.net/p/infozip/bugs/40/
 1238 +     */
 1239 +
 1240 +    if (MB_CUR_MAX <= 1)
 1241 +    {
 1242 +        /* There's no point to converting multi-byte chars if there are
 1243 +         * no multi-byte chars.
 1244 +         */
 1245 +        wslen = (size_t)-1;
 1246      }
 1247 -    while (*r) {
 1248 -        if (size > 0 && s >= slim && se == NULL) {
 1249 -            se = s;
 1250 +    else
 1251 +    {
 1252 +        /* Get Unicode wide character count (for storage allocation). */
 1253 +        wslen = mbstowcs( NULL, raw, 0);
 1254 +    }
 1255 +
 1256 +    if (wslen != (size_t)-1)
 1257 +    {
 1258 +        /* Apparently valid Unicode.  Allocate wide-char storage. */
 1259 +        wstring = (wchar_t *)malloc((wslen + 1) * sizeof(wchar_t));
 1260 +        if (wstring == NULL) {
 1261 +            strcpy( (char *)space, raw);
 1262 +            return (char *)space;
 1263          }
 1264 -#ifdef QDOS
 1265 -        if (qlflag & 2) {
 1266 -            if (*r == '/' || *r == '.') {
 1267 +        wostring = (wchar_t *)malloc(2 * (wslen + 1) * sizeof(wchar_t));
 1268 +        if (wostring == NULL) {
 1269 +            free(wstring);
 1270 +            strcpy( (char *)space, raw);
 1271 +            return (char *)space;
 1272 +        }
 1273 +
 1274 +        /* Convert the multi-byte Unicode to wide chars. */
 1275 +        wslen = mbstowcs(wstring, raw, wslen + 1);
 1276 +
 1277 +        /* Filter the wide-character string. */
 1278 +        fnfilterw( wstring, wostring, (2 * (wslen + 1) * sizeof(wchar_t)));
 1279 +
 1280 +        /* Convert filtered wide chars back to multi-byte. */
 1281 +        woslen = wcstombs( NULL, wostring, 0);
 1282 +        if ((newraw = malloc(woslen + 1)) == NULL) {
 1283 +            free(wstring);
 1284 +            free(wostring);
 1285 +            strcpy( (char *)space, raw);
 1286 +            return (char *)space;
 1287 +        }
 1288 +        woslen = wcstombs( newraw, wostring, (woslen * MB_CUR_MAX) + 1);
 1289 +
 1290 +        if (size > 0) {
 1291 +            slim = space + size - 4;
 1292 +        }
 1293 +        r = (ZCONST uch *)newraw;
 1294 +        while (*r) {
 1295 +            if (size > 0 && s >= slim && se == NULL) {
 1296 +                se = s;
 1297 +            }
 1298 +#  ifdef QDOS
 1299 +            if (qlflag & 2) {
 1300 +                if (*r == '/' || *r == '.') {
 1301 +                    if (se != NULL && (s > (space + (size-3)))) {
 1302 +                        have_overflow = TRUE;
 1303 +                        break;
 1304 +                    }
 1305 +                    ++r;
 1306 +                    *s++ = '_';
 1307 +                    continue;
 1308 +                }
 1309 +            } else
 1310 +#  endif
 1311 +            {
 1312                  if (se != NULL && (s > (space + (size-3)))) {
 1313                      have_overflow = TRUE;
 1314                      break;
 1315                  }
 1316 -                ++r;
 1317 -                *s++ = '_';
 1318 -                continue;
 1319 +                *s++ = *r++;
 1320              }
 1321 -        } else
 1322 +        }
 1323 +        if (have_overflow) {
 1324 +            strcpy((char *)se, "...");
 1325 +        } else {
 1326 +            *s = '\0';
 1327 +        }
 1328 +
 1329 +        free(wstring);
 1330 +        free(wostring);
 1331 +        free(newraw);
 1332 +    }
 1333 +    else
 1334 +# endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
 1335 +    {
 1336 +        /* No Unicode support, or apparently invalid Unicode. */
 1337 +        r = (ZCONST uch *)raw;
 1338 +
 1339 +        if (size > 0) {
 1340 +            slim = space + size
 1341 +#ifdef _MBCS
 1342 +                         - (MB_CUR_MAX - 1)
 1343 +#endif
 1344 +                         - 4;
 1345 +        }
 1346 +        while (*r) {
 1347 +            if (size > 0 && s >= slim && se == NULL) {
 1348 +                se = s;
 1349 +            }
 1350 +#ifdef QDOS
 1351 +            if (qlflag & 2) {
 1352 +                if (*r == '/' || *r == '.') {
 1353 +                    if (se != NULL && (s > (space + (size-3)))) {
 1354 +                        have_overflow = TRUE;
 1355 +                        break;
 1356 +                    }
 1357 +                    ++r;
 1358 +                    *s++ = '_';
 1359 +                    continue;
 1360 +                }
 1361 +            } else
 1362  #endif
 1363  #ifdef HAVE_WORKING_ISPRINT
 1364 -# ifndef UZ_FNFILTER_REPLACECHAR
 1365 -    /* A convenient choice for the replacement of unprintable char codes is
 1366 -     * the "single char wildcard", as this character is quite unlikely to
 1367 -     * appear in filenames by itself.  The following default definition
 1368 -     * sets the replacement char to a question mark as the most common
 1369 -     * "single char wildcard"; this setting should be overridden in the
 1370 -     * appropiate system-specific configuration header when needed.
 1371 -     */
 1372 -#   define UZ_FNFILTER_REPLACECHAR      '?'
 1373 -# endif
 1374 -        if (!isprint(*r)) {
 1375 +            if (!isprint(*r)) {
 1376 +                if (*r < 32) {
 1377 +                    /* ASCII control codes are escaped as "^{letter}". */
 1378 +                    if (se != NULL && (s > (space + (size-4)))) {
 1379 +                        have_overflow = TRUE;
 1380 +                        break;
 1381 +                    }
 1382 +                    *s++ = '^', *s++ = (uch)(64 + *r++);
 1383 +                } else {
 1384 +                    /* Other unprintable codes are replaced by the
 1385 +                     * placeholder character. */
 1386 +                    if (se != NULL && (s > (space + (size-3)))) {
 1387 +                        have_overflow = TRUE;
 1388 +                        break;
 1389 +                    }
 1390 +                    *s++ = UZ_FNFILTER_REPLACECHAR;
 1391 +                    INCSTR(r);
 1392 +                }
 1393 +#else /* !HAVE_WORKING_ISPRINT */
 1394              if (*r < 32) {
 1395                  /* ASCII control codes are escaped as "^{letter}". */
 1396                  if (se != NULL && (s > (space + (size-4)))) {
 1397 @@ -2710,47 +2843,30 @@ char *fnfilter(raw, space, size)   /* convert name to safely printable form */
 1398                      break;
 1399                  }
 1400                  *s++ = '^', *s++ = (uch)(64 + *r++);
 1401 +#endif /* ?HAVE_WORKING_ISPRINT */
 1402              } else {
 1403 -                /* Other unprintable codes are replaced by the
 1404 -                 * placeholder character. */
 1405 +#ifdef _MBCS
 1406 +                unsigned i = CLEN(r);
 1407 +                if (se != NULL && (s > (space + (size-i-2)))) {
 1408 +                    have_overflow = TRUE;
 1409 +                    break;
 1410 +                }
 1411 +                for (; i > 0; i--)
 1412 +                    *s++ = *r++;
 1413 +#else
 1414                  if (se != NULL && (s > (space + (size-3)))) {
 1415                      have_overflow = TRUE;
 1416                      break;
 1417                  }
 1418 -                *s++ = UZ_FNFILTER_REPLACECHAR;
 1419 -                INCSTR(r);
 1420 -            }
 1421 -#else /* !HAVE_WORKING_ISPRINT */
 1422 -        if (*r < 32) {
 1423 -            /* ASCII control codes are escaped as "^{letter}". */
 1424 -            if (se != NULL && (s > (space + (size-4)))) {
 1425 -                have_overflow = TRUE;
 1426 -                break;
 1427 -            }
 1428 -            *s++ = '^', *s++ = (uch)(64 + *r++);
 1429 -#endif /* ?HAVE_WORKING_ISPRINT */
 1430 -        } else {
 1431 -#ifdef _MBCS
 1432 -            unsigned i = CLEN(r);
 1433 -            if (se != NULL && (s > (space + (size-i-2)))) {
 1434 -                have_overflow = TRUE;
 1435 -                break;
 1436 -            }
 1437 -            for (; i > 0; i--)
 1438                  *s++ = *r++;
 1439 -#else
 1440 -            if (se != NULL && (s > (space + (size-3)))) {
 1441 -                have_overflow = TRUE;
 1442 -                break;
 1443 -            }
 1444 -            *s++ = *r++;
 1445  #endif
 1446 -         }
 1447 -    }
 1448 -    if (have_overflow) {
 1449 -        strcpy((char *)se, "...");
 1450 -    } else {
 1451 -        *s = '\0';
 1452 +             }
 1453 +        }
 1454 +        if (have_overflow) {
 1455 +            strcpy((char *)se, "...");
 1456 +        } else {
 1457 +            *s = '\0';
 1458 +        }
 1459      }
 1460  
 1461  #ifdef WINDLL
 1462 @@ -2772,6 +2888,53 @@ char *fnfilter(raw, space, size)   /* convert name to safely printable form */
 1463  } /* end function fnfilter() */
 1464  
 1465  
 1466 +#if defined( UNICODE_SUPPORT) && defined( _MBCS)
 1467 +
 1468 +/****************************/
 1469 +/*  Function fnfilter[w]()  */  /* (Here instead of in list.c for SFX.) */
 1470 +/****************************/
 1471 +
 1472 +/* fnfilterw() - Convert wide name to safely printable form. */
 1473 +
 1474 +/* fnfilterw() - Convert wide-character name to safely printable form. */
 1475 +
 1476 +wchar_t *fnfilterw( src, dst, siz)
 1477 +    ZCONST wchar_t *src;        /* Pointer to source char (string). */
 1478 +    wchar_t *dst;               /* Pointer to destination char (string). */
 1479 +    extent siz;                 /* Not used (!). */
 1480 +{
 1481 +    wchar_t *dsx = dst;
 1482 +
 1483 +    /* Filter the wide chars. */
 1484 +    while (*src)
 1485 +    {
 1486 +        if (iswprint( *src))
 1487 +        {
 1488 +            /* Printable code.  Copy it. */
 1489 +            *dst++ = *src;
 1490 +        }
 1491 +        else
 1492 +        {
 1493 +            /* Unprintable code.  Substitute something printable for it. */
 1494 +            if (*src < 32)
 1495 +            {
 1496 +                /* Replace ASCII control code with "^{letter}". */
 1497 +                *dst++ = (wchar_t)'^';
 1498 +                *dst++ = (wchar_t)(64 + *src);
 1499 +            }
 1500 +            else
 1501 +            {
 1502 +                /* Replace other unprintable code with the placeholder. */
 1503 +                *dst++ = (wchar_t)UZ_FNFILTER_REPLACECHAR;
 1504 +            }
 1505 +        }
 1506 +        src++;
 1507 +    }
 1508 +    *dst = (wchar_t)0;  /* NUL-terminate the destination string. */
 1509 +    return dsx;
 1510 +} /* fnfilterw(). */
 1511 +
 1512 +#endif /* defined( UNICODE_SUPPORT) && defined( _MBCS) */
 1513  
 1514  
 1515  #ifdef SET_DIR_ATTRIB
 1516 diff --git a/unzpriv.h b/unzpriv.h
 1517 index 22d3923..e48a652 100644
 1518 --- a/unzpriv.h
 1519 +++ b/unzpriv.h
 1520 @@ -1212,6 +1212,7 @@
 1521  # ifdef UNICODE_WCHAR
 1522  #  if !(defined(_WIN32_WCE) || defined(POCKET_UNZIP))
 1523  #   include <wchar.h>
 1524 +#   include <wctype.h>
 1525  #  endif
 1526  # endif
 1527  # ifndef _MBCS  /* no need to include <locale.h> twice, see below */
 1528 @@ -2410,6 +2411,12 @@ int    memflush                  OF((__GPRO__ ZCONST uch *rawbuf, ulg size));
 1529  char  *fnfilter                  OF((ZCONST char *raw, uch *space,
 1530                                       extent size));
 1531  
 1532 +# if defined( UNICODE_SUPPORT) && defined( _MBCS)
 1533 +wchar_t *fnfilterw               OF((ZCONST wchar_t *src, wchar_t *dst,
 1534 +                                     extent siz));
 1535 +#endif
 1536 +
 1537 +
 1538  /*---------------------------------------------------------------------------
 1539      Decompression functions:
 1540    ---------------------------------------------------------------------------*/
 1541 -- 
 1542 2.4.3
 1543 
 1544 From 754137e70cf58a64ad524b704a86b651ba0cde07 Mon Sep 17 00:00:00 2001
 1545 From: Petr Stodulka <pstodulk@redhat.com>
 1546 Date: Wed, 14 Dec 2016 16:30:36 +0100
 1547 Subject: [PATCH] Fix CVE-2016-9844 (rhbz#1404283)
 1548 
 1549 Fixes buffer overflow in zipinfo in similar way like fix for
 1550 CVE-2014-9913 provided by upstream.
 1551 ---
 1552  zipinfo.c | 14 +++++++++++++-
 1553  1 file changed, 13 insertions(+), 1 deletion(-)
 1554 
 1555 diff --git a/zipinfo.c b/zipinfo.c
 1556 index c03620e..accca2a 100644
 1557 --- a/zipinfo.c
 1558 +++ b/zipinfo.c
 1559 @@ -1984,7 +1984,19 @@ static int zi_short(__G)   /* return PK-type error code */
 1560          ush  dnum=(ush)((G.crec.general_purpose_bit_flag>>1) & 3);
 1561          methbuf[3] = dtype[dnum];
 1562      } else if (methnum >= NUM_METHODS) {   /* unknown */
 1563 -        sprintf(&methbuf[1], "%03u", G.crec.compression_method);
 1564 +        /* 2016-12-05 SMS.
 1565 +         * https://launchpad.net/bugs/1643750
 1566 +         * Unexpectedly large compression methods overflow
 1567 +         * &methbuf[].  Use the old, three-digit decimal format
 1568 +         * for values which fit.  Otherwise, sacrifice the "u",
 1569 +         * and use four-digit hexadecimal.
 1570 +         */
 1571 +        if (G.crec.compression_method <= 999) {
 1572 +              sprintf( &methbuf[ 1], "%03u", G.crec.compression_method);
 1573 +        } else {
 1574 +              sprintf( &methbuf[ 0], "%04X", G.crec.compression_method);
 1575 +        }
 1576 +
 1577      }
 1578  
 1579      for (k = 0;  k < 15;  ++k)
 1580 -- 
 1581 2.5.5
 1582 
 1583 From: "Steven M. Schweda" <sms@antinode.info>
 1584 Subject: Do not ignore extra fields containing Unix Timestamps
 1585 Bug-Debian: https://bugs.debian.org/842993
 1586 X-Debian-version: 6.0-21
 1587 
 1588 --- a/process.c
 1589 +++ b/process.c
 1590 @@ -2914,10 +2914,13 @@
 1591              break;
 1592  
 1593            case EF_IZUNIX2:
 1594 -            if (have_new_type_eb == 0) {
 1595 -                flags &= ~0x0ff;        /* ignore any previous IZUNIX field */
 1596 +            if (have_new_type_eb == 0) {        /* (< 1) */
 1597                  have_new_type_eb = 1;
 1598              }
 1599 +            if (have_new_type_eb <= 1) {
 1600 +                /* Ignore any prior (EF_IZUNIX/EF_PKUNIX) UID/GID. */
 1601 +                flags &= 0x0ff;
 1602 +            }
 1603  #ifdef IZ_HAVE_UXUIDGID
 1604              if (have_new_type_eb > 1)
 1605                  break;          /* IZUNIX3 overrides IZUNIX2 e.f. block ! */
 1606 @@ -2933,6 +2936,8 @@
 1607              /* new 3rd generation Unix ef */
 1608              have_new_type_eb = 2;
 1609  
 1610 +            /* Ignore any prior EF_IZUNIX/EF_PKUNIX/EF_IZUNIX2 UID/GID. */
 1611 +            flags &= 0x0ff;
 1612          /*
 1613            Version       1 byte      version of this extra field, currently 1
 1614            UIDSize       1 byte      Size of UID field
 1615 @@ -2953,8 +2958,6 @@
 1616                  uid_size = *((EB_HEADSIZE + 1) + ef_buf);
 1617                  gid_size = *((EB_HEADSIZE + uid_size + 2) + ef_buf);
 1618  
 1619 -                flags &= ~0x0ff;      /* ignore any previous UNIX field */
 1620 -
 1621                  if ( read_ux3_value((EB_HEADSIZE + 2) + ef_buf,
 1622                                      uid_size, &z_uidgid[0])
 1623                      &&
 1624 --- a/fileio.c	2014-12-05 05:06:05 -0600
 1625 +++ b/fileio.c	2017-11-14 01:06:28 -0600
 1626 @@ -1,5 +1,5 @@
 1627  /*
 1628 -  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
 1629 +  Copyright (c) 1990-2017 Info-ZIP.  All rights reserved.
 1630  
 1631    See the accompanying file LICENSE, version 2009-Jan-02 or later
 1632    (the contents of which are also included in unzip.h) for terms of use.
 1633 @@ -1582,6 +1582,8 @@
 1634      int r = IZ_PW_ENTERED;
 1635      char *m;
 1636      char *prompt;
 1637 +    char *ep;
 1638 +    char *zp;
 1639  
 1640  #ifndef REENTRANT
 1641      /* tell picky compilers to shut up about "unused variable" warnings */
 1642 @@ -1590,9 +1592,12 @@
 1643  
 1644      if (*rcnt == 0) {           /* First call for current entry */
 1645          *rcnt = 2;
 1646 -        if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) {
 1647 -            sprintf(prompt, LoadFarString(PasswPrompt),
 1648 -                    FnFilter1(zfn), FnFilter2(efn));
 1649 +        zp = FnFilter1( zfn);
 1650 +        ep = FnFilter2( efn);
 1651 +        prompt = (char *)malloc(        /* Slightly too long (2* "%s"). */
 1652 +         sizeof( PasswPrompt)+ strlen( zp)+ strlen( ep));
 1653 +        if (prompt != (char *)NULL) {
 1654 +            sprintf(prompt, LoadFarString(PasswPrompt), zp, ep);
 1655              m = prompt;
 1656          } else
 1657              m = (char *)LoadFarString(PasswPrompt2);
 1658 --- unzip60/list.c	
 1659 +++ unzip60/list.c	
 1660 @@ -97,7 +97,7 @@ int list_files(__G)    /* return PK-type
 1661  {
 1662      int do_this_file=FALSE, cfactor, error, error_in_archive=PK_COOL;
 1663  #ifndef WINDLL
 1664 -    char sgn, cfactorstr[13];
 1665 +    char sgn, cfactorstr[1+10+1+1];	/* <sgn><int>%NUL */
 1666      int longhdr=(uO.vflag>1);
 1667  #endif
 1668      int date_format;
 1669 @@ -389,9 +389,9 @@ int list_files(__G)    /* return PK-type
 1670              }
 1671  #else /* !WINDLL */
 1672              if (cfactor == 100)
 1673 -                sprintf(cfactorstr, LoadFarString(CompFactor100));
 1674 +                snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
 1675              else
 1676 -                sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
 1677 +                snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
 1678              if (longhdr)
 1679                  Info(slide, 0, ((char *)slide, LoadFarString(LongHdrStats),
 1680                    FmZofft(G.crec.ucsize, "8", "u"), methbuf,
 1681 @@ -471,9 +471,9 @@ int list_files(__G)    /* return PK-type
 1682  
 1683  #else /* !WINDLL */
 1684          if (cfactor == 100)
 1685 -            sprintf(cfactorstr, LoadFarString(CompFactor100));
 1686 +            snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactor100));
 1687          else
 1688 -            sprintf(cfactorstr, LoadFarString(CompFactorStr), sgn, cfactor);
 1689 +            snprintf(cfactorstr, sizeof(cfactorstr), LoadFarString(CompFactorStr), sgn, cfactor);
 1690          if (longhdr) {
 1691              Info(slide, 0, ((char *)slide, LoadFarString(LongFileTrailer),
 1692                FmZofft(tot_ucsize, "8", "u"), FmZofft(tot_csize, "8", "u"),
 1693 From 06d1b08aef94984256cad3c5a54cedb10295681f Mon Sep 17 00:00:00 2001
 1694 From: Jakub Martisko <jamartis@redhat.com>
 1695 Date: Thu, 8 Nov 2018 09:31:18 +0100
 1696 Subject: [PATCH] Possible unterminated string fix
 1697 
 1698 ---
 1699  unix/unix.c   |  4 +++-
 1700  unix/unxcfg.h |  2 +-
 1701  unzip.c       | 12 ++++++++----
 1702  zipinfo.c     | 12 ++++++++----
 1703  4 files changed, 20 insertions(+), 10 deletions(-)
 1704 
 1705 diff --git a/unix/unix.c b/unix/unix.c
 1706 index 59b622d..cd57f80 100644
 1707 --- a/unix/unix.c
 1708 +++ b/unix/unix.c
 1709 @@ -1945,7 +1945,9 @@ void init_conversion_charsets()
 1710      	for(i = 0; i < sizeof(dos_charset_map)/sizeof(CHARSET_MAP); i++)
 1711      		if(!strcasecmp(local_charset, dos_charset_map[i].local_charset)) {
 1712      			strncpy(OEM_CP, dos_charset_map[i].archive_charset,
 1713 -    					sizeof(OEM_CP));
 1714 +    					MAX_CP_NAME - 1);
 1715 +
 1716 +			OEM_CP[MAX_CP_NAME - 1] = '\0';
 1717      			break;
 1718      		}
 1719      }
 1720 diff --git a/unix/unxcfg.h b/unix/unxcfg.h
 1721 index 8729de2..9ee8cfe 100644
 1722 --- a/unix/unxcfg.h
 1723 +++ b/unix/unxcfg.h
 1724 @@ -228,7 +228,7 @@ typedef struct stat z_stat;
 1725  /*    and notfirstcall are used by do_wild().                          */
 1726  
 1727  
 1728 -#define MAX_CP_NAME 25 
 1729 +#define MAX_CP_NAME 25 + 1 
 1730     
 1731  #ifdef SETLOCALE
 1732  #  undef SETLOCALE
 1733 diff --git a/unzip.c b/unzip.c
 1734 index 2d94a38..a485f2b 100644
 1735 --- a/unzip.c
 1736 +++ b/unzip.c
 1737 @@ -1561,7 +1561,8 @@ int uz_opts(__G__ pargc, pargv)
 1738          		                  "error:  a valid character encoding should follow the -I argument"));
 1739      	                        return(PK_PARAM); 
 1740      						}
 1741 -    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1742 +    						strncpy(ISO_CP, s, MAX_CP_NAME - 1);
 1743 +                ISO_CP[MAX_CP_NAME - 1] = '\0';
 1744      					} else { /* -I charset */
 1745      						++argv;
 1746      						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1747 @@ -1570,7 +1571,8 @@ int uz_opts(__G__ pargc, pargv)
 1748      	                        return(PK_PARAM); 
 1749      						}
 1750      						s = *argv;
 1751 -    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1752 +    						strncpy(ISO_CP, s, MAX_CP_NAME - 1);
 1753 +                ISO_CP[MAX_CP_NAME - 1] = '\0';
 1754      					}
 1755      					while(*(++s)); /* No params straight after charset name */
 1756      				}
 1757 @@ -1665,7 +1667,8 @@ int uz_opts(__G__ pargc, pargv)
 1758          		                  "error:  a valid character encoding should follow the -I argument"));
 1759      	                        return(PK_PARAM); 
 1760      						}
 1761 -    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1762 +    						strncpy(OEM_CP, s, MAX_CP_NAME - 1);
 1763 +                OEM_CP[MAX_CP_NAME - 1] = '\0';
 1764      					} else { /* -O charset */
 1765      						++argv;
 1766      						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1767 @@ -1674,7 +1677,8 @@ int uz_opts(__G__ pargc, pargv)
 1768      	                        return(PK_PARAM); 
 1769      						}
 1770      						s = *argv;
 1771 -    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1772 +    						strncpy(OEM_CP, s, MAX_CP_NAME - 1);
 1773 +                OEM_CP[MAX_CP_NAME - 1] = '\0';
 1774      					}
 1775      					while(*(++s)); /* No params straight after charset name */
 1776      				}
 1777 diff --git a/zipinfo.c b/zipinfo.c
 1778 index accca2a..cb7e08d 100644
 1779 --- a/zipinfo.c
 1780 +++ b/zipinfo.c
 1781 @@ -519,7 +519,8 @@ int zi_opts(__G__ pargc, pargv)
 1782          		                  "error:  a valid character encoding should follow the -I argument"));
 1783      	                        return(PK_PARAM); 
 1784      						}
 1785 -    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1786 +    						strncpy(ISO_CP, s, MAX_CP_NAME - 1);
 1787 +                ISO_CP[MAX_CP_NAME - 1] = '\0';
 1788      					} else { /* -I charset */
 1789      						++argv;
 1790      						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1791 @@ -528,7 +529,8 @@ int zi_opts(__G__ pargc, pargv)
 1792      	                        return(PK_PARAM); 
 1793      						}
 1794      						s = *argv;
 1795 -    						strncpy(ISO_CP, s, sizeof(ISO_CP));
 1796 +    						strncpy(ISO_CP, s, MAX_CP_NAME - 1);
 1797 +                ISO_CP[MAX_CP_NAME - 1] = '\0';
 1798      					}
 1799      					while(*(++s)); /* No params straight after charset name */
 1800      				}
 1801 @@ -568,7 +570,8 @@ int zi_opts(__G__ pargc, pargv)
 1802          		                  "error:  a valid character encoding should follow the -I argument"));
 1803      	                        return(PK_PARAM); 
 1804      						}
 1805 -    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1806 +    						strncpy(OEM_CP, s, MAX_CP_NAME - 1);
 1807 +                OEM_CP[MAX_CP_NAME - 1] = '\0';
 1808      					} else { /* -O charset */
 1809      						++argv;
 1810      						if(!(--argc > 0 && *argv != NULL && **argv != '-')) {
 1811 @@ -577,7 +580,8 @@ int zi_opts(__G__ pargc, pargv)
 1812      	                        return(PK_PARAM); 
 1813      						}
 1814      						s = *argv;
 1815 -    						strncpy(OEM_CP, s, sizeof(OEM_CP));
 1816 +    						strncpy(OEM_CP, s, MAX_CP_NAME - 1);
 1817 +                OEM_CP[MAX_CP_NAME - 1] = '\0';
 1818      					}
 1819      					while(*(++s)); /* No params straight after charset name */
 1820      				}
 1821 -- 
 1822 2.14.5
 1823 
 1824 From 41beb477c5744bc396fa1162ee0c14218ec12213 Mon Sep 17 00:00:00 2001
 1825 From: Mark Adler <madler@alumni.caltech.edu>
 1826 Date: Mon, 27 May 2019 08:20:32 -0700
 1827 Subject: [PATCH] Fix bug in undefer_input() that misplaced the input state.
 1828 
 1829 ---
 1830  fileio.c | 4 +++-
 1831  1 file changed, 3 insertions(+), 1 deletion(-)
 1832 
 1833 diff --git a/fileio.c b/fileio.c
 1834 index c042987..bc00d74 100644
 1835 --- a/fileio.c
 1836 +++ b/fileio.c
 1837 @@ -530,8 +530,10 @@ void undefer_input(__G)
 1838           * This condition was checked when G.incnt_leftover was set > 0 in
 1839           * defer_leftover_input(), and it is NOT allowed to touch G.csize
 1840           * before calling undefer_input() when (G.incnt_leftover > 0)
 1841 -         * (single exception: see read_byte()'s  "G.csize <= 0" handling) !!
 1842 +         * (single exception: see readbyte()'s  "G.csize <= 0" handling) !!
 1843           */
 1844 +        if (G.csize < 0L)
 1845 +            G.csize = 0L;
 1846          G.incnt = G.incnt_leftover + (int)G.csize;
 1847          G.inptr = G.inptr_leftover - (int)G.csize;
 1848          G.incnt_leftover = 0;
 1849 From 47b3ceae397d21bf822bc2ac73052a4b1daf8e1c Mon Sep 17 00:00:00 2001
 1850 From: Mark Adler <madler@alumni.caltech.edu>
 1851 Date: Tue, 11 Jun 2019 22:01:18 -0700
 1852 Subject: [PATCH] Detect and reject a zip bomb using overlapped entries.
 1853 
 1854 This detects an invalid zip file that has at least one entry that
 1855 overlaps with another entry or with the central directory to the
 1856 end of the file. A Fifield zip bomb uses overlapped local entries
 1857 to vastly increase the potential inflation ratio. Such an invalid
 1858 zip file is rejected.
 1859 
 1860 See https://www.bamsoftware.com/hacks/zipbomb/ for David Fifield's
 1861 analysis, construction, and examples of such zip bombs.
 1862 
 1863 The detection maintains a list of covered spans of the zip files
 1864 so far, where the central directory to the end of the file and any
 1865 bytes preceding the first entry at zip file offset zero are
 1866 considered covered initially. Then as each entry is decompressed
 1867 or tested, it is considered covered. When a new entry is about to
 1868 be processed, its initial offset is checked to see if it is
 1869 contained by a covered span. If so, the zip file is rejected as
 1870 invalid.
 1871 
 1872 This commit depends on a preceding commit: "Fix bug in
 1873 undefer_input() that misplaced the input state."
 1874 ---
 1875  extract.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1876  globals.c |   1 +
 1877  globals.h |   3 +
 1878  process.c |  11 ++++
 1879  unzip.h   |   1 +
 1880  5 files changed, 205 insertions(+), 1 deletion(-)
 1881 
 1882 diff --git a/extract.c b/extract.c
 1883 index 1acd769..0973a33 100644
 1884 --- a/extract.c
 1885 +++ b/extract.c
 1886 @@ -319,6 +319,125 @@ static ZCONST char Far UnsupportedExtraField[] =
 1887    "\nerror:  unsupported extra-field compression type (%u)--skipping\n";
 1888  static ZCONST char Far BadExtraFieldCRC[] =
 1889    "error [%s]:  bad extra-field CRC %08lx (should be %08lx)\n";
 1890 +static ZCONST char Far NotEnoughMemCover[] =
 1891 +  "error: not enough memory for bomb detection\n";
 1892 +static ZCONST char Far OverlappedComponents[] =
 1893 +  "error: invalid zip file with overlapped components (possible zip bomb)\n";
 1894 +
 1895 +
 1896 +
 1897 +
 1898 +
 1899 +/* A growable list of spans. */
 1900 +typedef zoff_t bound_t;
 1901 +typedef struct {
 1902 +    bound_t beg;        /* start of the span */
 1903 +    bound_t end;        /* one past the end of the span */
 1904 +} span_t;
 1905 +typedef struct {
 1906 +    span_t *span;       /* allocated, distinct, and sorted list of spans */
 1907 +    size_t num;         /* number of spans in the list */
 1908 +    size_t max;         /* allocated number of spans (num <= max) */
 1909 +} cover_t;
 1910 +
 1911 +/*
 1912 + * Return the index of the first span in cover whose beg is greater than val.
 1913 + * If there is no such span, then cover->num is returned.
 1914 + */
 1915 +static size_t cover_find(cover, val)
 1916 +    cover_t *cover;
 1917 +    bound_t val;
 1918 +{
 1919 +    size_t lo = 0, hi = cover->num;
 1920 +    while (lo < hi) {
 1921 +        size_t mid = (lo + hi) >> 1;
 1922 +        if (val < cover->span[mid].beg)
 1923 +            hi = mid;
 1924 +        else
 1925 +            lo = mid + 1;
 1926 +    }
 1927 +    return hi;
 1928 +}
 1929 +
 1930 +/* Return true if val lies within any one of the spans in cover. */
 1931 +static int cover_within(cover, val)
 1932 +    cover_t *cover;
 1933 +    bound_t val;
 1934 +{
 1935 +    size_t pos = cover_find(cover, val);
 1936 +    return pos > 0 && val < cover->span[pos - 1].end;
 1937 +}
 1938 +
 1939 +/*
 1940 + * Add a new span to the list, but only if the new span does not overlap any
 1941 + * spans already in the list. The new span covers the values beg..end-1. beg
 1942 + * must be less than end.
 1943 + *
 1944 + * Keep the list sorted and merge adjacent spans. Grow the allocated space for
 1945 + * the list as needed. On success, 0 is returned. If the new span overlaps any
 1946 + * existing spans, then 1 is returned and the new span is not added to the
 1947 + * list. If the new span is invalid because beg is greater than or equal to
 1948 + * end, then -1 is returned. If the list needs to be grown but the memory
 1949 + * allocation fails, then -2 is returned.
 1950 + */
 1951 +static int cover_add(cover, beg, end)
 1952 +    cover_t *cover;
 1953 +    bound_t beg;
 1954 +    bound_t end;
 1955 +{
 1956 +    size_t pos;
 1957 +    int prec, foll;
 1958 +
 1959 +    if (beg >= end)
 1960 +    /* The new span is invalid. */
 1961 +        return -1;
 1962 +
 1963 +    /* Find where the new span should go, and make sure that it does not
 1964 +       overlap with any existing spans. */
 1965 +    pos = cover_find(cover, beg);
 1966 +    if ((pos > 0 && beg < cover->span[pos - 1].end) ||
 1967 +        (pos < cover->num && end > cover->span[pos].beg))
 1968 +        return 1;
 1969 +
 1970 +    /* Check for adjacencies. */
 1971 +    prec = pos > 0 && beg == cover->span[pos - 1].end;
 1972 +    foll = pos < cover->num && end == cover->span[pos].beg;
 1973 +    if (prec && foll) {
 1974 +        /* The new span connects the preceding and following spans. Merge the
 1975 +           following span into the preceding span, and delete the following
 1976 +           span. */
 1977 +        cover->span[pos - 1].end = cover->span[pos].end;
 1978 +        cover->num--;
 1979 +        memmove(cover->span + pos, cover->span + pos + 1,
 1980 +                (cover->num - pos) * sizeof(span_t));
 1981 +    }
 1982 +    else if (prec)
 1983 +        /* The new span is adjacent only to the preceding span. Extend the end
 1984 +           of the preceding span. */
 1985 +        cover->span[pos - 1].end = end;
 1986 +    else if (foll)
 1987 +        /* The new span is adjacent only to the following span. Extend the
 1988 +           beginning of the following span. */
 1989 +        cover->span[pos].beg = beg;
 1990 +    else {
 1991 +        /* The new span has gaps between both the preceding and the following
 1992 +           spans. Assure that there is room and insert the span.  */
 1993 +        if (cover->num == cover->max) {
 1994 +            size_t max = cover->max == 0 ? 16 : cover->max << 1;
 1995 +            span_t *span = realloc(cover->span, max * sizeof(span_t));
 1996 +            if (span == NULL)
 1997 +                return -2;
 1998 +            cover->span = span;
 1999 +            cover->max = max;
 2000 +        }
 2001 +        memmove(cover->span + pos + 1, cover->span + pos,
 2002 +                (cover->num - pos) * sizeof(span_t));
 2003 +        cover->num++;
 2004 +        cover->span[pos].beg = beg;
 2005 +        cover->span[pos].end = end;
 2006 +    }
 2007 +    return 0;
 2008 +}
 2009  
 2010  
 2011  
 2012 @@ -374,6 +493,29 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2013      }
 2014  #endif /* !SFX || SFX_EXDIR */
 2015  
 2016 +    /* One more: initialize cover structure for bomb detection. Start with a
 2017 +       span that covers the central directory though the end of the file. */
 2018 +    if (G.cover == NULL) {
 2019 +        G.cover = malloc(sizeof(cover_t));
 2020 +        if (G.cover == NULL) {
 2021 +            Info(slide, 0x401, ((char *)slide,
 2022 +              LoadFarString(NotEnoughMemCover)));
 2023 +            return PK_MEM;
 2024 +        }
 2025 +        ((cover_t *)G.cover)->span = NULL;
 2026 +        ((cover_t *)G.cover)->max = 0;
 2027 +    }
 2028 +    ((cover_t *)G.cover)->num = 0;
 2029 +    if ((G.extra_bytes != 0 &&
 2030 +         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
 2031 +        cover_add((cover_t *)G.cover,
 2032 +                  G.extra_bytes + G.ecrec.offset_start_central_directory,
 2033 +                  G.ziplen) != 0) {
 2034 +        Info(slide, 0x401, ((char *)slide,
 2035 +          LoadFarString(NotEnoughMemCover)));
 2036 +        return PK_MEM;
 2037 +    }
 2038 +
 2039  /*---------------------------------------------------------------------------
 2040      The basic idea of this function is as follows.  Since the central di-
 2041      rectory lies at the end of the zipfile and the member files lie at the
 2042 @@ -591,7 +733,8 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2043              if (error > error_in_archive)
 2044                  error_in_archive = error;
 2045              /* ...and keep going (unless disk full or user break) */
 2046 -            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC) {
 2047 +            if (G.disk_full > 1 || error_in_archive == IZ_CTRLC ||
 2048 +                error == PK_BOMB) {
 2049                  /* clear reached_end to signal premature stop ... */
 2050                  reached_end = FALSE;
 2051                  /* ... and cancel scanning the central directory */
 2052 @@ -1060,6 +1203,11 @@ static int extract_or_test_entrylist(__G__ numchunk,
 2053  
 2054          /* seek_zipf(__G__ pInfo->offset);  */
 2055          request = G.pInfo->offset + G.extra_bytes;
 2056 +        if (cover_within((cover_t *)G.cover, request)) {
 2057 +            Info(slide, 0x401, ((char *)slide,
 2058 +              LoadFarString(OverlappedComponents)));
 2059 +            return PK_BOMB;
 2060 +        }
 2061          inbuf_offset = request % INBUFSIZ;
 2062          bufstart = request - inbuf_offset;
 2063  
 2064 @@ -1591,6 +1739,18 @@ static int extract_or_test_entrylist(__G__ numchunk,
 2065              return IZ_CTRLC;        /* cancel operation by user request */
 2066          }
 2067  #endif
 2068 +        error = cover_add((cover_t *)G.cover, request,
 2069 +                          G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
 2070 +        if (error < 0) {
 2071 +            Info(slide, 0x401, ((char *)slide,
 2072 +              LoadFarString(NotEnoughMemCover)));
 2073 +            return PK_MEM;
 2074 +        }
 2075 +        if (error != 0) {
 2076 +            Info(slide, 0x401, ((char *)slide,
 2077 +              LoadFarString(OverlappedComponents)));
 2078 +            return PK_BOMB;
 2079 +        }
 2080  #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
 2081          UserStop();
 2082  #endif
 2083 @@ -1992,6 +2152,34 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
 2084      }
 2085  
 2086      undefer_input(__G);
 2087 +
 2088 +    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
 2089 +        /* skip over data descriptor (harder than it sounds, due to signature
 2090 +         * ambiguity)
 2091 +         */
 2092 +#       define SIG 0x08074b50
 2093 +#       define LOW 0xffffffff
 2094 +        uch buf[12];
 2095 +        unsigned shy = 12 - readbuf((char *)buf, 12);
 2096 +        ulg crc = shy ? 0 : makelong(buf);
 2097 +        ulg clen = shy ? 0 : makelong(buf + 4);
 2098 +        ulg ulen = shy ? 0 : makelong(buf + 8); /* or high clen if ZIP64 */
 2099 +        if (crc == SIG &&                       /* if not SIG, no signature */
 2100 +            (G.lrec.crc32 != SIG ||             /* if not SIG, have signature */
 2101 +             (clen == SIG &&                    /* if not SIG, no signature */
 2102 +              ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
 2103 +               (ulen == SIG &&                  /* if not SIG, no signature */
 2104 +                (G.zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
 2105 +                                                /* if not SIG, have signature */
 2106 +                )))))
 2107 +                   /* skip four more bytes to account for signature */
 2108 +                   shy += 4 - readbuf((char *)buf, 4);
 2109 +        if (G.zip64)
 2110 +            shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
 2111 +        if (shy)
 2112 +            error = PK_ERR;
 2113 +    }
 2114 +
 2115      return error;
 2116  
 2117  } /* end function extract_or_test_member() */
 2118 diff --git a/globals.c b/globals.c
 2119 index fa8cca5..1e0f608 100644
 2120 --- a/globals.c
 2121 +++ b/globals.c
 2122 @@ -181,6 +181,7 @@ Uz_Globs *globalsCtor()
 2123  # if (!defined(NO_TIMESTAMPS))
 2124      uO.D_flag=1;    /* default to '-D', no restoration of dir timestamps */
 2125  # endif
 2126 +    G.cover = NULL;     /* not allocated yet */
 2127  #endif
 2128  
 2129      uO.lflag=(-1);
 2130 diff --git a/globals.h b/globals.h
 2131 index 11b7215..2bdcdeb 100644
 2132 --- a/globals.h
 2133 +++ b/globals.h
 2134 @@ -260,12 +260,15 @@ typedef struct Globals {
 2135      ecdir_rec       ecrec;         /* used in unzip.c, extract.c */
 2136      z_stat   statbuf;              /* used by main, mapname, check_for_newer */
 2137  
 2138 +    int zip64;                     /* true if Zip64 info in extra field */
 2139 +
 2140      int      mem_mode;
 2141      uch      *outbufptr;           /* extract.c static */
 2142      ulg      outsize;              /* extract.c static */
 2143      int      reported_backslash;   /* extract.c static */
 2144      int      disk_full;
 2145      int      newfile;
 2146 +    void     **cover;              /* used in extract.c for bomb detection */
 2147  
 2148      int      didCRlast;            /* fileio static */
 2149      ulg      numlines;             /* fileio static: number of lines printed */
 2150 diff --git a/process.c b/process.c
 2151 index 1e9a1e1..d2e4dc3 100644
 2152 --- a/process.c
 2153 +++ b/process.c
 2154 @@ -637,6 +637,13 @@ void free_G_buffers(__G)     /* releases all memory allocated in global vars */
 2155      }
 2156  #endif
 2157  
 2158 +    /* Free the cover span list and the cover structure. */
 2159 +    if (G.cover != NULL) {
 2160 +        free(*(G.cover));
 2161 +        free(G.cover);
 2162 +        G.cover = NULL;
 2163 +    }
 2164 +
 2165  } /* end function free_G_buffers() */
 2166  
 2167  
 2168 @@ -1890,6 +1897,8 @@ int getZip64Data(__G__ ef_buf, ef_len)
 2169  #define Z64FLGS 0xffff
 2170  #define Z64FLGL 0xffffffff
 2171  
 2172 +    G.zip64 = FALSE;
 2173 +
 2174      if (ef_len == 0 || ef_buf == NULL)
 2175          return PK_COOL;
 2176  
 2177 @@ -1927,6 +1936,8 @@ int getZip64Data(__G__ ef_buf, ef_len)
 2178  #if 0
 2179            break;                /* Expect only one EF_PKSZ64 block. */
 2180  #endif /* 0 */
 2181 +
 2182 +          G.zip64 = TRUE;
 2183          }
 2184 
 2185          /* Skip this extra field block. */
 2186 diff --git a/unzip.h b/unzip.h
 2187 index 5b2a326..ed24a5b 100644
 2188 --- a/unzip.h
 2189 +++ b/unzip.h
 2190 @@ -645,6 +645,7 @@ typedef struct _Uzp_cdir_Rec {
 2191  #define PK_NOZIP           9   /* zipfile not found */
 2192  #define PK_PARAM          10   /* bad or illegal parameters specified */
 2193  #define PK_FIND           11   /* no files found */
 2194 +#define PK_BOMB           12   /* likely zip bomb */
 2195  #define PK_DISK           50   /* disk full */
 2196  #define PK_EOF            51   /* unexpected EOF */
 2197  
 2198 From 6d351831be705cc26d897db44f878a978f4138fc Mon Sep 17 00:00:00 2001
 2199 From: Mark Adler <madler@alumni.caltech.edu>
 2200 Date: Thu, 25 Jul 2019 20:43:17 -0700
 2201 Subject: [PATCH] Do not raise a zip bomb alert for a misplaced central
 2202  directory.
 2203 
 2204 There is a zip-like file in the Firefox distribution, omni.ja,
 2205 which is a zip container with the central directory placed at the
 2206 start of the file instead of after the local entries as required
 2207 by the zip standard. This commit marks the actual location of the
 2208 central directory, as well as the end of central directory records,
 2209 as disallowed locations. This now permits such containers to not
 2210 raise a zip bomb alert, where in fact there are no overlaps.
 2211 ---
 2212  extract.c | 25 +++++++++++++++++++------
 2213  process.c |  6 ++++++
 2214  unzpriv.h | 10 ++++++++++
 2215  3 files changed, 35 insertions(+), 6 deletions(-)
 2216 
 2217 diff --git a/extract.c b/extract.c
 2218 index 0973a33..1b73cb0 100644
 2219 --- a/extract.c
 2220 +++ b/extract.c
 2221 @@ -493,8 +493,11 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2222      }
 2223  #endif /* !SFX || SFX_EXDIR */
 2224  
 2225 -    /* One more: initialize cover structure for bomb detection. Start with a
 2226 -       span that covers the central directory though the end of the file. */
 2227 +    /* One more: initialize cover structure for bomb detection. Start with
 2228 +       spans that cover any extra bytes at the start, the central directory,
 2229 +       the end of central directory record (including the Zip64 end of central
 2230 +       directory locator, if present), and the Zip64 end of central directory
 2231 +       record, if present. */
 2232      if (G.cover == NULL) {
 2233          G.cover = malloc(sizeof(cover_t));
 2234          if (G.cover == NULL) {
 2235 @@ -506,15 +509,25 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2236          ((cover_t *)G.cover)->max = 0;
 2237      }
 2238      ((cover_t *)G.cover)->num = 0;
 2239 -    if ((G.extra_bytes != 0 &&
 2240 -         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
 2241 -        cover_add((cover_t *)G.cover,
 2242 +    if (cover_add((cover_t *)G.cover,
 2243                    G.extra_bytes + G.ecrec.offset_start_central_directory,
 2244 -                  G.ziplen) != 0) {
 2245 +                  G.extra_bytes + G.ecrec.offset_start_central_directory +
 2246 +                  G.ecrec.size_central_directory) != 0) {
 2247          Info(slide, 0x401, ((char *)slide,
 2248            LoadFarString(NotEnoughMemCover)));
 2249          return PK_MEM;
 2250      }
 2251 +    if ((G.extra_bytes != 0 &&
 2252 +         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
 2253 +        (G.ecrec.have_ecr64 &&
 2254 +         cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
 2255 +                   G.ecrec.ec64_end) != 0) ||
 2256 +        cover_add((cover_t *)G.cover, G.ecrec.ec_start,
 2257 +                  G.ecrec.ec_end) != 0) {
 2258 +        Info(slide, 0x401, ((char *)slide,
 2259 +          LoadFarString(OverlappedComponents)));
 2260 +        return PK_BOMB;
 2261 +    }
 2262  
 2263  /*---------------------------------------------------------------------------
 2264      The basic idea of this function is as follows.  Since the central di-
 2265 diff --git a/process.c b/process.c
 2266 index d2e4dc3..d75d405 100644
 2267 --- a/process.c
 2268 +++ b/process.c
 2269 @@ -1408,6 +1408,10 @@ static int find_ecrec64(__G__ searchlen)         /* return PK-class error */
 2270  
 2271      /* Now, we are (almost) sure that we have a Zip64 archive. */
 2272      G.ecrec.have_ecr64 = 1;
 2273 +    G.ecrec.ec_start -= ECLOC64_SIZE+4;
 2274 +    G.ecrec.ec64_start = ecrec64_start_offset;
 2275 +    G.ecrec.ec64_end = ecrec64_start_offset +
 2276 +                       12 + makeint64(&byterec[ECREC64_LENGTH]);
 2277  
 2278      /* Update the "end-of-central-dir offset" for later checks. */
 2279      G.real_ecrec_offset = ecrec64_start_offset;
 2280 @@ -1542,6 +1546,8 @@ static int find_ecrec(__G__ searchlen)          /* return PK-class error */
 2281        makelong(&byterec[OFFSET_START_CENTRAL_DIRECTORY]);
 2282      G.ecrec.zipfile_comment_length =
 2283        makeword(&byterec[ZIPFILE_COMMENT_LENGTH]);
 2284 +    G.ecrec.ec_start = G.real_ecrec_offset;
 2285 +    G.ecrec.ec_end = G.ecrec.ec_start + 22 + G.ecrec.zipfile_comment_length;
 2286  
 2287      /* Now, we have to read the archive comment, BEFORE the file pointer
 2288         is moved away backwards to seek for a Zip64 ECLOC64 structure.
 2289 diff --git a/unzpriv.h b/unzpriv.h
 2290 index dc9eff5..297b3c7 100644
 2291 --- a/unzpriv.h
 2292 +++ b/unzpriv.h
 2293 @@ -2185,6 +2185,16 @@ typedef struct VMStimbuf {
 2294         int have_ecr64;                  /* valid Zip64 ecdir-record exists */
 2295         int is_zip64_archive;            /* Zip64 ecdir-record is mandatory */
 2296         ush zipfile_comment_length;
 2297 +       zusz_t ec_start, ec_end;         /* offsets of start and end of the
 2298 +                                           end of central directory record,
 2299 +                                           including if present the Zip64
 2300 +                                           end of central directory locator,
 2301 +                                           which immediately precedes the
 2302 +                                           end of central directory record */
 2303 +       zusz_t ec64_start, ec64_end;     /* if have_ecr64 is true, then these
 2304 +                                           are the offsets of the start and
 2305 +                                           end of the Zip64 end of central
 2306 +                                           directory record */
 2307     } ecdir_rec;
 2308  
 2309  
 2310 From 6fe72291a5563cdbcd2bdd87e36528537b7cdcfb Mon Sep 17 00:00:00 2001
 2311 From: Jakub Martisko <jamartis@redhat.com>
 2312 Date: Mon, 18 Nov 2019 14:17:46 +0100
 2313 Subject: [PATCH] update the man page
 2314 
 2315 ---
 2316  man/unzip.1 | 2 ++
 2317  1 file changed, 2 insertions(+)
 2318 
 2319 diff --git a/man/unzip.1 b/man/unzip.1
 2320 index 21816d1..4d66073 100644
 2321 --- a/man/unzip.1
 2322 +++ b/man/unzip.1
 2323 @@ -850,6 +850,8 @@ the specified zipfiles were not found.
 2324  invalid options were specified on the command line.
 2325  .IP 11
 2326  no matching files were found.
 2327 +.IP 12
 2328 +invalid zip file with overlapped components (possible zip-bomb). The zip-bomb checks can be disabled by using the UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE environment variable.
 2329  .IP 50
 2330  the disk is (or was) full during extraction.
 2331  .IP 51
 2332 -- 
 2333 2.23.0
 2334 
 2335 From 5e2efcd633a4a1fb95a129a75508e7d769e767be Mon Sep 17 00:00:00 2001
 2336 From: Mark Adler <madler@alumni.caltech.edu>
 2337 Date: Sun, 9 Feb 2020 20:36:28 -0800
 2338 Subject: [PATCH] Fix bug in UZbunzip2() that incorrectly updated G.incnt.
 2339 
 2340 The update assumed a full buffer, which is not always full. This
 2341 could result in a false overlapped element detection when a small
 2342 bzip2-compressed file was unzipped. This commit remedies that.
 2343 ---
 2344  extract.c | 2 +-
 2345  1 file changed, 1 insertion(+), 1 deletion(-)
 2346 
 2347 diff --git a/extract.c b/extract.c
 2348 index d9866f9..0cb7bfc 100644
 2349 --- a/extract.c
 2350 +++ b/extract.c
 2351 @@ -3010,7 +3010,7 @@ __GDEF
 2352  #endif
 2353  
 2354      G.inptr = (uch *)bstrm.next_in;
 2355 -    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
 2356 +    G.incnt -= G.inptr - G.inbuf;       /* reset for other routines */
 2357  
 2358  uzbunzip_cleanup_exit:
 2359      err = BZ2_bzDecompressEnd(&bstrm);
 2360 From 5c572555cf5d80309a07c30cf7a54b2501493720 Mon Sep 17 00:00:00 2001
 2361 From: Mark Adler <madler@alumni.caltech.edu>
 2362 Date: Sun, 9 Feb 2020 21:39:09 -0800
 2363 Subject: [PATCH] Fix bug in UZinflate() that incorrectly updated G.incnt.
 2364 
 2365 The update assumed a full buffer, which is not always full. This
 2366 could result in a false overlapped element detection when a small
 2367 deflate-compressed file was unzipped using an old zlib. This
 2368 commit remedies that.
 2369 ---
 2370  inflate.c | 2 +-
 2371  1 file changed, 1 insertion(+), 1 deletion(-)
 2372 
 2373 diff --git a/inflate.c b/inflate.c
 2374 index 2f5a015..70e3cc0 100644
 2375 --- a/inflate.c
 2376 +++ b/inflate.c
 2377 @@ -700,7 +700,7 @@ int UZinflate(__G__ is_defl64)
 2378        G.dstrm.total_out));
 2379  
 2380      G.inptr = (uch *)G.dstrm.next_in;
 2381 -    G.incnt = (G.inbuf + INBUFSIZ) - G.inptr;  /* reset for other routines */
 2382 +    G.incnt -= G.inptr - G.inbuf;       /* reset for other routines */
 2383  
 2384  uzinflate_cleanup_exit:
 2385      err = inflateReset(&G.dstrm);
 2386 From 122050bac16fae82a460ff739fb1ca0f106e9d85 Mon Sep 17 00:00:00 2001
 2387 From: Mark Adler <madler@alumni.caltech.edu>
 2388 Date: Sat, 2 Jan 2021 13:09:34 -0800
 2389 Subject: [PATCH] Determine Zip64 status entry-by-entry instead of for entire
 2390  file.
 2391 
 2392 Fixes a bug for zip files with mixed Zip64 and not Zip64 entries,
 2393 which resulted in an incorrect data descriptor length. The bug is
 2394 seen when a Zip64 entry precedes a non-Zip64 entry, in which case
 2395 the data descriptor would have been assumed to be larger than it
 2396 is, resulting in an incorrect bomb warning due to a perceived
 2397 overlap with the next entry. This commit determines and saves the
 2398 Zip64 status for each entry based on the central directory, and
 2399 then computes the length of each data descriptor accordingly.
 2400 ---
 2401  extract.c | 5 +++--
 2402  globals.h | 2 --
 2403  process.c | 4 +---
 2404  unzpriv.h | 1 +
 2405  4 files changed, 5 insertions(+), 7 deletions(-)
 2406 
 2407 diff --git a/extract.c b/extract.c
 2408 index 504afd6..878817d 100644
 2409 --- a/extract.c
 2410 +++ b/extract.c
 2411 @@ -658,6 +658,7 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2412                      break;
 2413                  }
 2414              }
 2415 +            G.pInfo->zip64 = FALSE;
 2416              if ((error = do_string(__G__ G.crec.extra_field_length,
 2417                  EXTRA_FIELD)) != 0)
 2418              {
 2419 @@ -2187,12 +2188,12 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
 2420               (clen == SIG &&                    /* if not SIG, no signature */
 2421                ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
 2422                 (ulen == SIG &&                  /* if not SIG, no signature */
 2423 -                (G.zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
 2424 +                (G.pInfo->zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
 2425                                                  /* if not SIG, have signature */
 2426                  )))))
 2427                     /* skip four more bytes to account for signature */
 2428                     shy += 4 - readbuf((char *)buf, 4);
 2429 -        if (G.zip64)
 2430 +        if (G.pInfo->zip64)
 2431              shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
 2432          if (shy)
 2433              error = PK_ERR;
 2434 diff --git a/globals.h b/globals.h
 2435 index f9c6daf..a883c90 100644
 2436 --- a/globals.h
 2437 +++ b/globals.h
 2438 @@ -261,8 +261,6 @@ typedef struct Globals {
 2439      ecdir_rec       ecrec;         /* used in unzip.c, extract.c */
 2440      z_stat   statbuf;              /* used by main, mapname, check_for_newer */
 2441  
 2442 -    int zip64;                     /* true if Zip64 info in extra field */
 2443 -
 2444      int      mem_mode;
 2445      uch      *outbufptr;           /* extract.c static */
 2446      ulg      outsize;              /* extract.c static */
 2447 diff --git a/process.c b/process.c
 2448 index d75d405..d643c6f 100644
 2449 --- a/process.c
 2450 +++ b/process.c
 2451 @@ -1903,8 +1903,6 @@ int getZip64Data(__G__ ef_buf, ef_len)
 2452  #define Z64FLGS 0xffff
 2453  #define Z64FLGL 0xffffffff
 2454  
 2455 -    G.zip64 = FALSE;
 2456 -
 2457      if (ef_len == 0 || ef_buf == NULL)
 2458          return PK_COOL;
 2459  
 2460 @@ -1943,7 +1941,7 @@ int getZip64Data(__G__ ef_buf, ef_len)
 2461            break;                /* Expect only one EF_PKSZ64 block. */
 2462  #endif /* 0 */
 2463  
 2464 -          G.zip64 = TRUE;
 2465 +          G.pInfo->zip64 = TRUE;
 2466          }
 2467  
 2468          /* Skip this extra field block. */
 2469 diff --git a/unzpriv.h b/unzpriv.h
 2470 index 09f288e..75b3359 100644
 2471 --- a/unzpriv.h
 2472 +++ b/unzpriv.h
 2473 @@ -2034,6 +2034,7 @@ typedef struct min_info {
 2474  #ifdef UNICODE_SUPPORT
 2475      unsigned GPFIsUTF8: 1;   /* crec gen_purpose_flag UTF-8 bit 11 is set */
 2476  #endif
 2477 +    unsigned zip64: 1;       /* true if entry has Zip64 extra block */
 2478  #ifndef SFX
 2479      char Far *cfilname;      /* central header version of filename */
 2480  #endif
 2481 From 5b44c818b96193b3e240f38f61985fa2bc780eb7 Mon Sep 17 00:00:00 2001
 2482 From: Jakub Martisko <jamartis@redhat.com>
 2483 Date: Tue, 30 Nov 2021 15:42:17 +0100
 2484 Subject: [PATCH] Add an option to disable the zipbomb detection
 2485 
 2486 This can be done by settting a newly introduced environment variable
 2487 UNZIP_DISABLE_ZIPBOMB_DETECTION to {TRUE,True,true}. If the variable is unset, or
 2488 set to any other value the zipbomb detection is left enabled.
 2489 
 2490 Example:
 2491 	UNZIP_DISABLE_ZIPBOMB_DETECTION=True unzip ./zbsm.zip -d ./test
 2492 ---
 2493  extract.c | 85 ++++++++++++++++++++++++++++++-------------------------
 2494  unzip.c   | 15 ++++++++--
 2495  unzip.h   |  1 +
 2496  3 files changed, 60 insertions(+), 41 deletions(-)
 2497 
 2498 diff --git a/extract.c b/extract.c
 2499 index 878817d..3e58071 100644
 2500 --- a/extract.c
 2501 +++ b/extract.c
 2502 @@ -322,7 +322,8 @@ static ZCONST char Far BadExtraFieldCRC[] =
 2503  static ZCONST char Far NotEnoughMemCover[] =
 2504    "error: not enough memory for bomb detection\n";
 2505  static ZCONST char Far OverlappedComponents[] =
 2506 -  "error: invalid zip file with overlapped components (possible zip bomb)\n";
 2507 +  "error: invalid zip file with overlapped components (possible zip bomb)\n \
 2508 +To unzip the file anyway, rerun the command with UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE environmnent variable\n";
 2509  
 2510  
 2511  
 2512 @@ -502,35 +503,37 @@ int extract_or_test_files(__G)    /* return PK-type error code */
 2513         the end of central directory record (including the Zip64 end of central
 2514         directory locator, if present), and the Zip64 end of central directory
 2515         record, if present. */
 2516 -    if (G.cover == NULL) {
 2517 +    if (uO.zipbomb == TRUE) {
 2518 +      if (G.cover == NULL) {
 2519          G.cover = malloc(sizeof(cover_t));
 2520          if (G.cover == NULL) {
 2521 -            Info(slide, 0x401, ((char *)slide,
 2522 -              LoadFarString(NotEnoughMemCover)));
 2523 -            return PK_MEM;
 2524 +            Info(slide, 0x401, ((char *)slide,
 2525 +              LoadFarString(NotEnoughMemCover)));
 2526 +            return PK_MEM;
 2527          }
 2528          ((cover_t *)G.cover)->span = NULL;
 2529          ((cover_t *)G.cover)->max = 0;
 2530 -    }
 2531 -    ((cover_t *)G.cover)->num = 0;
 2532 -    if (cover_add((cover_t *)G.cover,
 2533 -                  G.extra_bytes + G.ecrec.offset_start_central_directory,
 2534 -                  G.extra_bytes + G.ecrec.offset_start_central_directory +
 2535 -                  G.ecrec.size_central_directory) != 0) {
 2536 +    }
 2537 +    ((cover_t *)G.cover)->num = 0;
 2538 +    if (cover_add((cover_t *)G.cover,
 2539 +                  G.extra_bytes + G.ecrec.offset_start_central_directory,
 2540 +                  G.extra_bytes + G.ecrec.offset_start_central_directory +
 2541 +                  G.ecrec.size_central_directory) != 0) {
 2542          Info(slide, 0x401, ((char *)slide,
 2543 -          LoadFarString(NotEnoughMemCover)));
 2544 +          LoadFarString(NotEnoughMemCover)));
 2545          return PK_MEM;
 2546 -    }
 2547 -    if ((G.extra_bytes != 0 &&
 2548 -         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
 2549 -        (G.ecrec.have_ecr64 &&
 2550 -         cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
 2551 -                   G.ecrec.ec64_end) != 0) ||
 2552 -        cover_add((cover_t *)G.cover, G.ecrec.ec_start,
 2553 -                  G.ecrec.ec_end) != 0) {
 2554 +    }
 2555 +    if ((G.extra_bytes != 0 &&
 2556 +         cover_add((cover_t *)G.cover, 0, G.extra_bytes) != 0) ||
 2557 +        (G.ecrec.have_ecr64 &&
 2558 +         cover_add((cover_t *)G.cover, G.ecrec.ec64_start,
 2559 +                   G.ecrec.ec64_end) != 0) ||
 2560 +        cover_add((cover_t *)G.cover, G.ecrec.ec_start,
 2561 +                  G.ecrec.ec_end) != 0) {
 2562          Info(slide, 0x401, ((char *)slide,
 2563 -          LoadFarString(OverlappedComponents)));
 2564 +          LoadFarString(OverlappedComponents)));
 2565          return PK_BOMB;
 2566 +      }
 2567      }
 2568  
 2569  /*---------------------------------------------------------------------------
 2570 @@ -1222,10 +1225,12 @@ static int extract_or_test_entrylist(__G__ numchunk,
 2571  
 2572          /* seek_zipf(__G__ pInfo->offset);  */
 2573          request = G.pInfo->offset + G.extra_bytes;
 2574 -        if (cover_within((cover_t *)G.cover, request)) {
 2575 +        if (uO.zipbomb == TRUE) {
 2576 +          if (cover_within((cover_t *)G.cover, request)) {
 2577              Info(slide, 0x401, ((char *)slide,
 2578 -              LoadFarString(OverlappedComponents)));
 2579 +              LoadFarString(OverlappedComponents)));
 2580              return PK_BOMB;
 2581 +          }
 2582          }
 2583          inbuf_offset = request % INBUFSIZ;
 2584          bufstart = request - inbuf_offset;
 2585 @@ -1758,17 +1763,19 @@ reprompt:
 2586              return IZ_CTRLC;        /* cancel operation by user request */
 2587          }
 2588  #endif
 2589 -        error = cover_add((cover_t *)G.cover, request,
 2590 -                          G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
 2591 -        if (error < 0) {
 2592 +        if (uO.zipbomb == TRUE) {
 2593 +          error = cover_add((cover_t *)G.cover, request,
 2594 +                            G.cur_zipfile_bufstart + (G.inptr - G.inbuf));
 2595 +          if (error < 0) {
 2596              Info(slide, 0x401, ((char *)slide,
 2597 -              LoadFarString(NotEnoughMemCover)));
 2598 +                                LoadFarString(NotEnoughMemCover)));
 2599              return PK_MEM;
 2600 -        }
 2601 -        if (error != 0) {
 2602 +          }
 2603 +          if (error != 0) {
 2604              Info(slide, 0x401, ((char *)slide,
 2605 -              LoadFarString(OverlappedComponents)));
 2606 +                                LoadFarString(OverlappedComponents)));
 2607              return PK_BOMB;
 2608 +          }
 2609          }
 2610  #ifdef MACOS  /* MacOS is no preemptive OS, thus call event-handling by hand */
 2611          UserStop();
 2612 @@ -2171,8 +2178,8 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
 2613      }
 2614  
 2615      undefer_input(__G);
 2616 -
 2617 -    if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
 2618 +    if (uO.zipbomb == TRUE) {
 2619 +      if ((G.lrec.general_purpose_bit_flag & 8) != 0) {
 2620          /* skip over data descriptor (harder than it sounds, due to signature
 2621           * ambiguity)
 2622           */
 2623 @@ -2189,16 +2196,16 @@ static int extract_or_test_member(__G)    /* return PK-type error code */
 2624                ((G.lrec.csize & LOW) != SIG ||   /* if not SIG, have signature */
 2625                 (ulen == SIG &&                  /* if not SIG, no signature */
 2626                  (G.pInfo->zip64 ? G.lrec.csize >> 32 : G.lrec.ucsize) != SIG
 2627 -                                                /* if not SIG, have signature */
 2628 +                /* if not SIG, have signature */
 2629                  )))))
 2630 -                   /* skip four more bytes to account for signature */
 2631 -                   shy += 4 - readbuf((char *)buf, 4);
 2632 +          /* skip four more bytes to account for signature */
 2633 +          shy += 4 - readbuf((char *)buf, 4);
 2634          if (G.pInfo->zip64)
 2635 -            shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
 2636 +          shy += 8 - readbuf((char *)buf, 8); /* skip eight more for ZIP64 */
 2637          if (shy)
 2638 -            error = PK_ERR;
 2639 +          error = PK_ERR;
 2640 +      }
 2641      }
 2642 -
 2643      return error;
 2644  
 2645  } /* end function extract_or_test_member() */
 2646 diff --git a/unzip.c b/unzip.c
 2647 index 8dbfc95..abb3644 100644
 2648 --- a/unzip.c
 2649 +++ b/unzip.c
 2650 @@ -1329,10 +1329,9 @@ int uz_opts(__G__ pargc, pargv)
 2651      int *pargc;
 2652      char ***pargv;
 2653  {
 2654 -    char **argv, *s;
 2655 +    char **argv, *s, *zipbomb_envar;
 2656      int argc, c, error=FALSE, negative=0, showhelp=0;
 2657  
 2658 -
 2659      argc = *pargc;
 2660      argv = *pargv;
 2661  
 2662 @@ -1923,6 +1922,18 @@ opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
 2663      else
 2664          G.extract_flag = TRUE;
 2665  
 2666 +    /* Disable the zipbomb detection, this is the only option set only via the shell variables but it should at least not clash with something in the future. */
 2667 +    zipbomb_envar = getenv("UNZIP_DISABLE_ZIPBOMB_DETECTION");
 2668 +    uO.zipbomb = TRUE;
 2669 +    if (zipbomb_envar != NULL) {
 2670 +      /* strcasecmp might be a better approach here but it is POSIX-only */
 2671 +      if ((strcmp ("TRUE", zipbomb_envar) == 0)
 2672 +       || (strcmp ("True", zipbomb_envar) == 0)
 2673 +       || (strcmp ("true",zipbomb_envar) == 0)) {
 2674 +        uO.zipbomb = FALSE;
 2675 +      }
 2676 +    }
 2677 +
 2678      *pargc = argc;
 2679      *pargv = argv;
 2680      return PK_OK;
 2681 diff --git a/unzip.h b/unzip.h
 2682 index ed24a5b..e7665e8 100644
 2683 --- a/unzip.h
 2684 +++ b/unzip.h
 2685 @@ -559,6 +559,7 @@ typedef struct _UzpOpts {
 2686  #ifdef UNIX
 2687      int cflxflag;       /* -^: allow control chars in extracted filenames */
 2688  #endif
 2689 +  int zipbomb;
 2690  #endif /* !FUNZIP */
 2691  } UzpOpts;
 2692  
 2693 -- 
 2694 2.33.0
 2695 
 2696 diff --git a/process.c b/process.c
 2697 index d2a846e..cba2463 100644
 2698 --- a/process.c
 2699 +++ b/process.c
 2700 @@ -2064,10 +2064,14 @@ int getUnicodeData(__G__ ef_buf, ef_len)
 2701            G.unipath_checksum = makelong(offset + ef_buf);
 2702            offset += 4;
 2703  
 2704 +          if (!G.filename_full) {
 2705 +            /* Check if we have a unicode extra section but no filename set */
 2706 +            return PK_ERR;
 2707 +          }
 2708 +
 2709            /*
 2710             * Compute 32-bit crc
 2711             */
 2712 -
 2713            chksum = crc32(chksum, (uch *)(G.filename_full),
 2714                           strlen(G.filename_full));

Generated by cgit