root/ext/zip/lib/zip_open.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zip_open
  2. zip_open_from_source
  3. zip_archive_set_tempdir
  4. _zip_open
  5. _zip_set_open_error
  6. _zip_read_cdir
  7. _zip_checkcons
  8. _zip_headercomp
  9. _zip_allocate_new
  10. _zip_file_exists
  11. _zip_find_central_dir
  12. _zip_memmem
  13. _zip_read_eocd
  14. _zip_read_eocd64

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

/* [<][>][^][v][top][bottom][index][help] */