Home | History | Annotate | Download | only in libziparchive
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *    http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Read-only access to Zip archives, with minimal heap allocation.
     19  */
     20 
     21 #include <assert.h>
     22 #include <errno.h>
     23 #include <fcntl.h>
     24 #include <inttypes.h>
     25 #include <limits.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <unistd.h>
     29 
     30 #include <memory>
     31 #include <vector>
     32 
     33 #include "android-base/file.h"
     34 #include "android-base/macros.h"  // TEMP_FAILURE_RETRY may or may not be in unistd
     35 #include "android-base/memory.h"
     36 #include "log/log.h"
     37 #include "utils/Compat.h"
     38 #include "utils/FileMap.h"
     39 #include "ziparchive/zip_archive.h"
     40 #include "zlib.h"
     41 
     42 #include "entry_name_utils-inl.h"
     43 #include "zip_archive_common.h"
     44 #include "zip_archive_private.h"
     45 
     46 using android::base::get_unaligned;
     47 
     48 // This is for windows. If we don't open a file in binary mode, weird
     49 // things will happen.
     50 #ifndef O_BINARY
     51 #define O_BINARY 0
     52 #endif
     53 
     54 // The maximum number of bytes to scan backwards for the EOCD start.
     55 static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
     56 
     57 static const char* kErrorMessages[] = {
     58   "Unknown return code.",
     59   "Iteration ended",
     60   "Zlib error",
     61   "Invalid file",
     62   "Invalid handle",
     63   "Duplicate entries in archive",
     64   "Empty archive",
     65   "Entry not found",
     66   "Invalid offset",
     67   "Inconsistent information",
     68   "Invalid entry name",
     69   "I/O Error",
     70   "File mapping failed"
     71 };
     72 
     73 static const int32_t kErrorMessageUpperBound = 0;
     74 
     75 static const int32_t kIterationEnd = -1;
     76 
     77 // We encountered a Zlib error when inflating a stream from this file.
     78 // Usually indicates file corruption.
     79 static const int32_t kZlibError = -2;
     80 
     81 // The input file cannot be processed as a zip archive. Usually because
     82 // it's too small, too large or does not have a valid signature.
     83 static const int32_t kInvalidFile = -3;
     84 
     85 // An invalid iteration / ziparchive handle was passed in as an input
     86 // argument.
     87 static const int32_t kInvalidHandle = -4;
     88 
     89 // The zip archive contained two (or possibly more) entries with the same
     90 // name.
     91 static const int32_t kDuplicateEntry = -5;
     92 
     93 // The zip archive contains no entries.
     94 static const int32_t kEmptyArchive = -6;
     95 
     96 // The specified entry was not found in the archive.
     97 static const int32_t kEntryNotFound = -7;
     98 
     99 // The zip archive contained an invalid local file header pointer.
    100 static const int32_t kInvalidOffset = -8;
    101 
    102 // The zip archive contained inconsistent entry information. This could
    103 // be because the central directory & local file header did not agree, or
    104 // if the actual uncompressed length or crc32 do not match their declared
    105 // values.
    106 static const int32_t kInconsistentInformation = -9;
    107 
    108 // An invalid entry name was encountered.
    109 static const int32_t kInvalidEntryName = -10;
    110 
    111 // An I/O related system call (read, lseek, ftruncate, map) failed.
    112 static const int32_t kIoError = -11;
    113 
    114 // We were not able to mmap the central directory or entry contents.
    115 static const int32_t kMmapFailed = -12;
    116 
    117 static const int32_t kErrorMessageLowerBound = -13;
    118 
    119 /*
    120  * A Read-only Zip archive.
    121  *
    122  * We want "open" and "find entry by name" to be fast operations, and
    123  * we want to use as little memory as possible.  We memory-map the zip
    124  * central directory, and load a hash table with pointers to the filenames
    125  * (which aren't null-terminated).  The other fields are at a fixed offset
    126  * from the filename, so we don't need to extract those (but we do need
    127  * to byte-read and endian-swap them every time we want them).
    128  *
    129  * It's possible that somebody has handed us a massive (~1GB) zip archive,
    130  * so we can't expect to mmap the entire file.
    131  *
    132  * To speed comparisons when doing a lookup by name, we could make the mapping
    133  * "private" (copy-on-write) and null-terminate the filenames after verifying
    134  * the record structure.  However, this requires a private mapping of
    135  * every page that the Central Directory touches.  Easier to tuck a copy
    136  * of the string length into the hash table entry.
    137  */
    138 
    139 /*
    140  * Round up to the next highest power of 2.
    141  *
    142  * Found on http://graphics.stanford.edu/~seander/bithacks.html.
    143  */
    144 static uint32_t RoundUpPower2(uint32_t val) {
    145   val--;
    146   val |= val >> 1;
    147   val |= val >> 2;
    148   val |= val >> 4;
    149   val |= val >> 8;
    150   val |= val >> 16;
    151   val++;
    152 
    153   return val;
    154 }
    155 
    156 static uint32_t ComputeHash(const ZipString& name) {
    157   uint32_t hash = 0;
    158   uint16_t len = name.name_length;
    159   const uint8_t* str = name.name;
    160 
    161   while (len--) {
    162     hash = hash * 31 + *str++;
    163   }
    164 
    165   return hash;
    166 }
    167 
    168 /*
    169  * Convert a ZipEntry to a hash table index, verifying that it's in a
    170  * valid range.
    171  */
    172 static int64_t EntryToIndex(const ZipString* hash_table,
    173                             const uint32_t hash_table_size,
    174                             const ZipString& name) {
    175   const uint32_t hash = ComputeHash(name);
    176 
    177   // NOTE: (hash_table_size - 1) is guaranteed to be non-negative.
    178   uint32_t ent = hash & (hash_table_size - 1);
    179   while (hash_table[ent].name != NULL) {
    180     if (hash_table[ent] == name) {
    181       return ent;
    182     }
    183 
    184     ent = (ent + 1) & (hash_table_size - 1);
    185   }
    186 
    187   ALOGV("Zip: Unable to find entry %.*s", name.name_length, name.name);
    188   return kEntryNotFound;
    189 }
    190 
    191 /*
    192  * Add a new entry to the hash table.
    193  */
    194 static int32_t AddToHash(ZipString *hash_table, const uint64_t hash_table_size,
    195                          const ZipString& name) {
    196   const uint64_t hash = ComputeHash(name);
    197   uint32_t ent = hash & (hash_table_size - 1);
    198 
    199   /*
    200    * We over-allocated the table, so we're guaranteed to find an empty slot.
    201    * Further, we guarantee that the hashtable size is not 0.
    202    */
    203   while (hash_table[ent].name != NULL) {
    204     if (hash_table[ent] == name) {
    205       // We've found a duplicate entry. We don't accept it
    206       ALOGW("Zip: Found duplicate entry %.*s", name.name_length, name.name);
    207       return kDuplicateEntry;
    208     }
    209     ent = (ent + 1) & (hash_table_size - 1);
    210   }
    211 
    212   hash_table[ent].name = name.name;
    213   hash_table[ent].name_length = name.name_length;
    214   return 0;
    215 }
    216 
    217 static int32_t MapCentralDirectory0(int fd, const char* debug_file_name,
    218                                     ZipArchive* archive, off64_t file_length,
    219                                     off64_t read_amount, uint8_t* scan_buffer) {
    220   const off64_t search_start = file_length - read_amount;
    221 
    222   if (lseek64(fd, search_start, SEEK_SET) != search_start) {
    223     ALOGW("Zip: seek %" PRId64 " failed: %s", static_cast<int64_t>(search_start),
    224           strerror(errno));
    225     return kIoError;
    226   }
    227   if (!android::base::ReadFully(fd, scan_buffer, static_cast<size_t>(read_amount))) {
    228     ALOGW("Zip: read %" PRId64 " failed: %s", static_cast<int64_t>(read_amount),
    229           strerror(errno));
    230     return kIoError;
    231   }
    232 
    233   /*
    234    * Scan backward for the EOCD magic.  In an archive without a trailing
    235    * comment, we'll find it on the first try.  (We may want to consider
    236    * doing an initial minimal read; if we don't find it, retry with a
    237    * second read as above.)
    238    */
    239   int i = read_amount - sizeof(EocdRecord);
    240   for (; i >= 0; i--) {
    241     if (scan_buffer[i] == 0x50) {
    242       uint32_t* sig_addr = reinterpret_cast<uint32_t*>(&scan_buffer[i]);
    243       if (get_unaligned<uint32_t>(sig_addr) == EocdRecord::kSignature) {
    244         ALOGV("+++ Found EOCD at buf+%d", i);
    245         break;
    246       }
    247     }
    248   }
    249   if (i < 0) {
    250     ALOGD("Zip: EOCD not found, %s is not zip", debug_file_name);
    251     return kInvalidFile;
    252   }
    253 
    254   const off64_t eocd_offset = search_start + i;
    255   const EocdRecord* eocd = reinterpret_cast<const EocdRecord*>(scan_buffer + i);
    256   /*
    257    * Verify that there's no trailing space at the end of the central directory
    258    * and its comment.
    259    */
    260   const off64_t calculated_length = eocd_offset + sizeof(EocdRecord)
    261       + eocd->comment_length;
    262   if (calculated_length != file_length) {
    263     ALOGW("Zip: %" PRId64 " extraneous bytes at the end of the central directory",
    264           static_cast<int64_t>(file_length - calculated_length));
    265     return kInvalidFile;
    266   }
    267 
    268   /*
    269    * Grab the CD offset and size, and the number of entries in the
    270    * archive and verify that they look reasonable.
    271    */
    272   if (static_cast<off64_t>(eocd->cd_start_offset) + eocd->cd_size > eocd_offset) {
    273     ALOGW("Zip: bad offsets (dir %" PRIu32 ", size %" PRIu32 ", eocd %" PRId64 ")",
    274         eocd->cd_start_offset, eocd->cd_size, static_cast<int64_t>(eocd_offset));
    275 #if defined(__ANDROID__)
    276     if (eocd->cd_start_offset + eocd->cd_size <= eocd_offset) {
    277       android_errorWriteLog(0x534e4554, "31251826");
    278     }
    279 #endif
    280     return kInvalidOffset;
    281   }
    282   if (eocd->num_records == 0) {
    283     ALOGW("Zip: empty archive?");
    284     return kEmptyArchive;
    285   }
    286 
    287   ALOGV("+++ num_entries=%" PRIu32 " dir_size=%" PRIu32 " dir_offset=%" PRIu32,
    288         eocd->num_records, eocd->cd_size, eocd->cd_start_offset);
    289 
    290   /*
    291    * It all looks good.  Create a mapping for the CD, and set the fields
    292    * in archive.
    293    */
    294   if (!archive->directory_map.create(debug_file_name, fd,
    295           static_cast<off64_t>(eocd->cd_start_offset),
    296           static_cast<size_t>(eocd->cd_size), true /* read only */) ) {
    297     return kMmapFailed;
    298   }
    299 
    300   archive->num_entries = eocd->num_records;
    301   archive->directory_offset = eocd->cd_start_offset;
    302 
    303   return 0;
    304 }
    305 
    306 /*
    307  * Find the zip Central Directory and memory-map it.
    308  *
    309  * On success, returns 0 after populating fields from the EOCD area:
    310  *   directory_offset
    311  *   directory_map
    312  *   num_entries
    313  */
    314 static int32_t MapCentralDirectory(int fd, const char* debug_file_name,
    315                                    ZipArchive* archive) {
    316 
    317   // Test file length. We use lseek64 to make sure the file
    318   // is small enough to be a zip file (Its size must be less than
    319   // 0xffffffff bytes).
    320   off64_t file_length = lseek64(fd, 0, SEEK_END);
    321   if (file_length == -1) {
    322     ALOGV("Zip: lseek on fd %d failed", fd);
    323     return kInvalidFile;
    324   }
    325 
    326   if (file_length > static_cast<off64_t>(0xffffffff)) {
    327     ALOGV("Zip: zip file too long %" PRId64, static_cast<int64_t>(file_length));
    328     return kInvalidFile;
    329   }
    330 
    331   if (file_length < static_cast<off64_t>(sizeof(EocdRecord))) {
    332     ALOGV("Zip: length %" PRId64 " is too small to be zip", static_cast<int64_t>(file_length));
    333     return kInvalidFile;
    334   }
    335 
    336   /*
    337    * Perform the traditional EOCD snipe hunt.
    338    *
    339    * We're searching for the End of Central Directory magic number,
    340    * which appears at the start of the EOCD block.  It's followed by
    341    * 18 bytes of EOCD stuff and up to 64KB of archive comment.  We
    342    * need to read the last part of the file into a buffer, dig through
    343    * it to find the magic number, parse some values out, and use those
    344    * to determine the extent of the CD.
    345    *
    346    * We start by pulling in the last part of the file.
    347    */
    348   off64_t read_amount = kMaxEOCDSearch;
    349   if (file_length < read_amount) {
    350     read_amount = file_length;
    351   }
    352 
    353   uint8_t* scan_buffer = reinterpret_cast<uint8_t*>(malloc(read_amount));
    354   int32_t result = MapCentralDirectory0(fd, debug_file_name, archive,
    355                                         file_length, read_amount, scan_buffer);
    356 
    357   free(scan_buffer);
    358   return result;
    359 }
    360 
    361 /*
    362  * Parses the Zip archive's Central Directory.  Allocates and populates the
    363  * hash table.
    364  *
    365  * Returns 0 on success.
    366  */
    367 static int32_t ParseZipArchive(ZipArchive* archive) {
    368   const uint8_t* const cd_ptr =
    369       reinterpret_cast<const uint8_t*>(archive->directory_map.getDataPtr());
    370   const size_t cd_length = archive->directory_map.getDataLength();
    371   const uint16_t num_entries = archive->num_entries;
    372 
    373   /*
    374    * Create hash table.  We have a minimum 75% load factor, possibly as
    375    * low as 50% after we round off to a power of 2.  There must be at
    376    * least one unused entry to avoid an infinite loop during creation.
    377    */
    378   archive->hash_table_size = RoundUpPower2(1 + (num_entries * 4) / 3);
    379   archive->hash_table = reinterpret_cast<ZipString*>(calloc(archive->hash_table_size,
    380       sizeof(ZipString)));
    381 
    382   /*
    383    * Walk through the central directory, adding entries to the hash
    384    * table and verifying values.
    385    */
    386   const uint8_t* const cd_end = cd_ptr + cd_length;
    387   const uint8_t* ptr = cd_ptr;
    388   for (uint16_t i = 0; i < num_entries; i++) {
    389     const CentralDirectoryRecord* cdr =
    390         reinterpret_cast<const CentralDirectoryRecord*>(ptr);
    391     if (cdr->record_signature != CentralDirectoryRecord::kSignature) {
    392       ALOGW("Zip: missed a central dir sig (at %" PRIu16 ")", i);
    393       return -1;
    394     }
    395 
    396     if (ptr + sizeof(CentralDirectoryRecord) > cd_end) {
    397       ALOGW("Zip: ran off the end (at %" PRIu16 ")", i);
    398       return -1;
    399     }
    400 
    401     const off64_t local_header_offset = cdr->local_file_header_offset;
    402     if (local_header_offset >= archive->directory_offset) {
    403       ALOGW("Zip: bad LFH offset %" PRId64 " at entry %" PRIu16,
    404           static_cast<int64_t>(local_header_offset), i);
    405       return -1;
    406     }
    407 
    408     const uint16_t file_name_length = cdr->file_name_length;
    409     const uint16_t extra_length = cdr->extra_field_length;
    410     const uint16_t comment_length = cdr->comment_length;
    411     const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
    412 
    413     /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
    414     if (!IsValidEntryName(file_name, file_name_length)) {
    415       return -1;
    416     }
    417 
    418     /* add the CDE filename to the hash table */
    419     ZipString entry_name;
    420     entry_name.name = file_name;
    421     entry_name.name_length = file_name_length;
    422     const int add_result = AddToHash(archive->hash_table,
    423         archive->hash_table_size, entry_name);
    424     if (add_result != 0) {
    425       ALOGW("Zip: Error adding entry to hash table %d", add_result);
    426       return add_result;
    427     }
    428 
    429     ptr += sizeof(CentralDirectoryRecord) + file_name_length + extra_length + comment_length;
    430     if ((ptr - cd_ptr) > static_cast<int64_t>(cd_length)) {
    431       ALOGW("Zip: bad CD advance (%tu vs %zu) at entry %" PRIu16,
    432           ptr - cd_ptr, cd_length, i);
    433       return -1;
    434     }
    435   }
    436   ALOGV("+++ zip good scan %" PRIu16 " entries", num_entries);
    437 
    438   return 0;
    439 }
    440 
    441 static int32_t OpenArchiveInternal(ZipArchive* archive,
    442                                    const char* debug_file_name) {
    443   int32_t result = -1;
    444   if ((result = MapCentralDirectory(archive->fd, debug_file_name, archive))) {
    445     return result;
    446   }
    447 
    448   if ((result = ParseZipArchive(archive))) {
    449     return result;
    450   }
    451 
    452   return 0;
    453 }
    454 
    455 int32_t OpenArchiveFd(int fd, const char* debug_file_name,
    456                       ZipArchiveHandle* handle, bool assume_ownership) {
    457   ZipArchive* archive = new ZipArchive(fd, assume_ownership);
    458   *handle = archive;
    459   return OpenArchiveInternal(archive, debug_file_name);
    460 }
    461 
    462 int32_t OpenArchive(const char* fileName, ZipArchiveHandle* handle) {
    463   const int fd = open(fileName, O_RDONLY | O_BINARY, 0);
    464   ZipArchive* archive = new ZipArchive(fd, true);
    465   *handle = archive;
    466 
    467   if (fd < 0) {
    468     ALOGW("Unable to open '%s': %s", fileName, strerror(errno));
    469     return kIoError;
    470   }
    471 
    472   return OpenArchiveInternal(archive, fileName);
    473 }
    474 
    475 /*
    476  * Close a ZipArchive, closing the file and freeing the contents.
    477  */
    478 void CloseArchive(ZipArchiveHandle handle) {
    479   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    480   ALOGV("Closing archive %p", archive);
    481   delete archive;
    482 }
    483 
    484 static int32_t UpdateEntryFromDataDescriptor(int fd,
    485                                              ZipEntry *entry) {
    486   uint8_t ddBuf[sizeof(DataDescriptor) + sizeof(DataDescriptor::kOptSignature)];
    487   if (!android::base::ReadFully(fd, ddBuf, sizeof(ddBuf))) {
    488     return kIoError;
    489   }
    490 
    491   const uint32_t ddSignature = *(reinterpret_cast<const uint32_t*>(ddBuf));
    492   const uint16_t offset = (ddSignature == DataDescriptor::kOptSignature) ? 4 : 0;
    493   const DataDescriptor* descriptor = reinterpret_cast<const DataDescriptor*>(ddBuf + offset);
    494 
    495   entry->crc32 = descriptor->crc32;
    496   entry->compressed_length = descriptor->compressed_size;
    497   entry->uncompressed_length = descriptor->uncompressed_size;
    498 
    499   return 0;
    500 }
    501 
    502 // Attempts to read |len| bytes into |buf| at offset |off|.
    503 // On non-Windows platforms, callers are guaranteed that the |fd|
    504 // offset is unchanged and there is no side effect to this call.
    505 //
    506 // On Windows platforms this is not thread-safe.
    507 static inline bool ReadAtOffset(int fd, uint8_t* buf, size_t len, off64_t off) {
    508 #if !defined(_WIN32)
    509   return TEMP_FAILURE_RETRY(pread64(fd, buf, len, off));
    510 #else
    511   if (lseek64(fd, off, SEEK_SET) != off) {
    512     ALOGW("Zip: failed seek to offset %" PRId64, off);
    513     return false;
    514   }
    515   return android::base::ReadFully(fd, buf, len);
    516 #endif
    517 }
    518 
    519 static int32_t FindEntry(const ZipArchive* archive, const int ent,
    520                          ZipEntry* data) {
    521   const uint16_t nameLen = archive->hash_table[ent].name_length;
    522 
    523   // Recover the start of the central directory entry from the filename
    524   // pointer.  The filename is the first entry past the fixed-size data,
    525   // so we can just subtract back from that.
    526   const uint8_t* ptr = archive->hash_table[ent].name;
    527   ptr -= sizeof(CentralDirectoryRecord);
    528 
    529   // This is the base of our mmapped region, we have to sanity check that
    530   // the name that's in the hash table is a pointer to a location within
    531   // this mapped region.
    532   const uint8_t* base_ptr = reinterpret_cast<const uint8_t*>(
    533     archive->directory_map.getDataPtr());
    534   if (ptr < base_ptr || ptr > base_ptr + archive->directory_map.getDataLength()) {
    535     ALOGW("Zip: Invalid entry pointer");
    536     return kInvalidOffset;
    537   }
    538 
    539   const CentralDirectoryRecord *cdr =
    540       reinterpret_cast<const CentralDirectoryRecord*>(ptr);
    541 
    542   // The offset of the start of the central directory in the zipfile.
    543   // We keep this lying around so that we can sanity check all our lengths
    544   // and our per-file structures.
    545   const off64_t cd_offset = archive->directory_offset;
    546 
    547   // Fill out the compression method, modification time, crc32
    548   // and other interesting attributes from the central directory. These
    549   // will later be compared against values from the local file header.
    550   data->method = cdr->compression_method;
    551   data->mod_time = cdr->last_mod_date << 16 | cdr->last_mod_time;
    552   data->crc32 = cdr->crc32;
    553   data->compressed_length = cdr->compressed_size;
    554   data->uncompressed_length = cdr->uncompressed_size;
    555 
    556   // Figure out the local header offset from the central directory. The
    557   // actual file data will begin after the local header and the name /
    558   // extra comments.
    559   const off64_t local_header_offset = cdr->local_file_header_offset;
    560   if (local_header_offset + static_cast<off64_t>(sizeof(LocalFileHeader)) >= cd_offset) {
    561     ALOGW("Zip: bad local hdr offset in zip");
    562     return kInvalidOffset;
    563   }
    564 
    565   uint8_t lfh_buf[sizeof(LocalFileHeader)];
    566   if (!ReadAtOffset(archive->fd, lfh_buf, sizeof(lfh_buf), local_header_offset)) {
    567     ALOGW("Zip: failed reading lfh name from offset %" PRId64,
    568         static_cast<int64_t>(local_header_offset));
    569     return kIoError;
    570   }
    571 
    572   const LocalFileHeader *lfh = reinterpret_cast<const LocalFileHeader*>(lfh_buf);
    573 
    574   if (lfh->lfh_signature != LocalFileHeader::kSignature) {
    575     ALOGW("Zip: didn't find signature at start of lfh, offset=%" PRId64,
    576         static_cast<int64_t>(local_header_offset));
    577     return kInvalidOffset;
    578   }
    579 
    580   // Paranoia: Match the values specified in the local file header
    581   // to those specified in the central directory.
    582   if ((lfh->gpb_flags & kGPBDDFlagMask) == 0) {
    583     data->has_data_descriptor = 0;
    584     if (data->compressed_length != lfh->compressed_size
    585         || data->uncompressed_length != lfh->uncompressed_size
    586         || data->crc32 != lfh->crc32) {
    587       ALOGW("Zip: size/crc32 mismatch. expected {%" PRIu32 ", %" PRIu32
    588         ", %" PRIx32 "}, was {%" PRIu32 ", %" PRIu32 ", %" PRIx32 "}",
    589         data->compressed_length, data->uncompressed_length, data->crc32,
    590         lfh->compressed_size, lfh->uncompressed_size, lfh->crc32);
    591       return kInconsistentInformation;
    592     }
    593   } else {
    594     data->has_data_descriptor = 1;
    595   }
    596 
    597   // Check that the local file header name matches the declared
    598   // name in the central directory.
    599   if (lfh->file_name_length == nameLen) {
    600     const off64_t name_offset = local_header_offset + sizeof(LocalFileHeader);
    601     if (name_offset + lfh->file_name_length > cd_offset) {
    602       ALOGW("Zip: Invalid declared length");
    603       return kInvalidOffset;
    604     }
    605 
    606     uint8_t* name_buf = reinterpret_cast<uint8_t*>(malloc(nameLen));
    607     if (!ReadAtOffset(archive->fd, name_buf, nameLen, name_offset)) {
    608       ALOGW("Zip: failed reading lfh name from offset %" PRId64, static_cast<int64_t>(name_offset));
    609       free(name_buf);
    610       return kIoError;
    611     }
    612 
    613     if (memcmp(archive->hash_table[ent].name, name_buf, nameLen)) {
    614       free(name_buf);
    615       return kInconsistentInformation;
    616     }
    617 
    618     free(name_buf);
    619   } else {
    620     ALOGW("Zip: lfh name did not match central directory.");
    621     return kInconsistentInformation;
    622   }
    623 
    624   const off64_t data_offset = local_header_offset + sizeof(LocalFileHeader)
    625       + lfh->file_name_length + lfh->extra_field_length;
    626   if (data_offset > cd_offset) {
    627     ALOGW("Zip: bad data offset %" PRId64 " in zip", static_cast<int64_t>(data_offset));
    628     return kInvalidOffset;
    629   }
    630 
    631   if (static_cast<off64_t>(data_offset + data->compressed_length) > cd_offset) {
    632     ALOGW("Zip: bad compressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
    633       static_cast<int64_t>(data_offset), data->compressed_length, static_cast<int64_t>(cd_offset));
    634     return kInvalidOffset;
    635   }
    636 
    637   if (data->method == kCompressStored &&
    638     static_cast<off64_t>(data_offset + data->uncompressed_length) > cd_offset) {
    639      ALOGW("Zip: bad uncompressed length in zip (%" PRId64 " + %" PRIu32 " > %" PRId64 ")",
    640        static_cast<int64_t>(data_offset), data->uncompressed_length,
    641        static_cast<int64_t>(cd_offset));
    642      return kInvalidOffset;
    643   }
    644 
    645   data->offset = data_offset;
    646   return 0;
    647 }
    648 
    649 struct IterationHandle {
    650   uint32_t position;
    651   // We're not using vector here because this code is used in the Windows SDK
    652   // where the STL is not available.
    653   ZipString prefix;
    654   ZipString suffix;
    655   ZipArchive* archive;
    656 
    657   IterationHandle(const ZipString* in_prefix,
    658                   const ZipString* in_suffix) {
    659     if (in_prefix) {
    660       uint8_t* name_copy = new uint8_t[in_prefix->name_length];
    661       memcpy(name_copy, in_prefix->name, in_prefix->name_length);
    662       prefix.name = name_copy;
    663       prefix.name_length = in_prefix->name_length;
    664     } else {
    665       prefix.name = NULL;
    666       prefix.name_length = 0;
    667     }
    668     if (in_suffix) {
    669       uint8_t* name_copy = new uint8_t[in_suffix->name_length];
    670       memcpy(name_copy, in_suffix->name, in_suffix->name_length);
    671       suffix.name = name_copy;
    672       suffix.name_length = in_suffix->name_length;
    673     } else {
    674       suffix.name = NULL;
    675       suffix.name_length = 0;
    676     }
    677   }
    678 
    679   ~IterationHandle() {
    680     delete[] prefix.name;
    681     delete[] suffix.name;
    682   }
    683 };
    684 
    685 int32_t StartIteration(ZipArchiveHandle handle, void** cookie_ptr,
    686                        const ZipString* optional_prefix,
    687                        const ZipString* optional_suffix) {
    688   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    689 
    690   if (archive == NULL || archive->hash_table == NULL) {
    691     ALOGW("Zip: Invalid ZipArchiveHandle");
    692     return kInvalidHandle;
    693   }
    694 
    695   IterationHandle* cookie = new IterationHandle(optional_prefix, optional_suffix);
    696   cookie->position = 0;
    697   cookie->archive = archive;
    698 
    699   *cookie_ptr = cookie ;
    700   return 0;
    701 }
    702 
    703 void EndIteration(void* cookie) {
    704   delete reinterpret_cast<IterationHandle*>(cookie);
    705 }
    706 
    707 int32_t FindEntry(const ZipArchiveHandle handle, const ZipString& entryName,
    708                   ZipEntry* data) {
    709   const ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
    710   if (entryName.name_length == 0) {
    711     ALOGW("Zip: Invalid filename %.*s", entryName.name_length, entryName.name);
    712     return kInvalidEntryName;
    713   }
    714 
    715   const int64_t ent = EntryToIndex(archive->hash_table,
    716     archive->hash_table_size, entryName);
    717 
    718   if (ent < 0) {
    719     ALOGV("Zip: Could not find entry %.*s", entryName.name_length, entryName.name);
    720     return ent;
    721   }
    722 
    723   return FindEntry(archive, ent, data);
    724 }
    725 
    726 int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
    727   IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
    728   if (handle == NULL) {
    729     return kInvalidHandle;
    730   }
    731 
    732   ZipArchive* archive = handle->archive;
    733   if (archive == NULL || archive->hash_table == NULL) {
    734     ALOGW("Zip: Invalid ZipArchiveHandle");
    735     return kInvalidHandle;
    736   }
    737 
    738   const uint32_t currentOffset = handle->position;
    739   const uint32_t hash_table_length = archive->hash_table_size;
    740   const ZipString* hash_table = archive->hash_table;
    741 
    742   for (uint32_t i = currentOffset; i < hash_table_length; ++i) {
    743     if (hash_table[i].name != NULL &&
    744         (handle->prefix.name_length == 0 ||
    745          hash_table[i].StartsWith(handle->prefix)) &&
    746         (handle->suffix.name_length == 0 ||
    747          hash_table[i].EndsWith(handle->suffix))) {
    748       handle->position = (i + 1);
    749       const int error = FindEntry(archive, i, data);
    750       if (!error) {
    751         name->name = hash_table[i].name;
    752         name->name_length = hash_table[i].name_length;
    753       }
    754 
    755       return error;
    756     }
    757   }
    758 
    759   handle->position = 0;
    760   return kIterationEnd;
    761 }
    762 
    763 class Writer {
    764  public:
    765   virtual bool Append(uint8_t* buf, size_t buf_size) = 0;
    766   virtual ~Writer() {}
    767  protected:
    768   Writer() = default;
    769  private:
    770   DISALLOW_COPY_AND_ASSIGN(Writer);
    771 };
    772 
    773 // A Writer that writes data to a fixed size memory region.
    774 // The size of the memory region must be equal to the total size of
    775 // the data appended to it.
    776 class MemoryWriter : public Writer {
    777  public:
    778   MemoryWriter(uint8_t* buf, size_t size) : Writer(),
    779       buf_(buf), size_(size), bytes_written_(0) {
    780   }
    781 
    782   virtual bool Append(uint8_t* buf, size_t buf_size) override {
    783     if (bytes_written_ + buf_size > size_) {
    784       ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)",
    785             size_, bytes_written_ + buf_size);
    786       return false;
    787     }
    788 
    789     memcpy(buf_ + bytes_written_, buf, buf_size);
    790     bytes_written_ += buf_size;
    791     return true;
    792   }
    793 
    794  private:
    795   uint8_t* const buf_;
    796   const size_t size_;
    797   size_t bytes_written_;
    798 };
    799 
    800 // A Writer that appends data to a file |fd| at its current position.
    801 // The file will be truncated to the end of the written data.
    802 class FileWriter : public Writer {
    803  public:
    804 
    805   // Creates a FileWriter for |fd| and prepare to write |entry| to it,
    806   // guaranteeing that the file descriptor is valid and that there's enough
    807   // space on the volume to write out the entry completely and that the file
    808   // is truncated to the correct length.
    809   //
    810   // Returns a valid FileWriter on success, |nullptr| if an error occurred.
    811   static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry* entry) {
    812     const uint32_t declared_length = entry->uncompressed_length;
    813     const off64_t current_offset = lseek64(fd, 0, SEEK_CUR);
    814     if (current_offset == -1) {
    815       ALOGW("Zip: unable to seek to current location on fd %d: %s", fd, strerror(errno));
    816       return nullptr;
    817     }
    818 
    819     int result = 0;
    820 #if defined(__linux__)
    821     if (declared_length > 0) {
    822       // Make sure we have enough space on the volume to extract the compressed
    823       // entry. Note that the call to ftruncate below will change the file size but
    824       // will not allocate space on disk and this call to fallocate will not
    825       // change the file size.
    826       // Note: fallocate is only supported by the following filesystems -
    827       // btrfs, ext4, ocfs2, and xfs. Therefore fallocate might fail with
    828       // EOPNOTSUPP error when issued in other filesystems.
    829       // Hence, check for the return error code before concluding that the
    830       // disk does not have enough space.
    831       result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
    832       if (result == -1 && errno == ENOSPC) {
    833         ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
    834               static_cast<int64_t>(declared_length + current_offset), strerror(errno));
    835         return std::unique_ptr<FileWriter>(nullptr);
    836       }
    837     }
    838 #endif  // __linux__
    839 
    840     result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
    841     if (result == -1) {
    842       ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
    843             static_cast<int64_t>(declared_length + current_offset), strerror(errno));
    844       return std::unique_ptr<FileWriter>(nullptr);
    845     }
    846 
    847     return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
    848   }
    849 
    850   virtual bool Append(uint8_t* buf, size_t buf_size) override {
    851     if (total_bytes_written_ + buf_size > declared_length_) {
    852       ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)",
    853             declared_length_, total_bytes_written_ + buf_size);
    854       return false;
    855     }
    856 
    857     const bool result = android::base::WriteFully(fd_, buf, buf_size);
    858     if (result) {
    859       total_bytes_written_ += buf_size;
    860     } else {
    861       ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
    862     }
    863 
    864     return result;
    865   }
    866  private:
    867   FileWriter(const int fd, const size_t declared_length) :
    868       Writer(),
    869       fd_(fd),
    870       declared_length_(declared_length),
    871       total_bytes_written_(0) {
    872   }
    873 
    874   const int fd_;
    875   const size_t declared_length_;
    876   size_t total_bytes_written_;
    877 };
    878 
    879 // This method is using libz macros with old-style-casts
    880 #pragma GCC diagnostic push
    881 #pragma GCC diagnostic ignored "-Wold-style-cast"
    882 static inline int zlib_inflateInit2(z_stream* stream, int window_bits) {
    883   return inflateInit2(stream, window_bits);
    884 }
    885 #pragma GCC diagnostic pop
    886 
    887 static int32_t InflateEntryToWriter(int fd, const ZipEntry* entry,
    888                                     Writer* writer, uint64_t* crc_out) {
    889   const size_t kBufSize = 32768;
    890   std::vector<uint8_t> read_buf(kBufSize);
    891   std::vector<uint8_t> write_buf(kBufSize);
    892   z_stream zstream;
    893   int zerr;
    894 
    895   /*
    896    * Initialize the zlib stream struct.
    897    */
    898   memset(&zstream, 0, sizeof(zstream));
    899   zstream.zalloc = Z_NULL;
    900   zstream.zfree = Z_NULL;
    901   zstream.opaque = Z_NULL;
    902   zstream.next_in = NULL;
    903   zstream.avail_in = 0;
    904   zstream.next_out = &write_buf[0];
    905   zstream.avail_out = kBufSize;
    906   zstream.data_type = Z_UNKNOWN;
    907 
    908   /*
    909    * Use the undocumented "negative window bits" feature to tell zlib
    910    * that there's no zlib header waiting for it.
    911    */
    912   zerr = zlib_inflateInit2(&zstream, -MAX_WBITS);
    913   if (zerr != Z_OK) {
    914     if (zerr == Z_VERSION_ERROR) {
    915       ALOGE("Installed zlib is not compatible with linked version (%s)",
    916         ZLIB_VERSION);
    917     } else {
    918       ALOGW("Call to inflateInit2 failed (zerr=%d)", zerr);
    919     }
    920 
    921     return kZlibError;
    922   }
    923 
    924   auto zstream_deleter = [](z_stream* stream) {
    925     inflateEnd(stream);  /* free up any allocated structures */
    926   };
    927 
    928   std::unique_ptr<z_stream, decltype(zstream_deleter)> zstream_guard(&zstream, zstream_deleter);
    929 
    930   const uint32_t uncompressed_length = entry->uncompressed_length;
    931 
    932   uint32_t compressed_length = entry->compressed_length;
    933   do {
    934     /* read as much as we can */
    935     if (zstream.avail_in == 0) {
    936       const size_t getSize = (compressed_length > kBufSize) ? kBufSize : compressed_length;
    937       if (!android::base::ReadFully(fd, read_buf.data(), getSize)) {
    938         ALOGW("Zip: inflate read failed, getSize = %zu: %s", getSize, strerror(errno));
    939         return kIoError;
    940       }
    941 
    942       compressed_length -= getSize;
    943 
    944       zstream.next_in = &read_buf[0];
    945       zstream.avail_in = getSize;
    946     }
    947 
    948     /* uncompress the data */
    949     zerr = inflate(&zstream, Z_NO_FLUSH);
    950     if (zerr != Z_OK && zerr != Z_STREAM_END) {
    951       ALOGW("Zip: inflate zerr=%d (nIn=%p aIn=%u nOut=%p aOut=%u)",
    952           zerr, zstream.next_in, zstream.avail_in,
    953           zstream.next_out, zstream.avail_out);
    954       return kZlibError;
    955     }
    956 
    957     /* write when we're full or when we're done */
    958     if (zstream.avail_out == 0 ||
    959       (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) {
    960       const size_t write_size = zstream.next_out - &write_buf[0];
    961       if (!writer->Append(&write_buf[0], write_size)) {
    962         // The file might have declared a bogus length.
    963         return kInconsistentInformation;
    964       }
    965 
    966       zstream.next_out = &write_buf[0];
    967       zstream.avail_out = kBufSize;
    968     }
    969   } while (zerr == Z_OK);
    970 
    971   assert(zerr == Z_STREAM_END);     /* other errors should've been caught */
    972 
    973   // stream.adler holds the crc32 value for such streams.
    974   *crc_out = zstream.adler;
    975 
    976   if (zstream.total_out != uncompressed_length || compressed_length != 0) {
    977     ALOGW("Zip: size mismatch on inflated file (%lu vs %" PRIu32 ")",
    978         zstream.total_out, uncompressed_length);
    979     return kInconsistentInformation;
    980   }
    981 
    982   return 0;
    983 }
    984 
    985 static int32_t CopyEntryToWriter(int fd, const ZipEntry* entry, Writer* writer,
    986                                  uint64_t *crc_out) {
    987   static const uint32_t kBufSize = 32768;
    988   std::vector<uint8_t> buf(kBufSize);
    989 
    990   const uint32_t length = entry->uncompressed_length;
    991   uint32_t count = 0;
    992   uint64_t crc = 0;
    993   while (count < length) {
    994     uint32_t remaining = length - count;
    995 
    996     // Safe conversion because kBufSize is narrow enough for a 32 bit signed
    997     // value.
    998     const size_t block_size = (remaining > kBufSize) ? kBufSize : remaining;
    999     if (!android::base::ReadFully(fd, buf.data(), block_size)) {
   1000       ALOGW("CopyFileToFile: copy read failed, block_size = %zu: %s", block_size, strerror(errno));
   1001       return kIoError;
   1002     }
   1003 
   1004     if (!writer->Append(&buf[0], block_size)) {
   1005       return kIoError;
   1006     }
   1007     crc = crc32(crc, &buf[0], block_size);
   1008     count += block_size;
   1009   }
   1010 
   1011   *crc_out = crc;
   1012 
   1013   return 0;
   1014 }
   1015 
   1016 int32_t ExtractToWriter(ZipArchiveHandle handle,
   1017                         ZipEntry* entry, Writer* writer) {
   1018   ZipArchive* archive = reinterpret_cast<ZipArchive*>(handle);
   1019   const uint16_t method = entry->method;
   1020   off64_t data_offset = entry->offset;
   1021 
   1022   if (lseek64(archive->fd, data_offset, SEEK_SET) != data_offset) {
   1023     ALOGW("Zip: lseek to data at %" PRId64 " failed", static_cast<int64_t>(data_offset));
   1024     return kIoError;
   1025   }
   1026 
   1027   // this should default to kUnknownCompressionMethod.
   1028   int32_t return_value = -1;
   1029   uint64_t crc = 0;
   1030   if (method == kCompressStored) {
   1031     return_value = CopyEntryToWriter(archive->fd, entry, writer, &crc);
   1032   } else if (method == kCompressDeflated) {
   1033     return_value = InflateEntryToWriter(archive->fd, entry, writer, &crc);
   1034   }
   1035 
   1036   if (!return_value && entry->has_data_descriptor) {
   1037     return_value = UpdateEntryFromDataDescriptor(archive->fd, entry);
   1038     if (return_value) {
   1039       return return_value;
   1040     }
   1041   }
   1042 
   1043   // TODO: Fix this check by passing the right flags to inflate2 so that
   1044   // it calculates the CRC for us.
   1045   if (entry->crc32 != crc && false) {
   1046     ALOGW("Zip: crc mismatch: expected %" PRIu32 ", was %" PRIu64, entry->crc32, crc);
   1047     return kInconsistentInformation;
   1048   }
   1049 
   1050   return return_value;
   1051 }
   1052 
   1053 int32_t ExtractToMemory(ZipArchiveHandle handle, ZipEntry* entry,
   1054                         uint8_t* begin, uint32_t size) {
   1055   std::unique_ptr<Writer> writer(new MemoryWriter(begin, size));
   1056   return ExtractToWriter(handle, entry, writer.get());
   1057 }
   1058 
   1059 int32_t ExtractEntryToFile(ZipArchiveHandle handle,
   1060                            ZipEntry* entry, int fd) {
   1061   std::unique_ptr<Writer> writer(FileWriter::Create(fd, entry));
   1062   if (writer.get() == nullptr) {
   1063     return kIoError;
   1064   }
   1065 
   1066   return ExtractToWriter(handle, entry, writer.get());
   1067 }
   1068 
   1069 const char* ErrorCodeString(int32_t error_code) {
   1070   if (error_code > kErrorMessageLowerBound && error_code < kErrorMessageUpperBound) {
   1071     return kErrorMessages[error_code * -1];
   1072   }
   1073 
   1074   return kErrorMessages[0];
   1075 }
   1076 
   1077 int GetFileDescriptor(const ZipArchiveHandle handle) {
   1078   return reinterpret_cast<ZipArchive*>(handle)->fd;
   1079 }
   1080