From a2e4df43a3e5634a3ab8742c6ca8b8946c5ce0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Mon, 7 Aug 2023 18:25:37 +0200 Subject: [PATCH] tinyexr: Sync with upstream 1.0.7 (cherry picked from commit b70e2af3b7f960370f00c11a028fb8ae0ea034d8) --- thirdparty/tinyexr/tinyexr.h | 96 ++++++++++++++++++++++++++++++++---- 1 file changed, 87 insertions(+), 9 deletions(-) diff --git a/thirdparty/tinyexr/tinyexr.h b/thirdparty/tinyexr/tinyexr.h index d08e97f6cd7..e5ac54a5068 100644 --- a/thirdparty/tinyexr/tinyexr.h +++ b/thirdparty/tinyexr/tinyexr.h @@ -114,6 +114,11 @@ extern "C" { #define TINYEXR_USE_STB_ZLIB (0) #endif +// Use nanozlib. +#ifndef TINYEXR_USE_NANOZLIB +#define TINYEXR_USE_NANOZLIB (0) +#endif + // Disable PIZ compression when applying cpplint. #ifndef TINYEXR_USE_PIZ #define TINYEXR_USE_PIZ (1) @@ -608,7 +613,10 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, #define NOMINMAX #endif #include // for UTF-8 and memory-mapping + +#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) #define TINYEXR_USE_WIN32_MMAP (1) +#endif #elif defined(__linux__) || defined(__unix__) #include // for open() @@ -650,7 +658,7 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, #include #endif -#if TINYEXR_USE_MINIZ +#if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1) #include #else // Issue #46. Please include your own zlib-compatible API header before @@ -658,6 +666,11 @@ extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, //#include "zlib.h" #endif +#if defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1) +#define NANOZLIB_IMPLEMENTATION +#include "nanozlib.h" +#endif + #if TINYEXR_USE_STB_ZLIB // Since we don't know where a project has stb_image.h and stb_image_write.h // and whether they are in the include path, we don't include them here, and @@ -668,6 +681,7 @@ extern "C" int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuf extern "C" unsigned char *stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality); #endif + #if TINYEXR_USE_ZFP #ifdef __clang__ @@ -1343,7 +1357,7 @@ static bool CompressZip(unsigned char *dst, } } -#if TINYEXR_USE_MINIZ +#if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1) // // Compress the data using miniz // @@ -1357,7 +1371,7 @@ static bool CompressZip(unsigned char *dst, } compressedSize = outSize; -#elif TINYEXR_USE_STB_ZLIB +#elif defined(TINYEXR_USE_STB_ZLIB) && (TINYEXR_USE_STB_ZLIB==1) int outSize; unsigned char* ret = stbi_zlib_compress(const_cast(&tmpBuf.at(0)), src_size, &outSize, 8); if (!ret) { @@ -1366,6 +1380,18 @@ static bool CompressZip(unsigned char *dst, memcpy(dst, ret, outSize); free(ret); + compressedSize = outSize; +#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1) + uint64_t dstSize = nanoz_compressBound(static_cast(src_size)); + int outSize{0}; + unsigned char *ret = nanoz_compress(&tmpBuf.at(0), src_size, &outSize, /* quality */8); + if (!ret) { + return false; + } + + memcpy(dst, ret, outSize); + free(ret); + compressedSize = outSize; #else uLong outSize = compressBound(static_cast(src_size)); @@ -1398,7 +1424,7 @@ static bool DecompressZip(unsigned char *dst, } std::vector tmpBuf(*uncompressed_size); -#if TINYEXR_USE_MINIZ +#if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1) int ret = mz_uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); if (MZ_OK != ret) { @@ -1410,6 +1436,17 @@ static bool DecompressZip(unsigned char *dst, if (ret < 0) { return false; } +#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB==1) + uint64_t dest_size = (*uncompressed_size); + uint64_t uncomp_size{0}; + nanoz_status_t ret = + nanoz_uncompress(src, src_size, dest_size, &tmpBuf.at(0), &uncomp_size); + if (NANOZ_SUCCESS != ret) { + return false; + } + if ((*uncompressed_size) != uncomp_size) { + return false; + } #else int ret = uncompress(&tmpBuf.at(0), uncompressed_size, src, src_size); if (Z_OK != ret) { @@ -5715,7 +5752,7 @@ static bool isValidTile(const EXRHeader* exr_header, static bool ReconstructTileOffsets(OffsetData& offset_data, const EXRHeader* exr_header, - const unsigned char* head, const unsigned char* marker, const size_t /*size*/, + const unsigned char* head, const unsigned char* marker, const size_t size, bool isMultiPartFile, bool isDeep) { int numXLevels = offset_data.num_x_levels; @@ -5724,11 +5761,20 @@ static bool ReconstructTileOffsets(OffsetData& offset_data, for (unsigned int dx = 0; dx < offset_data.offsets[l][dy].size(); ++dx) { tinyexr::tinyexr_uint64 tileOffset = tinyexr::tinyexr_uint64(marker - head); + if (isMultiPartFile) { + if ((marker + sizeof(int)) >= (head + size)) { + return false; + } + //int partNumber; marker += sizeof(int); } + if ((marker + 4 * sizeof(int)) >= (head + size)) { + return false; + } + int tileX; memcpy(&tileX, marker, sizeof(int)); tinyexr::swap4(&tileX); @@ -5750,6 +5796,9 @@ static bool ReconstructTileOffsets(OffsetData& offset_data, marker += sizeof(int); if (isDeep) { + if ((marker + 2 * sizeof(tinyexr::tinyexr_int64)) >= (head + size)) { + return false; + } tinyexr::tinyexr_int64 packed_offset_table_size; memcpy(&packed_offset_table_size, marker, sizeof(tinyexr::tinyexr_int64)); tinyexr::swap8(reinterpret_cast(&packed_offset_table_size)); @@ -5763,13 +5812,26 @@ static bool ReconstructTileOffsets(OffsetData& offset_data, // next Int64 is unpacked sample size - skip that too marker += packed_offset_table_size + packed_sample_size + 8; + if (marker >= (head + size)) { + return false; + } + } else { - int dataSize; - memcpy(&dataSize, marker, sizeof(int)); + if ((marker + sizeof(uint32_t)) >= (head + size)) { + return false; + } + + uint32_t dataSize; + memcpy(&dataSize, marker, sizeof(uint32_t)); tinyexr::swap4(&dataSize); - marker += sizeof(int); + marker += sizeof(uint32_t); + marker += dataSize; + + if (marker >= (head + size)) { + return false; + } } if (!isValidTile(exr_header, offset_data, @@ -5781,6 +5843,19 @@ static bool ReconstructTileOffsets(OffsetData& offset_data, if (level_idx < 0) { return false; } + + if (size_t(level_idx) >= offset_data.offsets.size()) { + return false; + } + + if (size_t(tileY) >= offset_data.offsets[size_t(level_idx)].size()) { + return false; + } + + if (size_t(tileX) >= offset_data.offsets[size_t(level_idx)][size_t(tileY)].size()) { + return false; + } + offset_data.offsets[size_t(level_idx)][size_t(tileY)][size_t(tileX)] = tileOffset; } } @@ -7043,13 +7118,16 @@ static bool EncodePixelData(/* out */ std::vector& out_data, } else if ((compression_type == TINYEXR_COMPRESSIONTYPE_ZIPS) || (compression_type == TINYEXR_COMPRESSIONTYPE_ZIP)) { -#if TINYEXR_USE_MINIZ +#if defined(TINYEXR_USE_MINIZ) && (TINYEXR_USE_MINIZ==1) std::vector block(mz_compressBound( static_cast(buf.size()))); #elif TINYEXR_USE_STB_ZLIB // there is no compressBound() function, so we use a value that // is grossly overestimated, but should always work std::vector block(256 + 2 * buf.size()); +#elif defined(TINYEXR_USE_NANOZLIB) && (TINYEXR_USE_NANOZLIB == 1) + std::vector block(nanoz_compressBound( + static_cast(buf.size()))); #else std::vector block( compressBound(static_cast(buf.size())));