File libheif-CVE-2024-41311.patch of Package libheif.36312

Index: libheif-1.12.0/libheif/heif_context.cc
===================================================================
--- libheif-1.12.0.orig/libheif/heif_context.cc
+++ libheif-1.12.0/libheif/heif_context.cc
@@ -317,9 +317,9 @@ Error ImageOverlay::parse(size_t num_ima
     std::stringstream sstr;
     sstr << "Overlay image data version " << ((int) m_version) << " is not implemented yet";
 
-    return Error(heif_error_Unsupported_feature,
-                 heif_suberror_Unsupported_data_version,
-                 sstr.str());
+    return {heif_error_Unsupported_feature,
+            heif_suberror_Unsupported_data_version,
+            sstr.str()};
   }
 
   int field_len = ((m_flags & 1) ? 4 : 2);
@@ -337,6 +337,12 @@ Error ImageOverlay::parse(size_t num_ima
   m_width = readvec(data, ptr, field_len);
   m_height = readvec(data, ptr, field_len);
 
+  if (m_width==0 || m_height==0) {
+    return {heif_error_Invalid_input,
+            heif_suberror_Invalid_overlay_data,
+            "Overlay image with zero width or height."};
+  }
+
   m_offsets.resize(num_images);
 
   for (size_t i = 0; i < num_images; i++) {
Index: libheif-1.12.0/libheif/heif_image.cc
===================================================================
--- libheif-1.12.0.orig/libheif/heif_image.cc
+++ libheif-1.12.0/libheif/heif_image.cc
@@ -782,7 +782,20 @@ Error HeifPixelImage::fill_RGB_16bit(uin
 }
 
 
-Error HeifPixelImage::overlay(std::shared_ptr<HeifPixelImage>& overlay, int dx, int dy)
+uint32_t negate_negative_int32(int32_t x)
+{
+  assert(x <= 0);
+
+  if (x == INT32_MIN) {
+    return static_cast<uint32_t>(INT32_MAX) + 1;
+  }
+  else {
+    return static_cast<uint32_t>(-x);
+  }
+}
+
+
+Error HeifPixelImage::overlay(std::shared_ptr<HeifPixelImage>& overlay, int32_t dx, int32_t dy)
 {
   std::set<enum heif_channel> channels = overlay->get_channel_set();
 
@@ -807,70 +820,89 @@ Error HeifPixelImage::overlay(std::share
     in_p = overlay->get_plane(channel, &in_stride);
     out_p = get_plane(channel, &out_stride);
 
-    int in_w = overlay->get_width(channel);
-    int in_h = overlay->get_height(channel);
-    assert(in_w >= 0);
-    assert(in_h >= 0);
+    uint32_t in_w = overlay->get_width(channel);
+    uint32_t in_h = overlay->get_height(channel);
 
-    int out_w = get_width(channel);
-    int out_h = get_height(channel);
-    assert(out_w >= 0);
-    assert(out_h >= 0);
+    uint32_t out_w = get_width(channel);
+    uint32_t out_h = get_height(channel);
 
-    // overlay image extends past the right border -> cut width for copy
-    if (dx + in_w > out_w) {
-      in_w = out_w - dx;
+    // top-left points where to start copying in source and destination
+    uint32_t in_x0;
+    uint32_t in_y0;
+    uint32_t out_x0;
+    uint32_t out_y0;
+
+    if (dx > 0 && static_cast<uint32_t>(dx) >= out_w) {
+      // the overlay image is completely outside the right border -> skip overlaying
+      return Error::Ok;
+    }
+    else if (dx < 0 && in_w <= negate_negative_int32(dx)) {
+      // the overlay image is completely outside the left border -> skip overlaying
+      return Error::Ok;
     }
 
-    // overlay image extends past the bottom border -> cut height for copy
-    if (dy + in_h > out_h) {
-      in_h = out_h - dy;
-    }
+    if (dx < 0) {
+      // overlay image started partially outside of left border
 
-    // overlay image completely outside right or bottom border -> do not copy
-    if (in_w < 0 || in_h < 0) {
-      return Error(heif_error_Invalid_input,
-                   heif_suberror_Overlay_image_outside_of_canvas,
-                   "Overlay image outside of right or bottom canvas border");
+      in_x0 = negate_negative_int32(dx);
+      out_x0 = 0;
+      in_w = in_w - in_x0; // in_x0 < in_w because in_w > -dx = in_x0
+    }
+    else {
+      in_x0 = 0;
+      out_x0 = static_cast<uint32_t>(dx);
     }
 
+    // we know that dx >= 0 && dx < out_w
 
-    // calculate top-left point where to start copying in source and destination
-    int in_x0 = 0;
-    int in_y0 = 0;
-    int out_x0 = dx;
-    int out_y0 = dy;
+    if (static_cast<uint32_t>(dx) > UINT32_MAX - in_w ||
+       dx + in_w > out_w) {
+      // overlay image extends partially outside of right border
 
-    // overlay image started outside of left border
-    // -> move start into the image and start at left output column
-    if (dx < 0) {
-      in_x0 = -dx;
-      out_x0 = 0;
+      in_w = out_w - static_cast<uint32_t>(dx); // we know that dx < out_w from first condition
     }
 
-    // overlay image started outside of top border
-    // -> move start into the image and start at top output row
+
+    if (dy > 0 && static_cast<uint32_t>(dy) >= out_h) {
+      // the overlay image is completely outside the bottom border -> skip overlaying
+      return Error::Ok;
+    }
+    else if (dy < 0 && in_h <= negate_negative_int32(dy)) {
+      // the overlay image is completely outside the top border -> skip overlaying
+      return Error::Ok;
+    }
+
+
+
     if (dy < 0) {
-      in_y0 = -dy;
+      // overlay image started partially outside of top border
+
+      in_y0 = negate_negative_int32(dy);
       out_y0 = 0;
+      in_h = in_h - in_y0; // in_y0 < in_h because in_h > -dy = in_y0
+    }
+    else {
+      in_y0 = 0;
+      out_y0 = static_cast<uint32_t>(dy);
     }
 
-    // if overlay image is completely outside at left border, do not copy anything.
-    if (in_w <= in_x0 ||
-        in_h <= in_y0) {
-      return Error(heif_error_Invalid_input,
-                   heif_suberror_Overlay_image_outside_of_canvas,
-                   "Overlay image outside of left or top canvas border");
+    // we know that dy >= 0 && dy < out_h
+
+    if (static_cast<uint32_t>(dy) > UINT32_MAX - in_h ||
+      dy + in_h > out_h) {
+      // overlay image extends partially outside of bottom border
+
+      in_h = out_h - static_cast<uint32_t>(dy); // we know that dy < out_h from first condition
     }
 
-    for (int y = in_y0; y < in_h; y++) {
+    for (uint32_t y = in_y0; y < in_h; y++) {
       if (!has_alpha) {
         memcpy(out_p + out_x0 + (out_y0 + y - in_y0) * out_stride,
                in_p + in_x0 + y * in_stride,
                in_w - in_x0);
       }
       else {
-        for (int x = in_x0; x < in_w; x++) {
+        for (uint32_t x = in_x0; x < in_w; x++) {
           uint8_t* outptr = &out_p[out_x0 + (out_y0 + y - in_y0) * out_stride + x];
           uint8_t in_val = in_p[in_x0 + y * in_stride + x];
           uint8_t alpha_val = alpha_p[in_x0 + y * in_stride + x];
Index: libheif-1.12.0/libheif/heif_image.h
===================================================================
--- libheif-1.12.0.orig/libheif/heif_image.h
+++ libheif-1.12.0/libheif/heif_image.h
@@ -117,7 +117,7 @@ namespace heif {
 
     Error fill_RGB_16bit(uint16_t r, uint16_t g, uint16_t b, uint16_t a);
 
-    Error overlay(std::shared_ptr<HeifPixelImage>& overlay, int dx, int dy);
+    Error overlay(std::shared_ptr<HeifPixelImage>& overlay, int32_t dx, int32_t dy);
 
     Error scale_nearest_neighbor(std::shared_ptr<HeifPixelImage>& output, int width, int height) const;
 
openSUSE Build Service is sponsored by