[librsvg] (#584): Fix arithmetic overflow when requesting large pixbufs



commit d5653304b14edf3eb6c3b0f8c6c03d0c0351790f
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Apr 7 14:34:23 2020 -0500

    (#584): Fix arithmetic overflow when requesting large pixbufs
    
    This is really a bug in gtk-rs/gdk-pixbuf -
    https://github.com/gtk-rs/gdk-pixbuf/issues/147
    
    The computation of the pixel offset within the Pixbuf's buffer needs
    to be done with 64-bit values, or type inference will just use i32,
    since that is what the Pixbuf API exposes.
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/584

 librsvg/pixbuf_utils.rs | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)
---
diff --git a/librsvg/pixbuf_utils.rs b/librsvg/pixbuf_utils.rs
index ccc0546e..921ec365 100644
--- a/librsvg/pixbuf_utils.rs
+++ b/librsvg/pixbuf_utils.rs
@@ -44,12 +44,44 @@ pub fn pixbuf_from_surface(surface: &SharedImageSurface) -> Result<Pixbuf, Rende
             (pixel.r, pixel.g, pixel.b, pixel.a)
         };
 
-        pixbuf.put_pixel(x as i32, y as i32, r, g, b, a);
+        // FIXME: Use pixbuf.put_pixel when
+        // https://github.com/gtk-rs/gdk-pixbuf/issues/147
+        // is integrated
+        my_put_pixel(&pixbuf, x as i32, y as i32, r, g, b, a);
     }
 
     Ok(pixbuf)
 }
 
+// Copied from gtk-rs/gdk-pixbuf
+//
+// See the following:
+//   https://gitlab.gnome.org/GNOME/librsvg/-/issues/584
+//   https://github.com/gtk-rs/gdk-pixbuf/issues/147
+//
+// Arithmetic can overflow in the computation of `pos` if it is not done with usize
+// values (everything coming out of a Pixbuf is i32).
+//
+// When this fix appears in a gtk-rs release, we can remove this.
+fn my_put_pixel(pixbuf: &Pixbuf, x: i32, y: i32, red: u8, green: u8, blue: u8, alpha: u8) {
+    unsafe {
+        let x = x as usize;
+        let y = y as usize;
+        let n_channels = pixbuf.get_n_channels() as usize;
+        assert!(n_channels == 3 || n_channels == 4);
+        let rowstride = pixbuf.get_rowstride() as usize;
+        let pixels = pixbuf.get_pixels();
+        let pos = y * rowstride + x * n_channels;
+
+        pixels[pos] = red;
+        pixels[pos + 1] = green;
+        pixels[pos + 2] = blue;
+        if n_channels == 4 {
+            pixels[pos + 3] = alpha;
+        }
+    }
+}
+
 enum SizeKind {
     Zoom,
     WidthHeight,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]