Bug 803568: Check for Cairo surface creation failure. r=bas a=akeybl
authorMilan Sreckovic <msreckovic@mozilla.com>
Thu, 17 Jan 2013 14:38:38 +0100
changeset 127262 1a2b008b524b3259d7a6994a3999265c6332dc19
parent 127261 a10ef2abf256b131d1d8b6753d4ef37db04ad531
child 127263 2f628016686e9e56883578a58bf0fb8e32b808eb
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbas, akeybl
bugs803568
milestone20.0a2
Bug 803568: Check for Cairo surface creation failure. r=bas a=akeybl
content/canvas/src/CanvasRenderingContext2D.cpp
gfx/2d/DrawTargetCairo.cpp
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -3635,16 +3635,23 @@ CanvasRenderingContext2D::PutImageData_e
   EnsureTarget();
   if (!IsTargetValid()) {
     return NS_ERROR_FAILURE;
   }
 
   RefPtr<SourceSurface> sourceSurface =
     mTarget->CreateSourceSurfaceFromData(imgsurf->Data(), IntSize(w, h), imgsurf->Stride(), FORMAT_B8G8R8A8);
 
+  // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
+  // covers the details of how to run into it, but the full detailed
+  // investigation hasn't been done to determine the underlying cause.  We
+  // will just handle the failure to allocate the surface to avoid a crash.
+  if (!sourceSurface) {
+    return NS_ERROR_FAILURE;
+  }
 
   mTarget->CopySurface(sourceSurface,
                        IntRect(dirtyRect.x - x, dirtyRect.y - y,
                                dirtyRect.width, dirtyRect.height),
                        IntPoint(dirtyRect.x, dirtyRect.y));
 
   Redraw(mgfx::Rect(dirtyRect.x, dirtyRect.y, dirtyRect.width, dirtyRect.height));
 
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -168,16 +168,25 @@ GetCairoSurfaceForSourceSurface(SourceSu
   }
 
   cairo_surface_t* surf =
     cairo_image_surface_create_for_data(data->GetData(),
                                         GfxFormatToCairoFormat(data->GetFormat()),
                                         data->GetSize().width,
                                         data->GetSize().height,
                                         data->Stride());
+
+  // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
+  // covers the details of how to run into it, but the full detailed
+  // investigation hasn't been done to determine the underlying cause.  We
+  // will just handle the failure to allocate the surface to avoid a crash.
+  if (cairo_surface_status(surf)) {
+    return nullptr;
+  }
+
   cairo_surface_set_user_data(surf,
  				                      &surfaceDataKey,
  				                      data.forget().drop(),
  				                      ReleaseData);
   return surf;
 }
 
 // Never returns nullptr. As such, you must always pass in Cairo-compatible
@@ -741,16 +750,23 @@ DrawTargetCairo::CreateGradientStops(Gra
 static void
 CopyDataToCairoSurface(cairo_surface_t* aSurface,
                        unsigned char *aData,
                        const IntSize &aSize,
                        int32_t aStride,
                        int32_t aPixelWidth)
 {
   unsigned char* surfData = cairo_image_surface_get_data(aSurface);
+  // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
+  // covers the details of how to run into it, but the full detailed
+  // investigation hasn't been done to determine the underlying cause.  We
+  // will just handle the failure to allocate the surface to avoid a crash.
+  if (!surfData) {
+    return;
+  }
   for (int32_t y = 0; y < aSize.height; ++y) {
     memcpy(surfData + y * aSize.width * aPixelWidth,
            aData + y * aStride,
            aSize.width * aPixelWidth);
   }
   cairo_surface_mark_dirty(aSurface);
 }
 
@@ -758,16 +774,24 @@ TemporaryRef<SourceSurface>
 DrawTargetCairo::CreateSourceSurfaceFromData(unsigned char *aData,
                                              const IntSize &aSize,
                                              int32_t aStride,
                                              SurfaceFormat aFormat) const
 {
   cairo_surface_t* surf = cairo_image_surface_create(GfxFormatToCairoFormat(aFormat),
                                                      aSize.width,
                                                      aSize.height);
+  // In certain scenarios, requesting larger than 8k image fails.  Bug 803568
+  // covers the details of how to run into it, but the full detailed
+  // investigation hasn't been done to determine the underlying cause.  We
+  // will just handle the failure to allocate the surface to avoid a crash.
+  if (cairo_surface_status(surf)) {
+    return nullptr;
+  }
+
   CopyDataToCairoSurface(surf, aData, aSize, aStride, BytesPerPixel(aFormat));
 
   RefPtr<SourceSurfaceCairo> source_surf = new SourceSurfaceCairo(surf, aSize, aFormat);
   cairo_surface_destroy(surf);
 
   return source_surf;
 }