id,summary,reporter,owner,description,type,status,priority,milestone,component,version,resolution,keywords,cc
1281,Wrong bounds computation in imageSurfaceGetPixels,guest,paolo,"r in imageSurfaceGetPixels is the stride of the surface, and therefore the number of bytes in one row (not the number of pixels).
Also, if I understand correctly, the +7 would have to go outside of the row computation to force rounding upwards.

Further, count in mkSurface is off by one.

Please see the following patch (file attachements not working):

{{{
diff -ru old/cairo-0.12.4/Graphics/Rendering/Cairo.hs new/cairo-0.12.4/Graphics/Rendering/Cairo.hs
--- old/cairo-0.12.4/Graphics/Rendering/Cairo.hs	2012-11-12 00:27:42.000000000 +0100
+++ new/cairo-0.12.4/Graphics/Rendering/Cairo.hs	2013-02-01 19:03:36.648095731 +0100
@@ -1813,15 +1813,10 @@
   when (pixPtr_==nullPtr) $ do
     fail ""imageSurfaceGetPixels: image surface not available""
   fmt <- imageSurfaceGetFormat pb
-  let bits = case fmt of
-               FormatARGB32 -> 32
-               FormatRGB24 -> 32
-               FormatA8 -> 8
-               FormatA1 -> 1
   h <- imageSurfaceGetHeight pb
   r <- imageSurfaceGetStride pb
   let pixPtr = castPtr pixPtr_
-  let bytes = h*((r*bits)+7) `div` 8
+      bytes = h * r
   return (mkSurfaceData pb pixPtr bytes)
 
 -- | An array that stores the raw pixel data of an image 'Surface'.
@@ -1833,7 +1828,7 @@
 
 mkSurfaceData :: Storable e => Surface -> Ptr e -> Int -> SurfaceData Int e
 mkSurfaceData pb (ptr :: Ptr e) size =
-  SurfaceData pb ptr (0, count) count
+  SurfaceData pb ptr (0, pred count) count
   where count = fromIntegral (size `div` sizeOf (undefined :: e))
 
 #if __GLASGOW_HASKELL__ < 605

}}}

The following should show the defect:

{{{
import Graphics.Rendering.Cairo
import Data.Array.IArray
import Data.Array.MArray (freeze)
import Data.Array.Unboxed (UArray)
import Data.Word

main :: IO ()
main = do
    (pixelData, stride) <- withImageSurface FormatRGB24 x y $ \surface -> do
        stride <- imageSurfaceGetStride surface
        renderWith surface $ do
            setSourceRGB 1 1 1
            paint
        pData <- imageSurfaceGetPixels surface >>= freeze :: IO (UArray Int Word8)
        return (pData, stride)
    putStrLn $ ""x : "" ++ show x ++ "" y : "" ++ show y ++ "" stride : "" ++ show stride ++ "" expected size : "" ++ show (y * stride) ++ "" or : "" ++ show (x * y * 4)
    print $ bounds pixelData
    putStrLn ""mistake shows here:""
    mapM_ print $ assocs pixelData
    where
    x = 10
    y = 10

}}}
",defect,closed,normal,0.13.0,Cairo bindings,0.12.4,fixed,,sven.mattsen@…
