Bug 8203709. Handle failure to create a snapshot surface in GetImageDataArray. r=mattwoodrow
authorRobert O'Callahan <robert@ocallahan.org>
Tue, 12 Feb 2013 17:56:28 +1300
changeset 121578 0b32c50a1bec6cbd284fe14016738ce43696da83
parent 121577 80df535bf5e627b8757b98346fcfa5bc1b12971d
child 121579 324ef02e21614cc7b39cfae97fe7945856f8ab6a
push id22808
push userrocallahan@mozilla.com
push dateTue, 12 Feb 2013 04:57:07 +0000
treeherdermozilla-inbound@0b32c50a1bec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs8203709
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 8203709. Handle failure to create a snapshot surface in GetImageDataArray. r=mattwoodrow
content/canvas/src/CanvasRenderingContext2D.cpp
gfx/2d/2D.h
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -3372,47 +3372,50 @@ CanvasRenderingContext2D::GetImageDataAr
 
   CheckedInt<int32_t> rightMost = CheckedInt<int32_t>(aX) + aWidth;
   CheckedInt<int32_t> bottomMost = CheckedInt<int32_t>(aY) + aHeight;
 
   if (!rightMost.isValid() || !bottomMost.isValid()) {
     return NS_ERROR_DOM_SYNTAX_ERR;
   }
 
+  IntRect srcRect(0, 0, mWidth, mHeight);
+  IntRect destRect(aX, aY, aWidth, aHeight);
+  IntRect srcReadRect = srcRect.Intersect(destRect);
+  RefPtr<DataSourceSurface> readback;
+  if (!srcReadRect.IsEmpty() && !mZero) {
+    RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
+    if (snapshot) {
+      readback = snapshot->GetDataSurface();
+    }
+    if (!readback || !readback->GetData()) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+  }
+
   JSObject* darray = JS_NewUint8ClampedArray(aCx, len.value());
   if (!darray) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   if (mZero) {
     *aRetval = darray;
     return NS_OK;
   }
 
   uint8_t* data = JS_GetUint8ClampedArrayData(darray);
 
-  IntRect srcRect(0, 0, mWidth, mHeight);
-  IntRect destRect(aX, aY, aWidth, aHeight);
-
-  IntRect srcReadRect = srcRect.Intersect(destRect);
   IntRect dstWriteRect = srcReadRect;
   dstWriteRect.MoveBy(-aX, -aY);
 
   uint8_t* src = data;
   uint32_t srcStride = aWidth * 4;
-
-  RefPtr<DataSourceSurface> readback;
-  if (!srcReadRect.IsEmpty()) {
-    RefPtr<SourceSurface> snapshot = mTarget->Snapshot();
-    if (snapshot) {
-      readback = snapshot->GetDataSurface();
-
-      srcStride = readback->Stride();
-      src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
-    }
+  if (readback) {
+    srcStride = readback->Stride();
+    src = readback->GetData() + srcReadRect.y * srcStride + srcReadRect.x * 4;
   }
 
   // NOTE! dst is the same as src, and this relies on reading
   // from src and advancing that ptr before writing to dst.
   // NOTE! I'm not sure that it is, I think this comment might have been
   // inherited from Thebes canvas and is no longer true
   uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
 
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -318,21 +318,26 @@ public:
    */
   virtual TemporaryRef<DataSourceSurface> GetDataSurface() = 0;
 };
 
 class DataSourceSurface : public SourceSurface
 {
 public:
   virtual SurfaceType GetType() const { return SURFACE_DATA; }
-  /* Get the raw bitmap data of the surface */
+  /*
+   * Get the raw bitmap data of the surface.
+   * Can return null if there was OOM allocating surface data.
+   */
   virtual uint8_t *GetData() = 0;
+
   /*
    * Stride of the surface, distance in bytes between the start of the image
    * data belonging to row y and row y+1. This may be negative.
+   * Can return 0 if there was OOM allocating surface data.
    */
   virtual int32_t Stride() = 0;
 
   /*
    * This function is called after modifying the data on the source surface
    * directly through the data pointer.
    */
   virtual void MarkDirty() {}