1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "zip_file.h" 17 18#include <ostream> 19#include "securec.h" 20#include "zip_file_reader.h" 21 22namespace panda { 23namespace ecmascript { 24namespace { 25constexpr uint32_t MAX_FILE_NAME = 4096; 26constexpr uint32_t UNZIP_BUFFER_SIZE = 1024; 27constexpr uint32_t UNZIP_BUF_IN_LEN = 160 * UNZIP_BUFFER_SIZE; // in buffer length: 160KB 28constexpr uint32_t UNZIP_BUF_OUT_LEN = 320 * UNZIP_BUFFER_SIZE; // out buffer length: 320KB 29constexpr uint32_t LOCAL_HEADER_SIGNATURE = 0x04034b50; 30constexpr uint32_t CENTRAL_SIGNATURE = 0x02014b50; 31constexpr uint32_t EOCD_SIGNATURE = 0x06054b50; 32constexpr uint32_t DATA_DESC_SIGNATURE = 0x08074b50; 33constexpr uint32_t FLAG_DATA_DESC = 0x8; 34constexpr uint8_t INFLATE_ERROR_TIMES = 5; 35const char FILE_SEPARATOR_CHAR = '/'; 36} // namespace 37 38ZipEntry::ZipEntry(const CentralDirEntry ¢ralEntry) 39{ 40 compressionMethod = centralEntry.compressionMethod; 41 uncompressedSize = centralEntry.uncompressedSize; 42 compressedSize = centralEntry.compressedSize; 43 localHeaderOffset = centralEntry.localHeaderOffset; 44 crc = centralEntry.crc; 45 flags = centralEntry.flags; 46 modifiedTime = centralEntry.modifiedTime; 47 modifiedDate = centralEntry.modifiedDate; 48} 49 50ZipFile::ZipFile(const std::string &pathName) : pathName_(pathName) 51{ 52 dirRoot_ = std::make_shared<DirTreeNode>(); 53} 54 55ZipFile::~ZipFile() 56{ 57 Close(); 58} 59 60void ZipFile::SetContentLocation(const ZipPos start, const size_t length) 61{ 62 if (isOpen_) { 63 return; 64 } 65 fileStartPos_ = start; 66 fileLength_ = length; 67} 68 69bool ZipFile::CheckEndDir(const EndDir &endDir) const 70{ 71 size_t lenEndDir = sizeof(EndDir); 72 if ((endDir.numDisk != 0) || (endDir.signature != EOCD_SIGNATURE) || (endDir.startDiskOfCentralDir != 0) || 73 (endDir.offset >= fileLength_) || (endDir.totalEntriesInThisDisk != endDir.totalEntries) || 74 (endDir.commentLen != 0) || 75 // central dir can't overlap end of central dir 76 ((endDir.offset + endDir.sizeOfCentralDir + lenEndDir) > fileLength_)) { 77 return false; 78 } 79 return true; 80} 81 82bool ZipFile::ParseEndDirectory() 83{ 84 size_t endDirLen = sizeof(EndDir); 85 size_t endFilePos = fileStartPos_ + fileLength_; 86 87 if (fileLength_ <= endDirLen) { 88 return false; 89 } 90 91 size_t eocdPos = endFilePos - endDirLen; 92 if (!zipFileReader_->ReadBuffer(reinterpret_cast<uint8_t*>(&endDir_), eocdPos, sizeof(EndDir))) { 93 return false; 94 } 95 96 centralDirPos_ = endDir_.offset + fileStartPos_; 97 98 return CheckEndDir(endDir_); 99} 100 101bool ZipFile::ParseOneEntry(uint8_t* &entryPtr) 102{ 103 if (entryPtr == nullptr) { 104 return false; 105 } 106 107 CentralDirEntry directoryEntry; 108 if (memcpy_s(&directoryEntry, sizeof(CentralDirEntry), entryPtr, sizeof(CentralDirEntry)) != EOK) { 109 return false; 110 } 111 112 if (directoryEntry.signature != CENTRAL_SIGNATURE) { 113 return false; 114 } 115 116 entryPtr += sizeof(CentralDirEntry); 117 size_t fileLength = (directoryEntry.nameSize >= MAX_FILE_NAME) ? (MAX_FILE_NAME - 1) : directoryEntry.nameSize; 118 std::string fileName(fileLength, 0); 119 if (memcpy_s(&(fileName[0]), fileLength, entryPtr, fileLength) != EOK) { 120 return false; 121 } 122 123 ZipEntry currentEntry(directoryEntry); 124 currentEntry.fileName = fileName; 125 entriesMap_[fileName] = currentEntry; 126 AddEntryToTree(fileName); 127 entryPtr += directoryEntry.nameSize + directoryEntry.extraSize + directoryEntry.commentSize; 128 return true; 129} 130 131void ZipFile::AddEntryToTree(const std::string &fileName) 132{ 133 size_t cur = 0; 134 auto parent = dirRoot_; 135 do { 136 while (cur < fileName.size() && fileName[cur] == FILE_SEPARATOR_CHAR) { 137 cur++; 138 } 139 if (cur >= fileName.size()) { 140 break; 141 } 142 auto next = fileName.find_first_of(FILE_SEPARATOR_CHAR, cur); 143 auto nodeName = fileName.substr(cur, next - cur); 144 auto it = parent->children.find(nodeName); 145 if (it != parent->children.end()) { 146 parent = it->second; 147 } else { 148 auto node = std::make_shared<DirTreeNode>(); 149 parent->children.emplace(nodeName, node); 150 parent = node; 151 } 152 cur = next; 153 } while (cur != std::string::npos); 154} 155 156bool ZipFile::ParseAllEntries() 157{ 158 auto centralData = zipFileReader_->ReadBuffer(static_cast<size_t>(centralDirPos_), 159 static_cast<size_t>(endDir_.sizeOfCentralDir)); 160 if (centralData.empty()) { 161 return false; 162 } 163 164 bool ret = true; 165 uint8_t *entryPtr = reinterpret_cast<uint8_t *>(centralData.data()); 166 for (uint16_t i = 0; i < endDir_.totalEntries; i++) { 167 if (!ParseOneEntry(entryPtr)) { 168 ret = false; 169 break; 170 } 171 } 172 173 return ret; 174} 175 176bool ZipFile::Open() 177{ 178 if (isOpen_) { 179 return true; 180 } 181 182 if (pathName_.length() > PATH_MAX) { 183 return false; 184 } 185 186 zipFileReader_ = ZipFileReader::CreateZipFileReader(pathName_); 187 if (!zipFileReader_) { 188 return false; 189 } 190 191 if (fileLength_ == 0) { 192 auto fileLength = zipFileReader_->GetFileLen(); 193 fileLength_ = static_cast<ZipPos>(fileLength); 194 if (fileStartPos_ >= fileLength_) { 195 zipFileReader_.reset(); 196 return false; 197 } 198 199 fileLength_ -= fileStartPos_; 200 } 201 202 bool result = ParseEndDirectory(); 203 if (result) { 204 result = ParseAllEntries(); 205 } 206 // it means open file success. 207 isOpen_ = true; 208 return result; 209} 210 211void ZipFile::Close() 212{ 213 if (!isOpen_ || zipFileReader_ == nullptr) { 214 return; 215 } 216 217 isOpen_ = false; 218 entriesMap_.clear(); 219 dirRoot_->children.clear(); 220 pathName_ = ""; 221 222 zipFileReader_.reset(); 223} 224 225// Get all file zipEntry in this file 226const ZipEntryMap &ZipFile::GetAllEntries() const 227{ 228 return entriesMap_; 229} 230 231bool ZipFile::HasEntry(const std::string &entryName) const 232{ 233 return entriesMap_.find(entryName) != entriesMap_.end(); 234} 235 236bool ZipFile::IsDirExist(const std::string &dir) const 237{ 238 if (dir.empty()) { 239 return false; 240 } 241 242 size_t cur = 0; 243 auto parent = dirRoot_; 244 do { 245 while (cur < dir.size() && dir[cur] == FILE_SEPARATOR_CHAR) { 246 cur++; 247 } 248 if (cur >= dir.size()) { 249 break; 250 } 251 auto next = dir.find_first_of(FILE_SEPARATOR_CHAR, cur); 252 auto nodeName = dir.substr(cur, next - cur); 253 auto it = parent->children.find(nodeName); 254 if (it == parent->children.end()) { 255 return false; 256 } 257 parent = it->second; 258 cur = next; 259 } while (cur != std::string::npos); 260 261 return true; 262} 263namespace { 264void GetTreeFileList(const std::shared_ptr<DirTreeNode> &root, const std::string &rootPath, 265 std::vector<std::string> &assetList) 266{ 267 if (root->children.empty()) { 268 assetList.push_back(rootPath); 269 } else { 270 for (const auto &child : root->children) { 271 GetTreeFileList(child.second, rootPath + "/" + child.first, assetList); 272 } 273 } 274} 275} 276 277void ZipFile::GetAllFileList(const std::string &srcPath, std::vector<std::string> &assetList) 278{ 279 if (srcPath.empty()) { 280 return; 281 } 282 283 auto rootName = srcPath.back() == FILE_SEPARATOR_CHAR ? 284 srcPath.substr(0, srcPath.length() - 1) : srcPath; 285 286 size_t cur = 0; 287 auto parent = dirRoot_; 288 do { 289 while (cur < rootName.size() && rootName[cur] == FILE_SEPARATOR_CHAR) { 290 cur++; 291 } 292 if (cur >= rootName.size()) { 293 break; 294 } 295 auto next = rootName.find_first_of(FILE_SEPARATOR_CHAR, cur); 296 auto nodeName = (next == std::string::npos) ? rootName.substr(cur) : 297 rootName.substr(cur, next - cur); 298 auto it = parent->children.find(nodeName); 299 if (it == parent->children.end()) { 300 return; 301 } 302 parent = it->second; 303 cur = next; 304 } while (cur != std::string::npos); 305 306 GetTreeFileList(parent, rootName, assetList); 307} 308 309void ZipFile::GetChildNames(const std::string &srcPath, std::set<std::string> &fileSet) 310{ 311 if (srcPath.empty()) { 312 return; 313 } 314 315 size_t cur = 0; 316 auto parent = dirRoot_; 317 do { 318 while (cur < srcPath.size() && srcPath[cur] == FILE_SEPARATOR_CHAR) { 319 cur++; 320 } 321 if (cur >= srcPath.size()) { 322 break; 323 } 324 auto next = srcPath.find_first_of(FILE_SEPARATOR_CHAR, cur); 325 auto nodeName = srcPath.substr(cur, next - cur); 326 auto it = parent->children.find(nodeName); 327 if (it == parent->children.end()) { 328 return; 329 } 330 parent = it->second; 331 cur = next; 332 } while (cur != std::string::npos); 333 334 for (const auto &child : parent->children) { 335 fileSet.insert(child.first); 336 } 337} 338 339bool ZipFile::GetEntry(const std::string &entryName, ZipEntry &resultEntry) const 340{ 341 auto iter = entriesMap_.find(entryName); 342 if (iter != entriesMap_.end()) { 343 resultEntry = iter->second; 344 return true; 345 } 346 return false; 347} 348 349size_t ZipFile::GetLocalHeaderSize(const uint16_t nameSize, const uint16_t extraSize) const 350{ 351 return sizeof(LocalHeader) + nameSize + extraSize; 352} 353 354bool ZipFile::CheckDataDesc(const ZipEntry &zipEntry, const LocalHeader &localHeader) const 355{ 356 uint32_t crcLocal = 0; 357 uint32_t compressedLocal = 0; 358 uint32_t uncompressedLocal = 0; 359 360 if (localHeader.flags & FLAG_DATA_DESC) { // use data desc 361 DataDesc dataDesc; 362 auto descPos = zipEntry.localHeaderOffset + GetLocalHeaderSize(localHeader.nameSize, localHeader.extraSize); 363 descPos += fileStartPos_ + zipEntry.compressedSize; 364 365 if (!zipFileReader_->ReadBuffer(reinterpret_cast<uint8_t*>(&dataDesc), descPos, sizeof(DataDesc))) { 366 return false; 367 } 368 369 if (dataDesc.signature != DATA_DESC_SIGNATURE) { 370 return false; 371 } 372 373 crcLocal = dataDesc.crc; 374 compressedLocal = dataDesc.compressedSize; 375 uncompressedLocal = dataDesc.uncompressedSize; 376 } else { 377 crcLocal = localHeader.crc; 378 compressedLocal = localHeader.compressedSize; 379 uncompressedLocal = localHeader.uncompressedSize; 380 } 381 382 if ((zipEntry.crc != crcLocal) || (zipEntry.compressedSize != compressedLocal) || 383 (zipEntry.uncompressedSize != uncompressedLocal)) { 384 return false; 385 } 386 387 return true; 388} 389 390bool ZipFile::CheckCoherencyLocalHeader(const ZipEntry &zipEntry, uint16_t &extraSize) const 391{ 392 // current only support store and Z_DEFLATED method 393 if ((zipEntry.compressionMethod != Z_DEFLATED) && (zipEntry.compressionMethod != 0)) { 394 return false; 395 } 396 397 auto nameSize = zipEntry.fileName.length(); 398 auto startPos = fileStartPos_ + zipEntry.localHeaderOffset; 399 size_t buffSize = sizeof(LocalHeader) + nameSize; 400 auto buff = zipFileReader_->ReadBuffer(startPos, buffSize); 401 if (buff.size() < buffSize) { 402 return false; 403 } 404 405 LocalHeader localHeader = {0}; 406 if (memcpy_s(&localHeader, sizeof(LocalHeader), buff.data(), sizeof(LocalHeader)) != EOK) { 407 return false; 408 } 409 if ((localHeader.signature != LOCAL_HEADER_SIGNATURE) || 410 (zipEntry.compressionMethod != localHeader.compressionMethod)) { 411 return false; 412 } 413 414 if (localHeader.nameSize != nameSize && nameSize < MAX_FILE_NAME - 1) { 415 return false; 416 } 417 std::string fileName = buff.substr(sizeof(LocalHeader)); 418 if (zipEntry.fileName != fileName) { 419 return false; 420 } 421 422 if (!CheckDataDesc(zipEntry, localHeader)) { 423 return false; 424 } 425 426 extraSize = localHeader.extraSize; 427 return true; 428} 429 430size_t ZipFile::GetEntryStart(const ZipEntry &zipEntry, const uint16_t extraSize) const 431{ 432 ZipPos startOffset = zipEntry.localHeaderOffset; 433 // get data offset, add signature+localheader+namesize+extrasize 434 startOffset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize); 435 startOffset += fileStartPos_; // add file start relative to file stream 436 437 return startOffset; 438} 439 440bool ZipFile::UnzipWithStore(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const 441{ 442 auto startPos = GetEntryStart(zipEntry, extraSize); 443 uint32_t remainSize = zipEntry.compressedSize; 444 while (remainSize > 0) { 445 size_t readLen = (remainSize > UNZIP_BUF_OUT_LEN) ? UNZIP_BUF_OUT_LEN : remainSize; 446 std::string readBuffer = zipFileReader_->ReadBuffer(startPos, readLen); 447 if (readBuffer.empty()) { 448 return false; 449 } 450 remainSize -= readLen; 451 startPos += readLen; 452 dest.write(readBuffer.data(), readBuffer.length()); 453 } 454 return true; 455} 456 457bool ZipFile::InitZStream(z_stream &zstream) const 458{ 459 // init zlib stream 460 if (memset_s(&zstream, sizeof(z_stream), 0, sizeof(z_stream))) { 461 return false; 462 } 463 int32_t zlibErr = inflateInit2(&zstream, -MAX_WBITS); 464 if (zlibErr != Z_OK) { 465 return false; 466 } 467 468 BytePtr bufOut = new (std::nothrow) Byte[UNZIP_BUF_OUT_LEN]; 469 if (bufOut == nullptr) { 470 return false; 471 } 472 473 BytePtr bufIn = new (std::nothrow) Byte[UNZIP_BUF_IN_LEN]; 474 if (bufIn == nullptr) { 475 delete[] bufOut; 476 return false; 477 } 478 zstream.next_out = bufOut; 479 zstream.next_in = bufIn; 480 zstream.avail_out = UNZIP_BUF_OUT_LEN; 481 return true; 482} 483 484bool ZipFile::ReadZStream(const BytePtr &buffer, z_stream &zstream, uint32_t &remainCompressedSize, 485 size_t &startPos) const 486{ 487 if (zstream.avail_in == 0) { 488 size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize; 489 if (!zipFileReader_->ReadBuffer(buffer, startPos, remainBytes)) { 490 return false; 491 } 492 493 remainCompressedSize -= remainBytes; 494 startPos += remainBytes; 495 zstream.avail_in = remainBytes; 496 zstream.next_in = buffer; 497 } 498 return true; 499} 500 501bool ZipFile::UnzipWithInflated(const ZipEntry &zipEntry, const uint16_t extraSize, std::ostream &dest) const 502{ 503 z_stream zstream; 504 if (!InitZStream(zstream)) { 505 return false; 506 } 507 508 auto startPos = GetEntryStart(zipEntry, extraSize); 509 510 BytePtr bufIn = zstream.next_in; 511 BytePtr bufOut = zstream.next_out; 512 513 bool ret = true; 514 int32_t zlibErr = Z_OK; 515 uint32_t remainCompressedSize = zipEntry.compressedSize; 516 size_t inflateLen = 0; 517 uint8_t errorTimes = 0; 518 while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) { 519 if (!ReadZStream(bufIn, zstream, remainCompressedSize, startPos)) { 520 ret = false; 521 break; 522 } 523 524 zlibErr = inflate(&zstream, Z_SYNC_FLUSH); 525 if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) { 526 ret = false; 527 break; 528 } 529 530 inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out; 531 if (inflateLen > 0) { 532 dest.write((const char *)bufOut, inflateLen); 533 zstream.next_out = bufOut; 534 zstream.avail_out = UNZIP_BUF_OUT_LEN; 535 errorTimes = 0; 536 } else { 537 errorTimes++; 538 } 539 if (errorTimes >= INFLATE_ERROR_TIMES) { 540 ret = false; 541 break; 542 } 543 } 544 545 // free all dynamically allocated data structures except the next_in and next_out for this stream. 546 zlibErr = inflateEnd(&zstream); 547 if (zlibErr != Z_OK) { 548 ret = false; 549 } 550 551 delete[] bufOut; 552 delete[] bufIn; 553 return ret; 554} 555 556ZipPos ZipFile::GetEntryDataOffset(const ZipEntry &zipEntry, const uint16_t extraSize) const 557{ 558 // get entry data offset relative file 559 ZipPos offset = zipEntry.localHeaderOffset; 560 561 offset += GetLocalHeaderSize(zipEntry.fileName.length(), extraSize); 562 offset += fileStartPos_; 563 564 return offset; 565} 566 567bool ZipFile::GetDataOffsetRelative(const std::string &file, ZipPos &offset, uint32_t &length) const 568{ 569 ZipEntry zipEntry; 570 if (!GetEntry(file, zipEntry)) { 571 return false; 572 } 573 574 return GetDataOffsetRelative(zipEntry, offset, length); 575} 576 577bool ZipFile::GetDataOffsetRelative(const ZipEntry &zipEntry, ZipPos &offset, uint32_t &length) const 578{ 579 uint16_t extraSize = 0; 580 if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) { 581 return false; 582 } 583 584 offset = GetEntryDataOffset(zipEntry, extraSize); 585 length = zipEntry.compressedSize; 586 return true; 587} 588 589bool ZipFile::ExtractFile(const std::string &file, std::ostream &dest) const 590{ 591 ZipEntry zipEntry; 592 if (!GetEntry(file, zipEntry)) { 593 return false; 594 } 595 596 uint16_t extraSize = 0; 597 if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) { 598 return false; 599 } 600 601 bool ret = true; 602 if (zipEntry.compressionMethod == 0) { 603 ret = UnzipWithStore(zipEntry, extraSize, dest); 604 } else { 605 ret = UnzipWithInflated(zipEntry, extraSize, dest); 606 } 607 608 return ret; 609} 610 611bool ZipFile::ReadZStreamFromMMap(const BytePtr &buffer, void* &dataPtr, 612 z_stream &zstream, uint32_t &remainCompressedSize) const 613{ 614 if (!dataPtr) { 615 return false; 616 } 617 618 uint8_t *srcDataPtr = static_cast<uint8_t *>(dataPtr); 619 if (zstream.avail_in == 0) { 620 size_t remainBytes = (remainCompressedSize > UNZIP_BUF_IN_LEN) ? UNZIP_BUF_IN_LEN : remainCompressedSize; 621 size_t readBytes = sizeof(Byte) * remainBytes; 622 if (memcpy_s(buffer, readBytes, srcDataPtr, readBytes) != EOK) { 623 return false; 624 } 625 srcDataPtr += readBytes; 626 remainCompressedSize -= remainBytes; 627 zstream.avail_in = remainBytes; 628 zstream.next_in = buffer; 629 } 630 dataPtr = srcDataPtr; 631 return true; 632} 633 634std::unique_ptr<FileMapper> ZipFile::CreateFileMapper(const std::string &fileName, FileMapperType type) const 635{ 636 ZipEntry zipEntry; 637 if (!GetEntry(fileName, zipEntry)) { 638 return nullptr; 639 } 640 641 ZipPos offset = 0; 642 uint32_t length = 0; 643 if (!GetDataOffsetRelative(zipEntry, offset, length)) { 644 return nullptr; 645 } 646 bool compress = zipEntry.compressionMethod > 0; 647 if (type == FileMapperType::SAFE_ABC && compress) { 648 } 649 std::unique_ptr<FileMapper> fileMapper = std::make_unique<FileMapper>(); 650 auto result = false; 651 if (type == FileMapperType::NORMAL_MEM) { 652 result = fileMapper->CreateFileMapper(zipFileReader_, fileName, offset, length, compress); 653 } else { 654 result = fileMapper->CreateFileMapper(fileName, compress, zipFileReader_->GetFd(), offset, length, type); 655 if (result && type == FileMapperType::SAFE_ABC) { 656 zipFileReader_->SetClosable(false); 657 } 658 } 659 660 if (!result) { 661 return nullptr; 662 } 663 return fileMapper; 664} 665 666bool ZipFile::UnzipWithInflatedFromMMap(const ZipEntry &zipEntry, [[maybe_unused]] const uint16_t extraSize, 667 void *mmapDataPtr, std::unique_ptr<uint8_t[]> &dataPtr, size_t &len) const 668{ 669 z_stream zstream; 670 if (!InitZStream(zstream)) { 671 return false; 672 } 673 674 BytePtr bufIn = zstream.next_in; 675 BytePtr bufOut = zstream.next_out; 676 677 bool ret = true; 678 int32_t zlibErr = Z_OK; 679 uint32_t remainCompressedSize = zipEntry.compressedSize; 680 size_t inflateLen = 0; 681 uint8_t errorTimes = 0; 682 683 len = zipEntry.uncompressedSize; 684 dataPtr = std::make_unique<uint8_t[]>(len); 685 if (!dataPtr) { 686 delete[] bufOut; 687 delete[] bufIn; 688 return false; 689 } 690 uint8_t *dstDataPtr = static_cast<uint8_t *>(dataPtr.get()); 691 void *mmapSrcDataPtr = mmapDataPtr; 692 693 while ((remainCompressedSize > 0) || (zstream.avail_in > 0)) { 694 if (!ReadZStreamFromMMap(bufIn, mmapSrcDataPtr, zstream, remainCompressedSize)) { 695 ret = false; 696 break; 697 } 698 699 zlibErr = inflate(&zstream, Z_SYNC_FLUSH); 700 if ((zlibErr >= Z_OK) && (zstream.msg != nullptr)) { 701 ret = false; 702 break; 703 } 704 705 inflateLen = UNZIP_BUF_OUT_LEN - zstream.avail_out; 706 if (inflateLen > 0) { 707 if (memcpy_s(dstDataPtr, inflateLen, bufOut, inflateLen) != EOK) { 708 ret = false; 709 break; 710 } 711 712 dstDataPtr += inflateLen; 713 zstream.next_out = bufOut; 714 zstream.avail_out = UNZIP_BUF_OUT_LEN; 715 errorTimes = 0; 716 } else { 717 errorTimes++; 718 } 719 if (errorTimes >= INFLATE_ERROR_TIMES) { 720 ret = false; 721 break; 722 } 723 } 724 725 // free all dynamically allocated data structures except the next_in and next_out for this stream. 726 zlibErr = inflateEnd(&zstream); 727 if (zlibErr != Z_OK) { 728 ret = false; 729 } 730 731 delete[] bufOut; 732 delete[] bufIn; 733 return ret; 734} 735 736bool ZipFile::ExtractToBufByName(const std::string &fileName, std::unique_ptr<uint8_t[]> &dataPtr, 737 size_t &len) const 738{ 739 ZipEntry zipEntry; 740 if (!GetEntry(fileName, zipEntry)) { 741 return false; 742 } 743 uint16_t extraSize = 0; 744 if (!CheckCoherencyLocalHeader(zipEntry, extraSize)) { 745 return false; 746 } 747 748 ZipPos offset = GetEntryDataOffset(zipEntry, extraSize); 749 uint32_t length = zipEntry.compressedSize; 750 auto dataTmp = std::make_unique<uint8_t[]>(length); 751 if (!zipFileReader_->ReadBuffer(dataTmp.get(), offset, length)) { 752 dataTmp.reset(); 753 return false; 754 } 755 756 if (zipEntry.compressionMethod > 0) { 757 return UnzipWithInflatedFromMMap(zipEntry, extraSize, dataTmp.get(), dataPtr, len); 758 } 759 760 len = length; 761 dataPtr = std::move(dataTmp); 762 763 return true; 764} 765} // namespace AbilityBase 766} // namespace OHOS 767