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