| 490 | } |
| 491 | |
| 492 | static int32_t FindEntry(const ZipArchive* archive, const int ent, ZipEntry* data) { |
| 493 | const uint16_t nameLen = archive->hash_table[ent].name_length; |
| 494 | |
| 495 | // Recover the start of the central directory entry from the filename |
| 496 | // pointer. The filename is the first entry past the fixed-size data, |
| 497 | // so we can just subtract back from that. |
| 498 | const uint8_t* ptr = archive->hash_table[ent].name; |
| 499 | ptr -= sizeof(CentralDirectoryRecord); |
| 500 | |
| 501 | // This is the base of our mmapped region, we have to sanity check that |
| 502 | // the name that's in the hash table is a pointer to a location within |
| 503 | // this mapped region. |
| 504 | const uint8_t* base_ptr = archive->central_directory.GetBasePtr(); |
| 505 | if (ptr < base_ptr || ptr > base_ptr + archive->central_directory.GetMapLength()) { |
| 506 | //chensenhuaALOGW("Zip: Invalid entry pointer"); |
| 507 | return kInvalidOffset; |
| 508 | } |
| 509 | |
| 510 | const CentralDirectoryRecord* cdr = reinterpret_cast<const CentralDirectoryRecord*>(ptr); |
| 511 | |
| 512 | // The offset of the start of the central directory in the zipfile. |
| 513 | // We keep this lying around so that we can sanity check all our lengths |
| 514 | // and our per-file structures. |
| 515 | const off64_t cd_offset = archive->directory_offset; |
| 516 | |
| 517 | // Fill out the compression method, modification time, crc32 |
| 518 | // and other interesting attributes from the central directory. These |
| 519 | // will later be compared against values from the local file header. |
| 520 | data->method = cdr->compression_method; |
| 521 | data->mod_time = cdr->last_mod_date << 16 | cdr->last_mod_time; |
| 522 | data->crc32 = cdr->crc32; |
| 523 | data->compressed_length = cdr->compressed_size; |
| 524 | data->uncompressed_length = cdr->uncompressed_size; |
| 525 | |
| 526 | // Figure out the local header offset from the central directory. The |
| 527 | // actual file data will begin after the local header and the name / |
| 528 | // extra comments. |
| 529 | const off64_t local_header_offset = cdr->local_file_header_offset; |
| 530 | if (local_header_offset + static_cast<off64_t>(sizeof(LocalFileHeader)) >= cd_offset) { |
| 531 | //chensenhuaALOGW("Zip: bad local hdr offset in zip"); |
| 532 | return kInvalidOffset; |
| 533 | } |
| 534 | |
| 535 | uint8_t lfh_buf[sizeof(LocalFileHeader)]; |
| 536 | if (!archive->mapped_zip.ReadAtOffset(lfh_buf, sizeof(lfh_buf), local_header_offset)) { |
| 537 | //chensenhua ALOGW("Zip: failed reading lfh name from offset %" PRId64, |
| 538 | //chensenhua static_cast<int64_t>(local_header_offset)); |
| 539 | return kIoError; |
| 540 | } |
| 541 | |
| 542 | const LocalFileHeader* lfh = reinterpret_cast<const LocalFileHeader*>(lfh_buf); |
| 543 | |
| 544 | if (lfh->lfh_signature != LocalFileHeader::kSignature) { |
| 545 | //chensenhua ALOGW("Zip: didn't find signature at start of lfh, offset=%" PRId64, |
| 546 | //chensenhua static_cast<int64_t>(local_header_offset)); |
| 547 | return kInvalidOffset; |
| 548 | } |
| 549 |
no test coverage detected