diff --git a/3rdparty/tinyexr/tinyexr.h b/3rdparty/tinyexr/tinyexr.h index 6e23778..7ef09af 100644 --- a/3rdparty/tinyexr/tinyexr.h +++ b/3rdparty/tinyexr/tinyexr.h @@ -306,12 +306,14 @@ extern int ParseEXRVersionFromMemory(EXRVersion *version, const unsigned char *memory, size_t size); // Parse single-part OpenEXR header from a file and initialize `EXRHeader`. -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRHeaderFromFile(EXRHeader *header, const EXRVersion *version, const char *filename, const char **err); // Parse single-part OpenEXR header from a memory and initialize `EXRHeader`. -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRHeaderFromMemory(EXRHeader *header, const EXRVersion *version, const unsigned char *memory, size_t size, @@ -319,7 +321,8 @@ extern int ParseEXRHeaderFromMemory(EXRHeader *header, // Parse multi-part OpenEXR headers from a file and initialize `EXRHeader*` // array. -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, int *num_headers, const EXRVersion *version, @@ -328,7 +331,8 @@ extern int ParseEXRMultipartHeaderFromFile(EXRHeader ***headers, // Parse multi-part OpenEXR headers from a memory and initialize `EXRHeader*` // array -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, int *num_headers, const EXRVersion *version, @@ -340,7 +344,8 @@ extern int ParseEXRMultipartHeaderFromMemory(EXRHeader ***headers, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, const char *filename, const char **err); @@ -350,7 +355,8 @@ extern int LoadEXRImageFromFile(EXRImage *image, const EXRHeader *header, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, const unsigned char *memory, const size_t size, const char **err); @@ -361,7 +367,8 @@ extern int LoadEXRImageFromMemory(EXRImage *image, const EXRHeader *header, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRMultipartImageFromFile(EXRImage *images, const EXRHeader **headers, unsigned int num_parts, @@ -374,7 +381,8 @@ extern int LoadEXRMultipartImageFromFile(EXRImage *images, // Application can free EXRImage using `FreeEXRImage` // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRMultipartImageFromMemory(EXRImage *images, const EXRHeader **headers, unsigned int num_parts, @@ -384,7 +392,8 @@ extern int LoadEXRMultipartImageFromMemory(EXRImage *images, // Saves multi-channel, single-frame OpenEXR image to a file. // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int SaveEXRImageToFile(const EXRImage *image, const EXRHeader *exr_header, const char *filename, const char **err); @@ -394,7 +403,8 @@ extern int SaveEXRImageToFile(const EXRImage *image, // Return the number of bytes if succes. // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern size_t SaveEXRImageToMemory(const EXRImage *image, const EXRHeader *exr_header, unsigned char **memory, const char **err); @@ -403,7 +413,8 @@ extern size_t SaveEXRImageToMemory(const EXRImage *image, // Application must free memory of variables in DeepImage(image, offset_table) // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadDeepEXR(DeepImage *out_image, const char *filename, const char **err); @@ -426,7 +437,8 @@ extern int LoadDeepEXR(DeepImage *out_image, const char *filename, // RGB(A) channels. // Returns negative value and may set error string in `err` when there's an // error -// When there was an error message, Application must free `err` with FreeEXRErrorMessage() +// When there was an error message, Application must free `err` with +// FreeEXRErrorMessage() extern int LoadEXRFromMemory(float **out_rgba, int *width, int *height, const unsigned char *memory, size_t size, const char **err); @@ -2520,10 +2532,10 @@ tinfl_status tinfl_decompress(tinfl_decompressor *r, tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; - const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = - pIn_buf_next + *pIn_buf_size; - mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = - pOut_buf_next + *pOut_buf_size; + const mz_uint8 *pIn_buf_cur = pIn_buf_next, + *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; + mz_uint8 *pOut_buf_cur = pOut_buf_next, + *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 @@ -2940,9 +2952,8 @@ void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, tinfl_status status = tinfl_decompress( &decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, - &dst_buf_size, - (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); + &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { MZ_FREE(pBuf); *pOut_len = 0; @@ -2995,8 +3006,9 @@ int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, - (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | - TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); + (flags & + ~(TINFL_FLAG_HAS_MORE_INPUT | + TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); in_buf_ofs += in_buf_size; if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) @@ -3121,9 +3133,7 @@ static const mz_uint8 s_tdefl_large_dist_extra[128] = { // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted // values. -typedef struct { - mz_uint16 m_key, m_sym_index; -} tdefl_sym_freq; +typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1) { @@ -5267,10 +5277,9 @@ mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); pStat->m_comment_size = n; - memcpy(pStat->m_comment, - p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + - MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + - MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), + memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; @@ -6957,13 +6966,12 @@ void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, // return bint.c[0] == 1; //} -static void SetErrorMessage(const std::string &msg, const char **err) -{ +static void SetErrorMessage(const std::string &msg, const char **err) { if (err) { #ifdef _WIN32 - (*err) = _strdup(msg.c_str()); + (*err) = _strdup(msg.c_str()); #else - (*err) = strdup(msg.c_str()); + (*err) = strdup(msg.c_str()); #endif } } @@ -10095,6 +10103,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, outLine += (height - 1 - y) * x_stride; } + if (reinterpret_cast(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; + } + for (int u = 0; u < width; u++) { tinyexr::FP16 hf; @@ -10123,6 +10137,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, outLine += (height - 1 - y) * x_stride; } + if (reinterpret_cast(line_ptr + width) > + (data_ptr + data_len)) { + // Insufficient data size + return false; + } + for (int u = 0; u < width; u++) { float val; tinyexr::cpy4(&val, line_ptr + u); @@ -10143,6 +10163,12 @@ static bool DecodePixelData(/* out */ unsigned char **out_images, } for (int u = 0; u < width; u++) { + if (reinterpret_cast(line_ptr + u) >= + (data_ptr + data_len)) { + // Corrupsed data? + return false; + } + unsigned int val; tinyexr::cpy4(&val, line_ptr + u); @@ -10325,6 +10351,9 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, size_t orig_size = size; for (size_t nattr = 0; nattr < TINYEXR_MAX_HEADER_ATTRIBUTES; nattr++) { if (0 == size) { + if (err) { + (*err) += "Insufficient data size for attributes.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } else if (marker[0] == '\0') { size--; @@ -10337,6 +10366,9 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, size_t marker_size; if (!tinyexr::ReadAttribute(&attr_name, &attr_type, &data, &marker_size, marker, size)) { + if (err) { + (*err) += "Failed to read attribute.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } marker += marker_size; @@ -10407,14 +10439,14 @@ static int ParseEXRHeader(HeaderInfo *info, bool *empty_header, if (!ReadChannelInfo(info->channels, data)) { if (err) { - (*err) = "Failed to parse channel info."; + (*err) += "Failed to parse channel info.\n"; } return TINYEXR_ERROR_INVALID_DATA; } if (info->channels.size() < 1) { if (err) { - (*err) = "# of channels is zero."; + (*err) += "# of channels is zero.\n"; } return TINYEXR_ERROR_INVALID_DATA; } @@ -10648,7 +10680,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) { static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, const std::vector &offsets, - const unsigned char *head, const size_t size) { + const unsigned char *head, const size_t size, std::string *err) { int num_channels = exr_header->num_channels; int num_scanline_blocks = 1; @@ -10669,8 +10701,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, int pixel_data_size = 0; size_t channel_offset = 0; if (!tinyexr::ComputeChannelLayout(&channel_offset_list, &pixel_data_size, - &channel_offset, num_channels, - exr_header->channels)) { + &channel_offset, num_channels, + exr_header->channels)) { + if (err) { + (*err) += "Failed to compute channel layout.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } @@ -10692,6 +10727,9 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, // 4 byte : data size // ~ : data(uncompressed or compressed) if (offsets[tile_idx] + sizeof(int) * 5 > size) { + if (err) { + (*err) += "Insufficient data size.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } @@ -10720,6 +10758,9 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header, tinyexr::swap4(reinterpret_cast(&data_len)); if (data_len < 4 || size_t(data_len) > data_size) { + if (err) { + (*err) += "Insufficient data length.\n"; + } return TINYEXR_ERROR_INVALID_DATA; } @@ -10977,13 +11018,38 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header, // OK break; } else { - tinyexr::SetErrorMessage("Cannot reconstruct lineOffset table in DecodeEXRImage.", err); + tinyexr::SetErrorMessage( + "Cannot reconstruct lineOffset table in DecodeEXRImage.", err); return TINYEXR_ERROR_INVALID_DATA; } } } - return DecodeChunk(exr_image, exr_header, offsets, head, size); + { + std::string e; + int ret = DecodeChunk(exr_image, exr_header, offsets, head, size, &e); + + if (ret != TINYEXR_SUCCESS) { + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } + + // release memory(if exists) + if ((exr_header->num_channels > 0) && exr_image && exr_image->images) { + for (size_t c = 0; c < size_t(exr_header->num_channels); c++) { + if (exr_image->images[c]) { + free(exr_image->images[c]); + exr_image->images[c] = NULL; + } + } + free(exr_image->images); + exr_image->images = NULL; + } + + } + + return ret; + } } } // namespace tinyexr @@ -11004,11 +11070,14 @@ int LoadEXR(float **out_rgba, int *width, int *height, const char *filename, { int ret = ParseEXRVersionFromFile(&exr_version, filename); if (ret != TINYEXR_SUCCESS) { + tinyexr::SetErrorMessage("Invalid EXR header.", err); return ret; } if (exr_version.multipart || exr_version.non_image) { - tinyexr::SetErrorMessage("Loading multipart or DeepImage is not supported in LoadEXR() API", err); + tinyexr::SetErrorMessage( + "Loading multipart or DeepImage is not supported in LoadEXR() API", + err); return TINYEXR_ERROR_INVALID_DATA; // @fixme. } } @@ -11161,13 +11230,19 @@ int ParseEXRHeaderFromMemory(EXRHeader *exr_header, const EXRVersion *version, const unsigned char *memory, size_t size, const char **err) { if (memory == NULL || exr_header == NULL) { - tinyexr::SetErrorMessage("Invalid argument. `memory` or `exr_header` argument is null in ParseEXRHeaderFromMemory()", err); + tinyexr::SetErrorMessage( + "Invalid argument. `memory` or `exr_header` argument is null in " + "ParseEXRHeaderFromMemory()", + err); // Invalid argument return TINYEXR_ERROR_INVALID_ARGUMENT; } if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage( + "Insufficient header/data size.\n", + err); return TINYEXR_ERROR_INVALID_DATA; } @@ -11321,6 +11396,7 @@ int LoadEXRImageFromFile(EXRImage *exr_image, const EXRHeader *exr_header, fseek(fp, 0, SEEK_SET); if (filesize < 16) { + tinyexr::SetErrorMessage("File size too short " + std::string(filename), err); return TINYEXR_ERROR_INVALID_FILE; } @@ -11342,7 +11418,8 @@ int LoadEXRImageFromMemory(EXRImage *exr_image, const EXRHeader *exr_header, const char **err) { if (exr_image == NULL || memory == NULL || (size < tinyexr::kEXRVersionSize)) { - tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory", err); + tinyexr::SetErrorMessage("Invalid argument for LoadEXRImageFromMemory", + err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -11370,14 +11447,16 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, #if !TINYEXR_USE_PIZ if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { - tinyexr::SetErrorMessage("PIZ compression is not supported in this build", err); + tinyexr::SetErrorMessage("PIZ compression is not supported in this build", + err); return 0; } #endif #if !TINYEXR_USE_ZFP if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { - tinyexr::SetErrorMessage("ZFP compression is not supported in this build", err); + tinyexr::SetErrorMessage("ZFP compression is not supported in this build", + err); return 0; } #endif @@ -11385,7 +11464,8 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, #if TINYEXR_USE_ZFP for (size_t i = 0; i < static_cast(exr_header->num_channels); i++) { if (exr_header->requested_pixel_types[i] != TINYEXR_PIXELTYPE_FLOAT) { - tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression", err); + tinyexr::SetErrorMessage("Pixel type must be FLOAT for ZFP compression", + err); return 0; } } @@ -11595,7 +11675,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, if (exr_header->pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_FLOAT) { for (int y = 0; y < h; y++) { - // Assume increasing Y + // Assume increasing Y float *line_ptr = reinterpret_cast(&buf.at( static_cast(pixel_data_size * y * exr_image->width) + channel_offset_list[c] * @@ -11616,7 +11696,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, } else if (exr_header->requested_pixel_types[c] == TINYEXR_PIXELTYPE_HALF) { for (int y = 0; y < h; y++) { - // Assume increasing Y + // Assume increasing Y unsigned short *line_ptr = reinterpret_cast( &buf.at(static_cast(pixel_data_size * y * exr_image->width) + @@ -11685,8 +11765,7 @@ size_t SaveEXRImageToMemory(const EXRImage *exr_image, // Assume increasing Y unsigned int *line_ptr = reinterpret_cast(&buf.at( static_cast(pixel_data_size * y * exr_image->width) + - channel_offset_list[c] * - static_cast(exr_image->width))); + channel_offset_list[c] * static_cast(exr_image->width))); for (int x = 0; x < exr_image->width; x++) { unsigned int val = reinterpret_cast( exr_image->images)[c][(y + start_y) * exr_image->width + x]; @@ -11869,14 +11948,16 @@ int SaveEXRImageToFile(const EXRImage *exr_image, const EXRHeader *exr_header, #if !TINYEXR_USE_PIZ if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_PIZ) { - tinyexr::SetErrorMessage("PIZ compression is not supported in this build", err); + tinyexr::SetErrorMessage("PIZ compression is not supported in this build", + err); return 0; } #endif #if !TINYEXR_USE_ZFP if (exr_header->compression_type == TINYEXR_COMPRESSIONTYPE_ZFP) { - tinyexr::SetErrorMessage("ZFP compression is not supported in this build", err); + tinyexr::SetErrorMessage("ZFP compression is not supported in this build", + err); return 0; } #endif @@ -11915,13 +11996,15 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { FILE *fp = NULL; errno_t errcode = fopen_s(&fp, filename, "rb"); if ((0 != errcode) || (!fp)) { - tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), err); + tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), + err); return TINYEXR_ERROR_CANT_OPEN_FILE; } #else FILE *fp = fopen(filename, "rb"); if (!fp) { - tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), err); + tinyexr::SetErrorMessage("Cannot read a file " + std::string(filename), + err); return TINYEXR_ERROR_CANT_OPEN_FILE; } #endif @@ -11934,7 +12017,8 @@ int LoadDeepEXR(DeepImage *deep_image, const char *filename, const char **err) { if (filesize == 0) { fclose(fp); - tinyexr::SetErrorMessage("File size is zero : " + std::string(filename), err); + tinyexr::SetErrorMessage("File size is zero : " + std::string(filename), + err); return TINYEXR_ERROR_INVALID_FILE; } @@ -12377,7 +12461,8 @@ int FreeEXRImage(EXRImage *exr_image) { int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, const char *filename, const char **err) { if (exr_header == NULL || exr_version == NULL || filename == NULL) { - tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile", err); + tinyexr::SetErrorMessage("Invalid argument for ParseEXRHeaderFromFile", + err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12406,7 +12491,8 @@ int ParseEXRHeaderFromFile(EXRHeader *exr_header, const EXRVersion *exr_version, fclose(fp); if (ret != filesize) { - tinyexr::SetErrorMessage("fread() error on " + std::string(filename), err); + tinyexr::SetErrorMessage("fread() error on " + std::string(filename), + err); return TINYEXR_ERROR_INVALID_FILE; } } @@ -12423,11 +12509,14 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, if (memory == NULL || exr_headers == NULL || num_headers == NULL || exr_version == NULL) { // Invalid argument - tinyexr::SetErrorMessage("Invalid argument for ParseEXRMultipartHeaderFromMemory", err); + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromMemory", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } if (size < tinyexr::kEXRVersionSize) { + tinyexr::SetErrorMessage( + "Data size too short", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12457,7 +12546,8 @@ int ParseEXRMultipartHeaderFromMemory(EXRHeader ***exr_headers, // `chunkCount` must exist in the header. if (info.chunk_count == 0) { - tinyexr::SetErrorMessage("`chunkCount' attribute is not found in the header.", err); + tinyexr::SetErrorMessage( + "`chunkCount' attribute is not found in the header.", err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12492,7 +12582,8 @@ int ParseEXRMultipartHeaderFromFile(EXRHeader ***exr_headers, int *num_headers, const char *filename, const char **err) { if (exr_headers == NULL || num_headers == NULL || exr_version == NULL || filename == NULL) { - tinyexr::SetErrorMessage("Invalid argument for ParseEXRMultipartHeaderFromFile()", err); + tinyexr::SetErrorMessage( + "Invalid argument for ParseEXRMultipartHeaderFromFile()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12630,7 +12721,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, const size_t size, const char **err) { if (exr_images == NULL || exr_headers == NULL || num_parts == 0 || memory == NULL || (size <= tinyexr::kEXRVersionSize)) { - tinyexr::SetErrorMessage("Invalid argument for LoadEXRMultipartImageFromMemory()", err); + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromMemory()", err); return TINYEXR_ERROR_INVALID_ARGUMENT; } @@ -12673,7 +12765,8 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, tinyexr::swap8(&offset); if (offset >= size) { - tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", err); + tinyexr::SetErrorMessage("Invalid offset size in EXR header chunks.", + err); return TINYEXR_ERROR_INVALID_DATA; } @@ -12698,15 +12791,19 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images, tinyexr::swap4(&part_no); if (part_no != i) { - tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.", err); + tinyexr::SetErrorMessage("Invalid `part number' in EXR header chunks.", + err); return TINYEXR_ERROR_INVALID_DATA; } } + std::string e; int ret = tinyexr::DecodeChunk(&exr_images[i], exr_headers[i], offset_table, - memory, size); + memory, size, &e); if (ret != TINYEXR_SUCCESS) { - tinyexr::SetErrorMessage("Error in DecodeChunk()", err); + if (!e.empty()) { + tinyexr::SetErrorMessage(e, err); + } return ret; } } @@ -12719,7 +12816,8 @@ int LoadEXRMultipartImageFromFile(EXRImage *exr_images, unsigned int num_parts, const char *filename, const char **err) { if (exr_images == NULL || exr_headers == NULL || num_parts == 0) { - tinyexr::SetErrorMessage("Invalid argument for LoadEXRMultipartImageFromFile", err); + tinyexr::SetErrorMessage( + "Invalid argument for LoadEXRMultipartImageFromFile", err); return TINYEXR_ERROR_INVALID_ARGUMENT; }