"Fossies" - the Fresh Open Source Software Archive

Member "src/Common/libzip/zip_open.c" (10 Oct 2018, 23587 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "zip_open.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.21_Source_vs_1.22_Source.

    1 /*
    2   zip_open.c -- open zip archive by name
    3   Copyright (C) 1999-2017 Dieter Baron and Thomas Klausner
    4 
    5   This file is part of libzip, a library to manipulate ZIP archives.
    6   The authors can be contacted at <libzip@nih.at>
    7 
    8   Redistribution and use in source and binary forms, with or without
    9   modification, are permitted provided that the following conditions
   10   are met:
   11   1. Redistributions of source code must retain the above copyright
   12      notice, this list of conditions and the following disclaimer.
   13   2. Redistributions in binary form must reproduce the above copyright
   14      notice, this list of conditions and the following disclaimer in
   15      the documentation and/or other materials provided with the
   16      distribution.
   17   3. The names of the authors may not be used to endorse or promote
   18      products derived from this software without specific prior
   19      written permission.
   20 
   21   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
   22   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   23   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
   25   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   27   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   29   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   30   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
   31   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32 */
   33 
   34 
   35 #include <limits.h>
   36 #include <stdio.h>
   37 #include <stdlib.h>
   38 #include <string.h>
   39 #include <sys/stat.h>
   40 
   41 #include "zipint.h"
   42 
   43 typedef enum {
   44     EXISTS_ERROR = -1,
   45     EXISTS_NOT = 0,
   46     EXISTS_EMPTY,
   47     EXISTS_NONEMPTY,
   48 } exists_t;
   49 static zip_t *_zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error);
   50 static zip_int64_t _zip_checkcons(zip_t *za, zip_cdir_t *cdir, zip_error_t *error);
   51 static zip_cdir_t *_zip_find_central_dir(zip_t *za, zip_uint64_t len);
   52 static exists_t _zip_file_exists(zip_source_t *src, zip_error_t *error);
   53 static int _zip_headercomp(const zip_dirent_t *, const zip_dirent_t *);
   54 static unsigned char *_zip_memmem(const unsigned char *, size_t, const unsigned char *, size_t);
   55 static zip_cdir_t *_zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error);
   56 static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
   57 static zip_cdir_t *_zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error);
   58 
   59 
   60 ZIP_EXTERN zip_t *
   61 zip_open(const char *fn, int _flags, int *zep) {
   62     zip_t *za;
   63     zip_source_t *src;
   64     struct zip_error error;
   65 
   66     zip_error_init(&error);
   67     if ((src = zip_source_file_create(fn, 0, -1, &error)) == NULL) {
   68     _zip_set_open_error(zep, &error, 0);
   69     zip_error_fini(&error);
   70     return NULL;
   71     }
   72 
   73     if ((za = zip_open_from_source(src, _flags, &error)) == NULL) {
   74     zip_source_free(src);
   75     _zip_set_open_error(zep, &error, 0);
   76     zip_error_fini(&error);
   77     return NULL;
   78     }
   79 
   80     zip_error_fini(&error);
   81     return za;
   82 }
   83 
   84 
   85 ZIP_EXTERN zip_t *
   86 zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error) {
   87     static zip_int64_t needed_support_read = -1;
   88     static zip_int64_t needed_support_write = -1;
   89 
   90     unsigned int flags;
   91     zip_int64_t supported;
   92     exists_t exists;
   93 
   94     if (_flags < 0 || src == NULL) {
   95     zip_error_set(error, ZIP_ER_INVAL, 0);
   96     return NULL;
   97     }
   98     flags = (unsigned int)_flags;
   99 
  100     supported = zip_source_supports(src);
  101     if (needed_support_read == -1) {
  102     needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
  103     needed_support_write = zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
  104     }
  105     if ((supported & needed_support_read) != needed_support_read) {
  106     zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
  107     return NULL;
  108     }
  109     if ((supported & needed_support_write) != needed_support_write) {
  110     flags |= ZIP_RDONLY;
  111     }
  112 
  113     if ((flags & (ZIP_RDONLY | ZIP_TRUNCATE)) == (ZIP_RDONLY | ZIP_TRUNCATE)) {
  114     zip_error_set(error, ZIP_ER_RDONLY, 0);
  115     return NULL;
  116     }
  117 
  118     exists = _zip_file_exists(src, error);
  119     switch (exists) {
  120     case EXISTS_ERROR:
  121     return NULL;
  122 
  123     case EXISTS_NOT:
  124     if ((flags & ZIP_CREATE) == 0) {
  125         zip_error_set(error, ZIP_ER_NOENT, 0);
  126         return NULL;
  127     }
  128     return _zip_allocate_new(src, flags, error);
  129 
  130     default: {
  131     zip_t *za;
  132     if (flags & ZIP_EXCL) {
  133         zip_error_set(error, ZIP_ER_EXISTS, 0);
  134         return NULL;
  135     }
  136     if (zip_source_open(src) < 0) {
  137         _zip_error_set_from_source(error, src);
  138         return NULL;
  139     }
  140 
  141     if (flags & ZIP_TRUNCATE) {
  142         za = _zip_allocate_new(src, flags, error);
  143     }
  144     else {
  145         /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
  146         za = _zip_open(src, flags, error);
  147     }
  148 
  149     if (za == NULL) {
  150         zip_source_close(src);
  151         return NULL;
  152     }
  153     return za;
  154     }
  155     }
  156 }
  157 
  158 
  159 zip_t *
  160 _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) {
  161     zip_t *za;
  162     zip_cdir_t *cdir;
  163     struct zip_stat st;
  164     zip_uint64_t len, idx;
  165 
  166     zip_stat_init(&st);
  167     if (zip_source_stat(src, &st) < 0) {
  168     _zip_error_set_from_source(error, src);
  169     return NULL;
  170     }
  171     if ((st.valid & ZIP_STAT_SIZE) == 0) {
  172     zip_error_set(error, ZIP_ER_SEEK, EOPNOTSUPP);
  173     return NULL;
  174     }
  175     len = st.size;
  176 
  177     /* treat empty files as empty archives */
  178     if (len == 0) {
  179     if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
  180         zip_source_free(src);
  181         return NULL;
  182     }
  183 
  184     return za;
  185     }
  186 
  187     if ((za = _zip_allocate_new(src, flags, error)) == NULL) {
  188     return NULL;
  189     }
  190 
  191     if ((cdir = _zip_find_central_dir(za, len)) == NULL) {
  192     _zip_error_copy(error, &za->error);
  193     /* keep src so discard does not get rid of it */
  194     zip_source_keep(src);
  195     zip_discard(za);
  196     return NULL;
  197     }
  198 
  199     za->entry = cdir->entry;
  200     za->nentry = cdir->nentry;
  201     za->nentry_alloc = cdir->nentry_alloc;
  202     za->comment_orig = cdir->comment;
  203 
  204     free(cdir);
  205 
  206     _zip_hash_reserve_capacity(za->names, za->nentry, &za->error);
  207 
  208     for (idx = 0; idx < za->nentry; idx++) {
  209     const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
  210     if (name == NULL) {
  211         /* keep src so discard does not get rid of it */
  212         zip_source_keep(src);
  213         zip_discard(za);
  214         return NULL;
  215     }
  216 
  217     if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
  218         if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
  219         _zip_error_copy(error, &za->error);
  220         /* keep src so discard does not get rid of it */
  221         zip_source_keep(src);
  222         zip_discard(za);
  223         return NULL;
  224         }
  225     }
  226     }
  227 
  228     za->ch_flags = za->flags;
  229 
  230     return za;
  231 }
  232 
  233 
  234 void
  235 _zip_set_open_error(int *zep, const zip_error_t *err, int ze) {
  236     if (err) {
  237     ze = zip_error_code_zip(err);
  238     if (zip_error_system_type(err) == ZIP_ET_SYS) {
  239         errno = zip_error_code_system(err);
  240     }
  241     }
  242 
  243     if (zep)
  244     *zep = ze;
  245 }
  246 
  247 
  248 /* _zip_readcdir:
  249    tries to find a valid end-of-central-directory at the beginning of
  250    buf, and then the corresponding central directory entries.
  251    Returns a struct zip_cdir which contains the central directory
  252    entries, or NULL if unsuccessful. */
  253 
  254 static zip_cdir_t *
  255 _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_error_t *error) {
  256     zip_cdir_t *cd;
  257     zip_uint16_t comment_len;
  258     zip_uint64_t i, left;
  259     zip_uint64_t eocd_offset = _zip_buffer_offset(buffer);
  260     zip_buffer_t *cd_buffer;
  261 
  262     if (_zip_buffer_left(buffer) < EOCDLEN) {
  263     /* not enough bytes left for comment */
  264     zip_error_set(error, ZIP_ER_NOZIP, 0);
  265     return NULL;
  266     }
  267 
  268     /* check for end-of-central-dir magic */
  269     if (memcmp(_zip_buffer_get(buffer, 4), EOCD_MAGIC, 4) != 0) {
  270     zip_error_set(error, ZIP_ER_NOZIP, 0);
  271     return NULL;
  272     }
  273 
  274     if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
  275     _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
  276     cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
  277     }
  278     else {
  279     _zip_buffer_set_offset(buffer, eocd_offset);
  280     cd = _zip_read_eocd(buffer, buf_offset, za->flags, error);
  281     }
  282 
  283     if (cd == NULL)
  284     return NULL;
  285 
  286     _zip_buffer_set_offset(buffer, eocd_offset + 20);
  287     comment_len = _zip_buffer_get_16(buffer);
  288 
  289     if (cd->offset + cd->size > buf_offset + eocd_offset) {
  290     /* cdir spans past EOCD record */
  291     zip_error_set(error, ZIP_ER_INCONS, 0);
  292     _zip_cdir_free(cd);
  293     return NULL;
  294     }
  295 
  296     if (comment_len || (za->open_flags & ZIP_CHECKCONS)) {
  297     zip_uint64_t tail_len;
  298 
  299     _zip_buffer_set_offset(buffer, eocd_offset + EOCDLEN);
  300     tail_len = _zip_buffer_left(buffer);
  301 
  302     if (tail_len < comment_len || ((za->open_flags & ZIP_CHECKCONS) && tail_len != comment_len)) {
  303         zip_error_set(error, ZIP_ER_INCONS, 0);
  304         _zip_cdir_free(cd);
  305         return NULL;
  306     }
  307 
  308     if (comment_len) {
  309         if ((cd->comment = _zip_string_new(_zip_buffer_get(buffer, comment_len), comment_len, ZIP_FL_ENC_GUESS, error)) == NULL) {
  310         _zip_cdir_free(cd);
  311         return NULL;
  312         }
  313     }
  314     }
  315 
  316     if (cd->offset >= buf_offset) {
  317     zip_uint8_t *data;
  318     /* if buffer already read in, use it */
  319     _zip_buffer_set_offset(buffer, cd->offset - buf_offset);
  320 
  321     if ((data = _zip_buffer_get(buffer, cd->size)) == NULL) {
  322         zip_error_set(error, ZIP_ER_INCONS, 0);
  323         _zip_cdir_free(cd);
  324         return NULL;
  325     }
  326     if ((cd_buffer = _zip_buffer_new(data, cd->size)) == NULL) {
  327         zip_error_set(error, ZIP_ER_MEMORY, 0);
  328         _zip_cdir_free(cd);
  329         return NULL;
  330     }
  331     }
  332     else {
  333     cd_buffer = NULL;
  334 
  335     if (zip_source_seek(za->src, (zip_int64_t)cd->offset, SEEK_SET) < 0) {
  336         _zip_error_set_from_source(error, za->src);
  337         _zip_cdir_free(cd);
  338         return NULL;
  339     }
  340 
  341     /* possible consistency check: cd->offset = len-(cd->size+cd->comment_len+EOCDLEN) ? */
  342     if (zip_source_tell(za->src) != (zip_int64_t)cd->offset) {
  343         zip_error_set(error, ZIP_ER_NOZIP, 0);
  344         _zip_cdir_free(cd);
  345         return NULL;
  346     }
  347     }
  348 
  349     left = (zip_uint64_t)cd->size;
  350     i = 0;
  351     while (left > 0) {
  352     bool grown = false;
  353     zip_int64_t entry_size;
  354 
  355     if (i == cd->nentry) {
  356         /* InfoZIP has a hack to avoid using Zip64: it stores nentries % 0x10000 */
  357         /* This hack isn't applicable if we're using Zip64, or if there is no central directory entry following. */
  358 
  359         if (cd->is_zip64 || left < CDENTRYSIZE) {
  360         break;
  361         }
  362 
  363         if (!_zip_cdir_grow(cd, 0x10000, error)) {
  364         _zip_cdir_free(cd);
  365         _zip_buffer_free(cd_buffer);
  366         return NULL;
  367         }
  368         grown = true;
  369     }
  370 
  371     if ((cd->entry[i].orig = _zip_dirent_new()) == NULL || (entry_size = _zip_dirent_read(cd->entry[i].orig, za->src, cd_buffer, false, error)) < 0) {
  372         if (grown && zip_error_code_zip(error) == ZIP_ER_NOZIP) {
  373         zip_error_set(error, ZIP_ER_INCONS, 0);
  374         }
  375         _zip_cdir_free(cd);
  376         _zip_buffer_free(cd_buffer);
  377         return NULL;
  378     }
  379     i++;
  380     left -= (zip_uint64_t)entry_size;
  381     }
  382 
  383     if (i != cd->nentry || left > 0) {
  384     zip_error_set(error, ZIP_ER_INCONS, 0);
  385     _zip_buffer_free(cd_buffer);
  386     _zip_cdir_free(cd);
  387     return NULL;
  388     }
  389 
  390     if (za->open_flags & ZIP_CHECKCONS) {
  391     bool ok;
  392 
  393     if (cd_buffer) {
  394         ok = _zip_buffer_eof(cd_buffer);
  395     }
  396     else {
  397         zip_int64_t offset = zip_source_tell(za->src);
  398 
  399         if (offset < 0) {
  400         _zip_error_set_from_source(error, za->src);
  401         _zip_cdir_free(cd);
  402         return NULL;
  403         }
  404         ok = ((zip_uint64_t)offset == cd->offset + cd->size);
  405     }
  406 
  407     if (!ok) {
  408         zip_error_set(error, ZIP_ER_INCONS, 0);
  409         _zip_buffer_free(cd_buffer);
  410         _zip_cdir_free(cd);
  411         return NULL;
  412     }
  413     }
  414 
  415     _zip_buffer_free(cd_buffer);
  416     return cd;
  417 }
  418 
  419 
  420 /* _zip_checkcons:
  421    Checks the consistency of the central directory by comparing central
  422    directory entries with local headers and checking for plausible
  423    file and header offsets. Returns -1 if not plausible, else the
  424    difference between the lowest and the highest fileposition reached */
  425 
  426 static zip_int64_t
  427 _zip_checkcons(zip_t *za, zip_cdir_t *cd, zip_error_t *error) {
  428     zip_uint64_t i;
  429     zip_uint64_t min, max, j;
  430     struct zip_dirent temp;
  431 
  432     _zip_dirent_init(&temp);
  433     if (cd->nentry) {
  434     max = cd->entry[0].orig->offset;
  435     min = cd->entry[0].orig->offset;
  436     }
  437     else
  438     min = max = 0;
  439 
  440     for (i = 0; i < cd->nentry; i++) {
  441     if (cd->entry[i].orig->offset < min)
  442         min = cd->entry[i].orig->offset;
  443     if (min > (zip_uint64_t)cd->offset) {
  444         zip_error_set(error, ZIP_ER_NOZIP, 0);
  445         return -1;
  446     }
  447 
  448     j = cd->entry[i].orig->offset + cd->entry[i].orig->comp_size + _zip_string_length(cd->entry[i].orig->filename) + LENTRYSIZE;
  449     if (j > max)
  450         max = j;
  451     if (max > (zip_uint64_t)cd->offset) {
  452         zip_error_set(error, ZIP_ER_NOZIP, 0);
  453         return -1;
  454     }
  455 
  456     if (zip_source_seek(za->src, (zip_int64_t)cd->entry[i].orig->offset, SEEK_SET) < 0) {
  457         _zip_error_set_from_source(error, za->src);
  458         return -1;
  459     }
  460 
  461     if (_zip_dirent_read(&temp, za->src, NULL, true, error) == -1) {
  462         _zip_dirent_finalize(&temp);
  463         return -1;
  464     }
  465 
  466     if (_zip_headercomp(cd->entry[i].orig, &temp) != 0) {
  467         zip_error_set(error, ZIP_ER_INCONS, 0);
  468         _zip_dirent_finalize(&temp);
  469         return -1;
  470     }
  471 
  472     cd->entry[i].orig->extra_fields = _zip_ef_merge(cd->entry[i].orig->extra_fields, temp.extra_fields);
  473     cd->entry[i].orig->local_extra_fields_read = 1;
  474     temp.extra_fields = NULL;
  475 
  476     _zip_dirent_finalize(&temp);
  477     }
  478 
  479     return (max - min) < ZIP_INT64_MAX ? (zip_int64_t)(max - min) : ZIP_INT64_MAX;
  480 }
  481 
  482 
  483 /* _zip_headercomp:
  484    compares a central directory entry and a local file header
  485    Return 0 if they are consistent, -1 if not. */
  486 
  487 static int
  488 _zip_headercomp(const zip_dirent_t *central, const zip_dirent_t *local) {
  489     if ((central->version_needed < local->version_needed)
  490 #if 0
  491     /* some zip-files have different values in local
  492        and global headers for the bitflags */
  493     || (central->bitflags != local->bitflags)
  494 #endif
  495     || (central->comp_method != local->comp_method) || (central->last_mod != local->last_mod) || !_zip_string_equal(central->filename, local->filename))
  496     return -1;
  497 
  498     if ((central->crc != local->crc) || (central->comp_size != local->comp_size) || (central->uncomp_size != local->uncomp_size)) {
  499     /* InfoZip stores valid values in local header even when data descriptor is used.
  500        This is in violation of the appnote. */
  501     if (((local->bitflags & ZIP_GPBF_DATA_DESCRIPTOR) == 0 || local->crc != 0 || local->comp_size != 0 || local->uncomp_size != 0))
  502         return -1;
  503     }
  504 
  505     return 0;
  506 }
  507 
  508 
  509 static zip_t *
  510 _zip_allocate_new(zip_source_t *src, unsigned int flags, zip_error_t *error) {
  511     zip_t *za;
  512 
  513     if ((za = _zip_new(error)) == NULL) {
  514     return NULL;
  515     }
  516 
  517     za->src = src;
  518     za->open_flags = flags;
  519     if (flags & ZIP_RDONLY) {
  520     za->flags |= ZIP_AFL_RDONLY;
  521     za->ch_flags |= ZIP_AFL_RDONLY;
  522     }
  523     return za;
  524 }
  525 
  526 
  527 /*
  528  * tests for file existence
  529  */
  530 static exists_t
  531 _zip_file_exists(zip_source_t *src, zip_error_t *error) {
  532     struct zip_stat st;
  533 
  534     zip_stat_init(&st);
  535     if (zip_source_stat(src, &st) != 0) {
  536     zip_error_t *src_error = zip_source_error(src);
  537     if (zip_error_code_zip(src_error) == ZIP_ER_READ && zip_error_code_system(src_error) == ENOENT) {
  538         return EXISTS_NOT;
  539     }
  540     _zip_error_copy(error, src_error);
  541     return EXISTS_ERROR;
  542     }
  543 
  544     return (st.valid & ZIP_STAT_SIZE) && st.size == 0 ? EXISTS_EMPTY : EXISTS_NONEMPTY;
  545 }
  546 
  547 
  548 static zip_cdir_t *
  549 _zip_find_central_dir(zip_t *za, zip_uint64_t len) {
  550     zip_cdir_t *cdir, *cdirnew;
  551     zip_uint8_t *match;
  552     zip_int64_t buf_offset;
  553     zip_uint64_t buflen;
  554     zip_int64_t a;
  555     zip_int64_t best;
  556     zip_error_t error;
  557     zip_buffer_t *buffer;
  558 
  559     if (len < EOCDLEN) {
  560     zip_error_set(&za->error, ZIP_ER_NOZIP, 0);
  561     return NULL;
  562     }
  563 
  564     buflen = (len < CDBUFSIZE ? len : CDBUFSIZE);
  565     if (zip_source_seek(za->src, -(zip_int64_t)buflen, SEEK_END) < 0) {
  566     zip_error_t *src_error = zip_source_error(za->src);
  567     if (zip_error_code_zip(src_error) != ZIP_ER_SEEK || zip_error_code_system(src_error) != EFBIG) {
  568         /* seek before start of file on my machine */
  569         _zip_error_copy(&za->error, src_error);
  570         return NULL;
  571     }
  572     }
  573     if ((buf_offset = zip_source_tell(za->src)) < 0) {
  574     _zip_error_set_from_source(&za->error, za->src);
  575     return NULL;
  576     }
  577 
  578     if ((buffer = _zip_buffer_new_from_source(za->src, buflen, NULL, &za->error)) == NULL) {
  579     return NULL;
  580     }
  581 
  582     best = -1;
  583     cdir = NULL;
  584     if (buflen >= CDBUFSIZE) {
  585     /* EOCD64 locator is before EOCD, so leave place for it */
  586     _zip_buffer_set_offset(buffer, EOCD64LOCLEN);
  587     }
  588     zip_error_set(&error, ZIP_ER_NOZIP, 0);
  589 
  590     match = _zip_buffer_get(buffer, 0);
  591     while ((match = _zip_memmem(match, _zip_buffer_left(buffer) - (EOCDLEN - 4), (const unsigned char *)EOCD_MAGIC, 4)) != NULL) {
  592     _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
  593     if ((cdirnew = _zip_read_cdir(za, buffer, (zip_uint64_t)buf_offset, &error)) != NULL) {
  594         if (cdir) {
  595         if (best <= 0) {
  596             best = _zip_checkcons(za, cdir, &error);
  597         }
  598 
  599         a = _zip_checkcons(za, cdirnew, &error);
  600         if (best < a) {
  601             _zip_cdir_free(cdir);
  602             cdir = cdirnew;
  603             best = a;
  604         }
  605         else {
  606             _zip_cdir_free(cdirnew);
  607         }
  608         }
  609         else {
  610         cdir = cdirnew;
  611         if (za->open_flags & ZIP_CHECKCONS)
  612             best = _zip_checkcons(za, cdir, &error);
  613         else {
  614             best = 0;
  615         }
  616         }
  617         cdirnew = NULL;
  618     }
  619 
  620     match++;
  621     _zip_buffer_set_offset(buffer, (zip_uint64_t)(match - _zip_buffer_data(buffer)));
  622     }
  623 
  624     _zip_buffer_free(buffer);
  625 
  626     if (best < 0) {
  627     _zip_error_copy(&za->error, &error);
  628     _zip_cdir_free(cdir);
  629     return NULL;
  630     }
  631 
  632     return cdir;
  633 }
  634 
  635 
  636 static unsigned char *
  637 _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little, size_t littlelen) {
  638     const unsigned char *p;
  639 
  640     if ((biglen < littlelen) || (littlelen == 0))
  641     return NULL;
  642     p = big - 1;
  643     while ((p = (const unsigned char *)memchr(p + 1, little[0], (size_t)(big - (p + 1)) + (size_t)(biglen - littlelen) + 1)) != NULL) {
  644     if (memcmp(p + 1, little + 1, littlelen - 1) == 0)
  645         return (unsigned char *)p;
  646     }
  647 
  648     return NULL;
  649 }
  650 
  651 
  652 static zip_cdir_t *
  653 _zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
  654     zip_cdir_t *cd;
  655     zip_uint64_t i, nentry, size, offset, eocd_offset;
  656 
  657     if (_zip_buffer_left(buffer) < EOCDLEN) {
  658     zip_error_set(error, ZIP_ER_INCONS, 0);
  659     return NULL;
  660     }
  661 
  662     eocd_offset = _zip_buffer_offset(buffer);
  663 
  664     _zip_buffer_get(buffer, 4); /* magic already verified */
  665 
  666     if (_zip_buffer_get_32(buffer) != 0) {
  667     zip_error_set(error, ZIP_ER_MULTIDISK, 0);
  668     return NULL;
  669     }
  670 
  671     /* number of cdir-entries on this disk */
  672     i = _zip_buffer_get_16(buffer);
  673     /* number of cdir-entries */
  674     nentry = _zip_buffer_get_16(buffer);
  675 
  676     if (nentry != i) {
  677     zip_error_set(error, ZIP_ER_NOZIP, 0);
  678     return NULL;
  679     }
  680 
  681     size = _zip_buffer_get_32(buffer);
  682     offset = _zip_buffer_get_32(buffer);
  683 
  684     if (offset + size < offset) {
  685     zip_error_set(error, ZIP_ER_SEEK, EFBIG);
  686     return NULL;
  687     }
  688 
  689     if (offset + size > buf_offset + eocd_offset) {
  690     /* cdir spans past EOCD record */
  691     zip_error_set(error, ZIP_ER_INCONS, 0);
  692     return NULL;
  693     }
  694 
  695     if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
  696     zip_error_set(error, ZIP_ER_INCONS, 0);
  697     return NULL;
  698     }
  699 
  700     if ((cd = _zip_cdir_new(nentry, error)) == NULL)
  701     return NULL;
  702 
  703     cd->is_zip64 = false;
  704     cd->size = size;
  705     cd->offset = offset;
  706 
  707     return cd;
  708 }
  709 
  710 
  711 static zip_cdir_t *
  712 _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) {
  713     zip_cdir_t *cd;
  714     zip_uint64_t offset;
  715     zip_uint8_t eocd[EOCD64LEN];
  716     zip_uint64_t eocd_offset;
  717     zip_uint64_t size, nentry, i, eocdloc_offset;
  718     bool free_buffer;
  719     zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
  720 
  721     eocdloc_offset = _zip_buffer_offset(buffer);
  722 
  723     _zip_buffer_get(buffer, 4); /* magic already verified */
  724 
  725     num_disks = _zip_buffer_get_16(buffer);
  726     eocd_disk = _zip_buffer_get_16(buffer);
  727     eocd_offset = _zip_buffer_get_64(buffer);
  728 
  729     if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
  730     zip_error_set(error, ZIP_ER_SEEK, EFBIG);
  731     return NULL;
  732     }
  733 
  734     if (eocd_offset + EOCD64LEN > eocdloc_offset + buf_offset) {
  735     zip_error_set(error, ZIP_ER_INCONS, 0);
  736     return NULL;
  737     }
  738 
  739     if (eocd_offset >= buf_offset && eocd_offset + EOCD64LEN <= buf_offset + _zip_buffer_size(buffer)) {
  740     _zip_buffer_set_offset(buffer, eocd_offset - buf_offset);
  741     free_buffer = false;
  742     }
  743     else {
  744     if (zip_source_seek(src, (zip_int64_t)eocd_offset, SEEK_SET) < 0) {
  745         _zip_error_set_from_source(error, src);
  746         return NULL;
  747     }
  748     if ((buffer = _zip_buffer_new_from_source(src, EOCD64LEN, eocd, error)) == NULL) {
  749         return NULL;
  750     }
  751     free_buffer = true;
  752     }
  753 
  754     if (memcmp(_zip_buffer_get(buffer, 4), EOCD64_MAGIC, 4) != 0) {
  755     zip_error_set(error, ZIP_ER_INCONS, 0);
  756     if (free_buffer) {
  757         _zip_buffer_free(buffer);
  758     }
  759     return NULL;
  760     }
  761 
  762     size = _zip_buffer_get_64(buffer);
  763 
  764     if ((flags & ZIP_CHECKCONS) && size + eocd_offset + 12 != buf_offset + eocdloc_offset) {
  765     zip_error_set(error, ZIP_ER_INCONS, 0);
  766     if (free_buffer) {
  767         _zip_buffer_free(buffer);
  768     }
  769     return NULL;
  770     }
  771 
  772     _zip_buffer_get(buffer, 4); /* skip version made by/needed */
  773 
  774     num_disks64 = _zip_buffer_get_32(buffer);
  775     eocd_disk64 = _zip_buffer_get_32(buffer);
  776 
  777     /* if eocd values are 0xffff, we have to use eocd64 values.
  778        otherwise, if the values are not the same, it's inconsistent;
  779        in any case, if the value is not 0, we don't support it */
  780     if (num_disks == 0xffff) {
  781     num_disks = num_disks64;
  782     }
  783     if (eocd_disk == 0xffff) {
  784     eocd_disk = eocd_disk64;
  785     }
  786     if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
  787     zip_error_set(error, ZIP_ER_INCONS, 0);
  788     if (free_buffer) {
  789         _zip_buffer_free(buffer);
  790     }
  791     return NULL;
  792     }
  793     if (num_disks != 0 || eocd_disk != 0) {
  794     zip_error_set(error, ZIP_ER_MULTIDISK, 0);
  795     if (free_buffer) {
  796         _zip_buffer_free(buffer);
  797     }
  798     return NULL;
  799     }
  800 
  801     nentry = _zip_buffer_get_64(buffer);
  802     i = _zip_buffer_get_64(buffer);
  803 
  804     if (nentry != i) {
  805     zip_error_set(error, ZIP_ER_MULTIDISK, 0);
  806     if (free_buffer) {
  807         _zip_buffer_free(buffer);
  808     }
  809     return NULL;
  810     }
  811 
  812     size = _zip_buffer_get_64(buffer);
  813     offset = _zip_buffer_get_64(buffer);
  814 
  815     if (!_zip_buffer_ok(buffer)) {
  816     zip_error_set(error, ZIP_ER_INTERNAL, 0);
  817     if (free_buffer) {
  818         _zip_buffer_free(buffer);
  819     }
  820     return NULL;
  821     }
  822 
  823     if (free_buffer) {
  824     _zip_buffer_free(buffer);
  825     }
  826 
  827     if (offset > ZIP_INT64_MAX || offset + size < offset) {
  828     zip_error_set(error, ZIP_ER_SEEK, EFBIG);
  829     return NULL;
  830     }
  831     if (offset + size > buf_offset + eocd_offset) {
  832     /* cdir spans past EOCD record */
  833     zip_error_set(error, ZIP_ER_INCONS, 0);
  834     return NULL;
  835     }
  836     if ((flags & ZIP_CHECKCONS) && offset + size != buf_offset + eocd_offset) {
  837     zip_error_set(error, ZIP_ER_INCONS, 0);
  838     return NULL;
  839     }
  840 
  841     if ((cd = _zip_cdir_new(nentry, error)) == NULL)
  842     return NULL;
  843 
  844     cd->is_zip64 = true;
  845     cd->size = size;
  846     cd->offset = offset;
  847 
  848     return cd;
  849 }