jdk/src/share/native/java/util/zip/zip_util.c
changeset 3078 c491f0d2a8aa
parent 2592 ef26f663a2ba
child 5148 2bf5469864ea
equal deleted inserted replaced
3074:057d906ae701 3078:c491f0d2a8aa
   254 #ifdef USE_MMAP
   254 #ifdef USE_MMAP
   255     if (zip->maddr != NULL) munmap((char *)zip->maddr, zip->mlen);
   255     if (zip->maddr != NULL) munmap((char *)zip->maddr, zip->mlen);
   256 #else
   256 #else
   257     free(zip->cencache.data);
   257     free(zip->cencache.data);
   258 #endif
   258 #endif
       
   259     if (zip->comment != NULL)
       
   260         free(zip->comment);
   259     if (zip->zfd != -1) ZFILE_Close(zip->zfd);
   261     if (zip->zfd != -1) ZFILE_Close(zip->zfd);
   260     free(zip);
   262     free(zip);
   261 }
   263 }
   262 
   264 
   263 /* The END header is followed by a variable length comment of size < 64k. */
   265 /* The END header is followed by a variable length comment of size < 64k. */
   264 static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
   266 static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
   265 
   267 
   266 #define READBLOCKSZ 128
   268 #define READBLOCKSZ 128
       
   269 
       
   270 static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
       
   271     /* ENDSIG matched, however the size of file comment in it does not
       
   272        match the real size. One "common" cause for this problem is some
       
   273        "extra" bytes are padded at the end of the zipfile.
       
   274        Let's do some extra verification, we don't care about the performance
       
   275        in this situation.
       
   276      */
       
   277     jlong cenpos = endpos - ENDSIZ(endbuf);
       
   278     jlong locpos = cenpos - ENDOFF(endbuf);
       
   279     char buf[4];
       
   280     return (cenpos >= 0 &&
       
   281             locpos >= 0 &&
       
   282             readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 &&
       
   283             GETSIG(buf) == CENSIG &&
       
   284             readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 &&
       
   285             GETSIG(buf) == LOCSIG);
       
   286 }
   267 
   287 
   268 /*
   288 /*
   269  * Searches for end of central directory (END) header. The contents of
   289  * Searches for end of central directory (END) header. The contents of
   270  * the END header will be read and placed in endbuf. Returns the file
   290  * the END header will be read and placed in endbuf. Returns the file
   271  * position of the END header, otherwise returns -1 if the END header
   291  * position of the END header, otherwise returns -1 if the END header
   278     jlong pos;
   298     jlong pos;
   279     const jlong len = zip->len;
   299     const jlong len = zip->len;
   280     const ZFILE zfd = zip->zfd;
   300     const ZFILE zfd = zip->zfd;
   281     const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
   301     const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
   282     const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
   302     const jlong minPos = minHDR - (sizeof(buf)-ENDHDR);
       
   303     jint clen;
   283 
   304 
   284     for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
   305     for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR)) {
   285 
   306 
   286         int i;
   307         int i;
   287         jlong off = 0;
   308         jlong off = 0;
   300         for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
   321         for (i = sizeof(buf) - ENDHDR; i >= 0; i--) {
   301             if (buf[i+0] == 'P'    &&
   322             if (buf[i+0] == 'P'    &&
   302                 buf[i+1] == 'K'    &&
   323                 buf[i+1] == 'K'    &&
   303                 buf[i+2] == '\005' &&
   324                 buf[i+2] == '\005' &&
   304                 buf[i+3] == '\006' &&
   325                 buf[i+3] == '\006' &&
   305                 (pos + i + ENDHDR + ENDCOM(buf + i) == len)) {
   326                 ((pos + i + ENDHDR + ENDCOM(buf + i) == len)
   306                     /* Found END header */
   327                  || verifyEND(zip, pos + i, buf + i))) {
   307                     memcpy(endbuf, buf + i, ENDHDR);
   328                 /* Found END header */
   308                     return pos + i;
   329                 memcpy(endbuf, buf + i, ENDHDR);
       
   330 
       
   331                 clen = ENDCOM(endbuf);
       
   332                 if (clen != 0) {
       
   333                     zip->comment = malloc(clen + 1);
       
   334                     if (zip->comment == NULL) {
       
   335                         return -1;
       
   336                     }
       
   337                     if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR)
       
   338                         == -1) {
       
   339                         free(zip->comment);
       
   340                         zip->comment = NULL;
       
   341                         return -1;
       
   342                     }
       
   343                     zip->comment[clen] = '\0';
       
   344                     zip->clen = clen;
       
   345                 }
       
   346                 return pos + i;
   309             }
   347             }
   310         }
   348         }
   311     }
   349     }
       
   350 
   312     return -1; /* END header not found */
   351     return -1; /* END header not found */
   313 }
   352 }
   314 
   353 
   315 /*
   354 /*
   316  * Searches for the ZIP64 end of central directory (END) header. The
   355  * Searches for the ZIP64 end of central directory (END) header. The
   652     }
   691     }
   653     if (cp != cenend)
   692     if (cp != cenend)
   654         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
   693         ZIP_FORMAT_ERROR("invalid CEN header (bad header size)");
   655 
   694 
   656     zip->total = i;
   695     zip->total = i;
   657 
       
   658     goto Finally;
   696     goto Finally;
   659 
   697 
   660  Catch:
   698  Catch:
   661     freeCEN(zip);
   699     freeCEN(zip);
   662     cenpos = -1;
   700     cenpos = -1;