@@ -10412,7 +10412,7 @@ static void ConvertHeader(EXRHeader *exr_header, const HeaderInfo &info) {
10412
10412
10413
10413
static int DecodeChunk (EXRImage *exr_image, const EXRHeader *exr_header,
10414
10414
const std::vector<tinyexr::tinyexr_uint64> &offsets,
10415
- const unsigned char *head) {
10415
+ const unsigned char *head, const size_t size ) {
10416
10416
int num_channels = exr_header->num_channels ;
10417
10417
10418
10418
int num_scanline_blocks = 1 ;
@@ -10453,6 +10453,11 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
10453
10453
// 16 byte: tile coordinates
10454
10454
// 4 byte : data size
10455
10455
// ~ : 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 );
10456
10461
const unsigned char *data_ptr =
10457
10462
reinterpret_cast <const unsigned char *>(head + offsets[tile_idx]);
10458
10463
@@ -10471,7 +10476,10 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
10471
10476
memcpy (&data_len, data_ptr + 16 ,
10472
10477
sizeof (int )); // 16 = sizeof(tile_coordinates)
10473
10478
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
+ }
10475
10483
10476
10484
// Move to data addr: 20 = 16 + 4;
10477
10485
data_ptr += 20 ;
@@ -10508,18 +10516,29 @@ static int DecodeChunk(EXRImage *exr_image, const EXRHeader *exr_header,
10508
10516
#endif
10509
10517
for (int y = 0 ; y < static_cast <int >(num_blocks); y++) {
10510
10518
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
+
10513
10524
// 4 byte: scan line
10514
10525
// 4 byte: data size
10515
10526
// ~ : 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
+
10516
10531
int line_no;
10517
10532
memcpy (&line_no, data_ptr, sizeof (int ));
10518
10533
int data_len;
10519
10534
memcpy (&data_len, data_ptr + 4 , sizeof (int ));
10520
10535
tinyexr::swap4 (reinterpret_cast <unsigned int *>(&line_no));
10521
10536
tinyexr::swap4 (reinterpret_cast <unsigned int *>(&data_len));
10522
10537
10538
+ if (size_t (data_len) > data_size) {
10539
+ return TINYEXR_ERROR_INVALID_DATA;
10540
+ }
10541
+
10523
10542
int end_line_no = (std::min)(line_no + num_scanline_blocks,
10524
10543
(exr_header->data_window [3 ] + 1 ));
10525
10544
@@ -10712,7 +10731,7 @@ static int DecodeEXRImage(EXRImage *exr_image, const EXRHeader *exr_header,
10712
10731
}
10713
10732
}
10714
10733
10715
- return DecodeChunk(exr_image, exr_header, offsets, head);
10734
+ return DecodeChunk (exr_image, exr_header, offsets, head, size );
10716
10735
}
10717
10736
10718
10737
} // namespace tinyexr
@@ -12453,7 +12472,7 @@ int LoadEXRMultipartImageFromMemory(EXRImage *exr_images,
12453
12472
}
12454
12473
12455
12474
int ret = tinyexr::DecodeChunk (&exr_images[i], exr_headers[i], offset_table,
12456
- memory);
12475
+ memory, size );
12457
12476
if (ret != TINYEXR_SUCCESS) {
12458
12477
return ret;
12459
12478
}
0 commit comments