From 1d0a14c1f7fd279bccb7b94fd3898aab7285993d Mon Sep 17 00:00:00 2001 From: liuyahui Date: Mon, 30 Oct 2023 11:36:20 +0800 Subject: [PATCH] fix IsASTC null pointer Signed-off-by: liuyahui --- .../innerkitsimpl/codec/src/image_source.cpp | 9 ++- .../stream/include/file_source_stream.h | 4 +- .../stream/src/file_source_stream.cpp | 64 ++++++++++++++++--- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/frameworks/innerkitsimpl/codec/src/image_source.cpp b/frameworks/innerkitsimpl/codec/src/image_source.cpp index 8fe2bb1cc..bf0e701fe 100644 --- a/frameworks/innerkitsimpl/codec/src/image_source.cpp +++ b/frameworks/innerkitsimpl/codec/src/image_source.cpp @@ -1949,7 +1949,7 @@ unique_ptr ImageSource::CreatePixelMapForYUV(uint32_t &errorCode) bool ImageSource::IsASTC(const uint8_t *fileData, size_t fileSize) { if (fileData == nullptr || fileSize < ASTC_HEADER_SIZE) { - IMAGE_LOGE("[ImageSource]IsASTC fileData incorrect."); + IMAGE_LOGE("[ImageSource]IsASTC fileData incorrect, file size is %{public}zu.", fileSize); return false; } unsigned int magicVal = static_cast(fileData[0]) + (static_cast(fileData[1]) << 8) + @@ -2010,7 +2010,10 @@ unique_ptr ImageSource::CreatePixelMapForASTC(uint32_t &errorCode) size_t fileSize = sourceStreamPtr_->GetStreamSize(); if (sourceStreamPtr_->GetStreamType() == ImagePlugin::FILE_STREAM_TYPE) { void *fdBuffer = new int32_t(); - *static_cast(fdBuffer) = static_cast(sourceStreamPtr_.get())->GetMMapFd(); + if (!static_cast(sourceStreamPtr_.get())->GetMMapFd(*static_cast(fdBuffer))) { + IMAGE_LOGE("[ImageSource] get mmap fd failed."); + return nullptr; + } pixelAstc->SetPixelsAddr(sourceStreamPtr_->GetDataPtr(), fdBuffer, fileSize, AllocatorType::SHARE_MEM_ALLOC, nullptr); } else if (sourceStreamPtr_->GetStreamType() == ImagePlugin::BUFFER_SOURCE_TYPE) { @@ -2046,7 +2049,7 @@ unique_ptr ImageSource::CreatePixelMapForASTC(uint32_t &errorCode) bool ImageSource::GetASTCInfo(const uint8_t *fileData, size_t fileSize, ASTCInfo& astcInfo) { if (fileData == nullptr || fileSize < ASTC_HEADER_SIZE) { - IMAGE_LOGE("[ImageSource]GetASTCInfo fileData incorrect."); + IMAGE_LOGE("[ImageSource]GetASTCInfo fileData incorrect, file size is %{public}zu.", fileSize); return false; } astcInfo.size.width = static_cast(fileData[ASTC_HEADER_DIM_X]) + diff --git a/frameworks/innerkitsimpl/stream/include/file_source_stream.h b/frameworks/innerkitsimpl/stream/include/file_source_stream.h index 7e38bf412..bafbe56bd 100644 --- a/frameworks/innerkitsimpl/stream/include/file_source_stream.h +++ b/frameworks/innerkitsimpl/stream/include/file_source_stream.h @@ -43,7 +43,8 @@ public: uint8_t *GetDataPtr() override; uint32_t GetStreamType() override; ImagePlugin::OutputDataStream* ToOutputDataStream() override; - int GetMMapFd(); + // mmapFd_ will be dup, owner of new fd need call close() + bool GetMMapFd(int& res); private: DISALLOW_COPY_AND_MOVE(FileSourceStream); @@ -57,7 +58,6 @@ private: uint8_t *readBuffer_ = nullptr; uint8_t *fileData_ = nullptr; int mmapFd_ = -1; - bool mmapFdPassedOn_ = false; }; } // namespace Media } // namespace OHOS diff --git a/frameworks/innerkitsimpl/stream/src/file_source_stream.cpp b/frameworks/innerkitsimpl/stream/src/file_source_stream.cpp index 0bfd6e4ce..4725f6817 100644 --- a/frameworks/innerkitsimpl/stream/src/file_source_stream.cpp +++ b/frameworks/innerkitsimpl/stream/src/file_source_stream.cpp @@ -23,6 +23,7 @@ #if !defined(_WIN32) && !defined(_APPLE) &&!defined(IOS_PLATFORM) &&!defined(A_PLATFORM) #include +#include "ashmem.h" #define SUPPORT_MMAP #endif @@ -218,7 +219,7 @@ uint32_t FileSourceStream::Tell() bool FileSourceStream::GetData(uint32_t desiredSize, uint8_t *outBuffer, uint32_t bufferSize, uint32_t &readSize) { if (fileSize_ == fileOffset_) { - IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize%{public}zu.", fileOffset_, fileSize_); + IMAGE_LOGE("[FileSourceStream]read finish, offset:%{public}zu ,dataSize:%{public}zu.", fileOffset_, fileSize_); return false; } if (desiredSize > (fileSize_ - fileOffset_)) { @@ -293,14 +294,46 @@ uint8_t *FileSourceStream::GetDataPtr() return fileData_; } #ifdef SUPPORT_MMAP - if (!DupFd(filePtr_, mmapFd_)) { + int fd = -1; + if (!DupFd(filePtr_, fd)) { return nullptr; } - auto mmptr = ::mmap(nullptr, fileSize_, PROT_READ, MAP_SHARED, mmapFd_, 0); + auto mmptr = ::mmap(nullptr, fileSize_, PROT_READ, MAP_SHARED, fd, 0); if (mmptr == MAP_FAILED) { HiLog::Error(LABEL, "[FileSourceStream] mmap failed, errno:%{public}d", errno); - return nullptr; - } + ::close(fd); + + // fallback to read entire file into shared memory + fd = AshmemCreate("FileSourceStream GetDataPtr", fileSize_); + if (fd < 0) { + IMAGE_LOGE("[FileSourceStream]GetDataPtr AshmemCreate fd < 0."); + return nullptr; + } + int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE); + if (result < 0) { + IMAGE_LOGE("[FileSourceStream]GetDataPtr AshmemSetProt error."); + ::close(fd); + return nullptr; + } + mmptr = ::mmap(nullptr, fileSize_, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (mmptr == MAP_FAILED || mmptr == nullptr) { + IMAGE_LOGE("[FileSourceStream]GetDataPtr data is nullptr."); + ::close(fd); + return nullptr; + } + uint32_t readSize = 0; + auto oldFileOffset = fileOffset_; + Seek(0); + if (!Peek(fileSize_, static_cast(mmptr), fileSize_, readSize)) { + Seek(oldFileOffset); + IMAGE_LOGE("[FileSourceStream] read file data into mmptr failed."); + ::munmap(static_cast(mmptr), fileSize_); + ::close(fd); + return nullptr; + } + Seek(oldFileOffset); + } + mmapFd_ = fd; fileData_ = static_cast(mmptr); #endif return fileData_; @@ -317,10 +350,11 @@ void FileSourceStream::ResetReadBuffer() free(readBuffer_); readBuffer_ = nullptr; } - if (fileData_ != nullptr && !mmapFdPassedOn_) { + if (fileData_ != nullptr && mmapFd_ >= 0) { #ifdef SUPPORT_MMAP ::munmap(fileData_, fileSize_); - close(mmapFd_); + ::close(mmapFd_); + mmapFd_ = -1; #endif } fileData_ = nullptr; @@ -336,10 +370,20 @@ OutputDataStream* FileSourceStream::ToOutputDataStream() return new (std::nothrow) FilePackerStream(dupFd); } -int FileSourceStream::GetMMapFd() +bool FileSourceStream::GetMMapFd(int& res) { - mmapFdPassedOn_ = true; - return mmapFd_; + if (mmapFd_ < 0) { + res = -1; + return false; + } + res = dup(mmapFd_); + if (res < 0) { + IMAGE_LOGE("[FileSourceStream] fail to get mmap fd."); + return false; + } + ::close(mmapFd_); + mmapFd_ = -1; + return true; } } // namespace Media } // namespace OHOS -- Gitee