Commit 23903961 for libheif
commit 23903961e1237ecdb0779a65b423cb75f524d254
Author: Dirk Farin <dirk.farin@gmail.com>
Date: Sat Mar 14 00:36:34 2026 +0100
fix computation of tile memory area for 4:2:0 chroma and odd tile sizes
diff --git a/libheif/pixelimage.cc b/libheif/pixelimage.cc
index eaa2bba4..85317ae0 100644
--- a/libheif/pixelimage.cc
+++ b/libheif/pixelimage.cc
@@ -1235,13 +1235,16 @@ Error HeifPixelImage::copy_image_to(const std::shared_ptr<const HeifPixelImage>&
uint32_t src_width = source->get_width(channel);
uint32_t src_height = source->get_height(channel);
- uint32_t copy_width = std::min(src_width, channel_width(w - x0, chroma, channel));
- uint32_t copy_height = std::min(src_height, channel_height(h - y0, chroma, channel));
-
- copy_width *= source->get_storage_bits_per_pixel(channel) / 8;
-
uint32_t xs = channel_width(x0, chroma, channel);
uint32_t ys = channel_height(y0, chroma, channel);
+
+ // Compute copy size from actual plane bounds to avoid chroma rounding mismatch.
+ // channel_height(y0) + channel_height(h - y0) can exceed channel_height(h) with 4:2:0
+ // due to ceiling division, so we use (plane_size - offset) instead.
+ uint32_t copy_width = std::min(src_width, channel_width(w, chroma, channel) - xs);
+ uint32_t copy_height = std::min(src_height, channel_height(h, chroma, channel) - ys);
+
+ copy_width *= source->get_storage_bits_per_pixel(channel) / 8;
xs *= source->get_storage_bits_per_pixel(channel) / 8;
for (uint32_t py = 0; py < copy_height; py++) {
@@ -2156,13 +2159,16 @@ HeifPixelImage::extract_image_area(uint32_t x0, uint32_t y0, uint32_t w, uint32_
};
}
- uint32_t copy_width = channel_width(minW, chroma, channel);
- uint32_t copy_height = channel_height(minH, chroma, channel);
-
- copy_width *= get_storage_bits_per_pixel(channel) / 8;
-
uint32_t xs = channel_width(x0, chroma, channel);
uint32_t ys = channel_height(y0, chroma, channel);
+
+ // Clamp copy size to source plane bounds to avoid chroma rounding mismatch OOB read.
+ uint32_t src_plane_h = channel_height(get_height(), chroma, channel);
+ uint32_t src_plane_w = channel_width(get_width(), chroma, channel);
+ uint32_t copy_width = std::min(channel_width(minW, chroma, channel), src_plane_w - xs);
+ uint32_t copy_height = std::min(channel_height(minH, chroma, channel), src_plane_h - ys);
+
+ copy_width *= get_storage_bits_per_pixel(channel) / 8;
xs *= get_storage_bits_per_pixel(channel) / 8;
for (uint32_t py = 0; py < copy_height; py++) {