@@ -10412,7 +10412,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
1041210412
1041310413static int DecodeChunk (EXRImage *exr_image, const EXRHeader *exr_header,
1041410414 const std::vector<tinyexr::tinyexr_uint64> &offsets,
10415- const unsigned char *head) {
10415+ const unsigned char *head, const size_t size ) {
1041610416 int num_channels = exr_header->num_channels ;
1041710417
1041810418 int num_scanline_blocks = 1 ;
@@ -10453,6 +10453,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
1045310453 // 16 byte: tile coordinates
1045410454 // 4 byte : data size
1045510455 // ~ : data(uncompressed or compressed)
10456+ if (offsets[tile_idx] + sizeof (int ) * 5 > size) {
10457+ return TINYEXR_ERROR_INVALID_DATA;
10458+ }
10459+
10460+ size_t data_size = size - (offsets[tile_idx] + sizeof (int ) * 5 );
1045610461 const unsigned char *data_ptr =
1045710462 reinterpret_cast <const unsigned char *>(head + offsets[tile_idx]);
1045810463
@@ -10471,7 +10476,10 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
1047110476 memcpy (&data_len, data_ptr + 16 ,
1047210477 sizeof (int )); // 16 = sizeof(tile_coordinates)
1047310478 tinyexr::swap4 (reinterpret_cast <unsigned int *>(&data_len));
10474- assert (data_len >= 4 );
10479+
10480+ if (data_len < 4 || size_t (data_len) > data_size) {
10481+ return TINYEXR_ERROR_INVALID_DATA;
10482+ }
1047510483
1047610484 // Move to data addr: 20 = 16 + 4;
1047710485 data_ptr += 20 ;
@@ -10508,18 +10516,29 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
1050810516#endif
1050910517 for (int y = 0 ; y < static_cast <int >(num_blocks); y++) {
1051010518 size_t y_idx = static_cast <size_t >(y);
10511- const unsigned char *data_ptr =
10512- reinterpret_cast <const unsigned char *>(head + offsets[y_idx]);
10519+
10520+ if (offsets[y_idx] + sizeof (int ) * 2 > size) {
10521+ return TINYEXR_ERROR_INVALID_DATA;
10522+ }
10523+
1051310524 // 4 byte: scan line
1051410525 // 4 byte: data size
1051510526 // ~ : pixel data(uncompressed or compressed)
10527+ size_t data_size = size - (offsets[y_idx] + sizeof (int ) * 2 );
10528+ const unsigned char *data_ptr =
10529+ reinterpret_cast <const unsigned char *>(head + offsets[y_idx]);
10530+
1051610531 int line_no;
1051710532 memcpy (&line_no, data_ptr, sizeof (int ));
1051810533 int data_len;
1051910534 memcpy (&data_len, data_ptr + 4 , sizeof (int ));
1052010535 tinyexr::swap4 (reinterpret_cast <unsigned int *>(&line_no));
1052110536 tinyexr::swap4 (reinterpret_cast <unsigned int *>(&data_len));
1052210537
10538+ if (size_t (data_len) > data_size) {
10539+ return TINYEXR_ERROR_INVALID_DATA;
10540+ }
10541+
1052310542 int end_line_no = (std::min)(line_no + num_scanline_blocks,
1052410543 (exr_header->data_window [3 ] + 1 ));
1052510544
@@ -10712,7 +10731,7 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
1071210731 }
1071310732 }
1071410733
10715- return DecodeChunk (exr_image, exr_header, offsets, head);
10734+ return DecodeChunk (exr_image, exr_header, offsets, head, size );
1071610735}
1071710736
1071810737} // namespace tinyexr
@@ -12453,7 +12472,7 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
1245312472 }
1245412473
1245512474 int ret = tinyexr::DecodeChunk (&exr_images[i], exr_headers[i], offset_table,
12456- memory);
12475+ memory, size );
1245712476 if (ret != TINYEXR_SUCCESS) {
1245812477 return ret;
1245912478 }
0 commit comments