From 76dd5cd892530ca4555736bf773fbc8066483241 Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Mon, 9 Mar 2015 15:48:20 -0400 Subject: [PATCH] Bug 1140113 - Catch direct (and some indirect) callers of CreateDrawTarget* and deal with failure. r=mstange --- dom/canvas/DocumentRendererChild.cpp | 4 ++++ gfx/2d/DrawTargetTiled.h | 6 ++++++ gfx/2d/FilterNodeSoftware.cpp | 6 ++++++ gfx/layers/client/ImageClient.cpp | 4 ++++ gfx/layers/client/TextureClient.cpp | 10 ++++++++++ gfx/layers/d3d11/TextureD3D11.cpp | 8 ++++++++ gfx/layers/d3d9/TextureD3D9.cpp | 28 +++++++++++++++++++--------- gfx/layers/opengl/CompositorOGL.cpp | 8 +++++--- gfx/thebes/gfxPlatform.cpp | 8 ++++++++ gfx/thebes/gfxUtils.cpp | 6 ++++++ image/src/DynamicImage.cpp | 4 ++++ image/src/RasterImage.cpp | 4 ++++ image/src/imgFrame.cpp | 8 ++++++++ image/src/imgTools.cpp | 9 +++++++++ layout/base/FrameLayerBuilder.cpp | 10 ++++++---- widget/cocoa/nsChildView.mm | 1 + widget/gonk/nsWindow.cpp | 4 ++++ widget/windows/WinUtils.cpp | 4 ++++ widget/windows/nsWindowGfx.cpp | 9 +++++++++ 19 files changed, 125 insertions(+), 16 deletions(-) diff --git a/dom/canvas/DocumentRendererChild.cpp b/dom/canvas/DocumentRendererChild.cpp index d81d00d052d1..e176578bab96 100644 --- a/dom/canvas/DocumentRendererChild.cpp +++ b/dom/canvas/DocumentRendererChild.cpp @@ -80,6 +80,10 @@ DocumentRendererChild::RenderDocument(nsIDOMWindow *window, IntSize(renderSize.width, renderSize.height), 4 * renderSize.width, SurfaceFormat::B8G8R8A8); + if (!dt) { + gfxWarning() << "DocumentRendererChild::RenderDocument failed to Factory::CreateDrawTargetForData"; + return false; + } nsRefPtr ctx = new gfxContext(dt); ctx->SetMatrix(mozilla::gfx::ThebesMatrix(transform)); diff --git a/gfx/2d/DrawTargetTiled.h b/gfx/2d/DrawTargetTiled.h index b0cd4d50453a..f8f169bcda4a 100644 --- a/gfx/2d/DrawTargetTiled.h +++ b/gfx/2d/DrawTargetTiled.h @@ -8,6 +8,7 @@ #include "2D.h" #include "Filters.h" +#include "Logging.h" #include @@ -183,6 +184,11 @@ public: Factory::CreateDrawTargetForData(BackendType::CAIRO, mappedSurf.mData, GetSize(), mappedSurf.mStride, GetFormat()); + if (!dt) { + gfxWarning() << "DrawTargetTiled::GetDataSurface failed in CreateDrawTargetForData"; + surf->Unmap(); + return nullptr; + } for (size_t i = 0; i < mSnapshots.size(); i++) { RefPtr dataSurf = mSnapshots[i]->GetDataSurface(); dt->CopySurface(dataSurf, IntRect(IntPoint(0, 0), mSnapshots[i]->GetSize()), mOrigins[i]); diff --git a/gfx/2d/FilterNodeSoftware.cpp b/gfx/2d/FilterNodeSoftware.cpp index a331bca66ee3..8126e6dbda08 100644 --- a/gfx/2d/FilterNodeSoftware.cpp +++ b/gfx/2d/FilterNodeSoftware.cpp @@ -994,6 +994,11 @@ FilterNodeBlendSoftware::Render(const IntRect& aRect) target->Stride(), target->GetFormat()); + if (!dt) { + gfxWarning() << "FilterNodeBlendSoftware::Render failed in CreateDrawTargetForData"; + return nullptr; + } + Rect r(0, 0, size.width, size.height); dt->DrawSurface(input2, r, r, DrawSurfaceOptions(), DrawOptions(1.0f, ToBlendOp(mBlendMode))); dt->Flush(); @@ -1099,6 +1104,7 @@ FilterNodeTransformSoftware::Render(const IntRect& aRect) mapping.mStride, surf->GetFormat()); if (!dt) { + gfxWarning() << "FilterNodeTransformSoftware::Render failed in CreateDrawTargetForData"; return nullptr; } diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index 05aa876cbe69..680c74dc39d3 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -225,6 +225,10 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag { // We must not keep a reference to the DrawTarget after it has been unlocked. DrawTarget* dt = texture->BorrowDrawTarget(); + if (!dt) { + gfxWarning() << "ImageClientSingle::UpdateImage failed in BorrowDrawTarget"; + return false; + } MOZ_ASSERT(surface.get()); dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint()); } diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index bcb7a36ec56f..f8cbd4896a48 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -532,7 +532,17 @@ bool TextureClient::CopyToTextureClient(TextureClient* aTarget, } RefPtr destinationTarget = aTarget->BorrowDrawTarget(); + if (!destinationTarget) { + gfxWarning() << "TextureClient::CopyToTextureClient (dest) failed in BorrowDrawTarget"; + return false; + } + RefPtr sourceTarget = BorrowDrawTarget(); + if (!sourceTarget) { + gfxWarning() << "TextureClient::CopyToTextureClient (src) failed in BorrowDrawTarget"; + return false; + } + RefPtr source = sourceTarget->Snapshot(); destinationTarget->CopySurface(source, aRect ? *aRect : gfx::IntRect(gfx::IntPoint(0, 0), GetSize()), diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 2b118e183d88..07ec34141813 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -270,11 +270,19 @@ TextureClientD3D11::Lock(OpenMode aMode) if (mNeedsClear) { mDrawTarget = BorrowDrawTarget(); + if (!mDrawTarget) { + Unlock(); + return false; + } mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height)); mNeedsClear = false; } if (mNeedsClearWhite) { mDrawTarget = BorrowDrawTarget(); + if (!mDrawTarget) { + Unlock(); + return false; + } mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0))); mNeedsClearWhite = false; } diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index c8bf9273a75a..ce0b87c90463 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -290,17 +290,19 @@ TextureSourceD3D9::SurfaceToTexture(DeviceManagerD3D9* aDeviceManager, reinterpret_cast(lockedRect.pBits), aSize, lockedRect.Pitch, gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aSurface->GetContentType())); - NativeSurface nativeSurf; - nativeSurf.mSize = aSize; - nativeSurf.mType = NativeSurfaceType::CAIRO_SURFACE; - // We don't know that this is actually the right format, but it's the best - // we can get for the content type. In practice this probably always works. - nativeSurf.mFormat = dt->GetFormat(); - nativeSurf.mSurface = aSurface->CairoSurface(); - RefPtr surf = dt->CreateSourceSurfaceFromNativeSurface(nativeSurf); + if (dt) { + NativeSurface nativeSurf; + nativeSurf.mSize = aSize; + nativeSurf.mType = NativeSurfaceType::CAIRO_SURFACE; + // We don't know that this is actually the right format, but it's the best + // we can get for the content type. In practice this probably always works. + nativeSurf.mFormat = dt->GetFormat(); + nativeSurf.mSurface = aSurface->CairoSurface(); - dt->CopySurface(surf, IntRect(IntPoint(), aSize), IntPoint()); + RefPtr surf = dt->CreateSourceSurfaceFromNativeSurface(nativeSurf); + dt->CopySurface(surf, IntRect(IntPoint(), aSize), IntPoint()); + } } FinishTextures(aDeviceManager, texture, surface); @@ -618,11 +620,19 @@ CairoTextureClientD3D9::Lock(OpenMode aMode) if (mNeedsClear) { mDrawTarget = BorrowDrawTarget(); + if (!mDrawTarget) { + Unlock(); + return false; + } mDrawTarget->ClearRect(Rect(0, 0, GetSize().width, GetSize().height)); mNeedsClear = false; } if (mNeedsClearWhite) { mDrawTarget = BorrowDrawTarget(); + if (!mDrawTarget) { + Unlock(); + return false; + } mDrawTarget->FillRect(Rect(0, 0, GetSize().width, GetSize().height), ColorPattern(Color(1.0, 1.0, 1.0, 1.0))); mNeedsClearWhite = false; } diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 4aab23384e89..f1eefcd7e8c9 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -1229,9 +1229,10 @@ CompositorOGL::EndFrame() mWidget->GetBounds(rect); } RefPtr target = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(rect.width, rect.height), SurfaceFormat::B8G8R8A8); - CopyToTarget(target, nsIntPoint(), Matrix()); - - WriteSnapshotToDumpFile(this, target); + if (target) { + CopyToTarget(target, nsIntPoint(), Matrix()); + WriteSnapshotToDumpFile(this, target); + } } #endif @@ -1343,6 +1344,7 @@ CompositorOGL::SetDestinationSurfaceSize(const gfx::IntSize& aSize) void CompositorOGL::CopyToTarget(DrawTarget* aTarget, const nsIntPoint& aTopLeft, const gfx::Matrix& aTransform) { + MOZ_ASSERT(aTarget); IntRect rect; if (mUseExternalSurfaceSize) { rect = IntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 69d04c1fa910..256bcff63f53 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -727,6 +727,10 @@ gfxPlatform::CreateDrawTargetForSurface(gfxASurface *aSurface, const IntSize& aS { SurfaceFormat format = Optimal2DFormatForContent(aSurface->GetContentType()); RefPtr drawTarget = Factory::CreateDrawTargetForCairoSurface(aSurface->CairoSurface(), aSize, &format); + if (!drawTarget) { + gfxWarning() << "gfxPlatform::CreateDrawTargetForSurface failed in CreateDrawTargetForCairoSurface"; + return nullptr; + } aSurface->SetData(&kDrawTarget, drawTarget, nullptr); return drawTarget.forget(); } @@ -909,6 +913,10 @@ gfxPlatform::GetSourceSurfaceForSurface(DrawTarget *aTarget, gfxASurface *aSurfa surf.mSize = ToIntSize(aSurface->GetSize()); RefPtr drawTarget = Factory::CreateDrawTarget(BackendType::CAIRO, IntSize(1, 1), format); + if (!drawTarget) { + gfxWarning() << "gfxPlatform::GetSourceSurfaceForSurface failed in CreateDrawTarget"; + return nullptr; + } srcBuffer = drawTarget->CreateSourceSurfaceFromNativeSurface(surf); if (srcBuffer) { srcBuffer = aTarget->OptimizeSourceSurface(srcBuffer); diff --git a/gfx/thebes/gfxUtils.cpp b/gfx/thebes/gfxUtils.cpp index 4cd1990137fc..f7650c761ff4 100644 --- a/gfx/thebes/gfxUtils.cpp +++ b/gfx/thebes/gfxUtils.cpp @@ -14,6 +14,7 @@ #include "mozilla/Base64.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/DataSurfaceHelpers.h" +#include "mozilla/gfx/Logging.h" #include "mozilla/Maybe.h" #include "mozilla/RefPtr.h" #include "mozilla/Vector.h" @@ -1037,6 +1038,11 @@ gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, // GPU. RefPtr dt = gfxPlatform::GetPlatform()-> CreateOffscreenContentDrawTarget(aSurface->GetSize(), aFormat); + if (!dt) { + gfxWarning() << "gfxUtils::CopySurfaceToDataSourceSurfaceWithFormat failed in CreateOffscreenContentDrawTarget"; + return nullptr; + } + // Using DrawSurface() here rather than CopySurface() because CopySurface // is optimized for memcpy and therefore isn't good for format conversion. // Using OP_OVER since in our case it's equivalent to OP_SOURCE and diff --git a/image/src/DynamicImage.cpp b/image/src/DynamicImage.cpp index 19ec5de99186..01baf40cb561 100644 --- a/image/src/DynamicImage.cpp +++ b/image/src/DynamicImage.cpp @@ -184,6 +184,10 @@ DynamicImage::GetFrame(uint32_t aWhichFrame, RefPtr dt = gfxPlatform::GetPlatform()-> CreateOffscreenContentDrawTarget(IntSize(size.width, size.height), SurfaceFormat::B8G8R8A8); + if (!dt) { + gfxWarning() << "DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget"; + return nullptr; + } nsRefPtr context = new gfxContext(dt); auto result = Draw(context, size, ImageRegion::Create(size), diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index e1dc30f82d3f..f2ddef406d28 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -692,6 +692,10 @@ RasterImage::CopyFrame(uint32_t aWhichFrame, uint32_t aFlags) size, mapping.mStride, SurfaceFormat::B8G8R8A8); + if (!target) { + gfxWarning() << "RasterImage::CopyFrame failed in CreateDrawTargetForData"; + return nullptr; + } nsIntRect intFrameRect = frameRef->GetRect(); Rect rect(intFrameRect.x, intFrameRect.y, diff --git a/image/src/imgFrame.cpp b/image/src/imgFrame.cpp index 4a1d425f14f3..3dfa76f2f227 100644 --- a/image/src/imgFrame.cpp +++ b/image/src/imgFrame.cpp @@ -483,6 +483,10 @@ nsresult imgFrame::Optimize() mapping.mStride, optFormat); + if (!target) { + gfxWarning() << "imgFrame::Optimize failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } Rect rect(0, 0, mSize.width, mSize.height); target->DrawSurface(mImageSurface, rect, rect); target->Flush(); @@ -882,6 +886,10 @@ imgFrame::Deoptimize() mSize, mapping.mStride, format); + if (!target) { + gfxWarning() << "imgFrame::Deoptimize failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } Rect rect(0, 0, mSize.width, mSize.height); if (mSinglePixel) diff --git a/image/src/imgTools.cpp b/image/src/imgTools.cpp index b81ac32deba2..c128df3f3ff7 100644 --- a/image/src/imgTools.cpp +++ b/image/src/imgTools.cpp @@ -221,6 +221,11 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer, dataSurface->GetSize(), map.mStride, SurfaceFormat::B8G8R8A8); + if (!dt) { + gfxWarning() << "imgTools::EncodeImage failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } + dt->DrawSurface(frame, Rect(0, 0, aScaledWidth, aScaledHeight), Rect(0, 0, frameWidth, frameHeight), @@ -293,6 +298,10 @@ NS_IMETHODIMP imgTools::EncodeCroppedImage(imgIContainer *aContainer, dataSurface->GetSize(), map.mStride, SurfaceFormat::B8G8R8A8); + if (!dt) { + gfxWarning() << "imgTools::EncodeCroppedImage failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } dt->CopySurface(frame, IntRect(aOffsetX, aOffsetY, aWidth, aHeight), IntPoint(0, 0)); diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 1d86c20f57d0..380ddc89fc93 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -2716,9 +2716,11 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder, tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( itemVisibleRect.Size().ToIntSize(), SurfaceFormat::B8G8R8A8); - context = new gfxContext(tempDT); - context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x, - -itemVisibleRect.y)); + if (tempDT) { + context = new gfxContext(tempDT); + context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x, + -itemVisibleRect.y)); + } } #endif basic->BeginTransaction(); @@ -2740,7 +2742,7 @@ PaintInactiveLayer(nsDisplayListBuilder* aBuilder, basic->SetTarget(nullptr); #ifdef MOZ_DUMP_PAINTING - if (gfxUtils::sDumpPainting) { + if (gfxUtils::sDumpPainting && tempDT) { RefPtr surface = tempDT->Snapshot(); DumpPaintedImage(aItem, surface); diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 48558b9d9d7e..dbb3d8568729 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -3460,6 +3460,7 @@ NSEvent* gLastDragMouseDownEvent = nil; gfx::Factory::CreateDrawTargetForCairoCGContext(aContext, gfx::IntSize(backingSize.width, backingSize.height)); + MOZ_ASSERT(dt); // see implementation dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr); targetContext = new gfxContext(dt); } else if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(gfx::BackendType::CAIRO)) { diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 20f6d9121231..e7294cbf18cc 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -45,6 +45,7 @@ #include "pixelflinger/format.h" #include "mozilla/BasicEvents.h" #include "mozilla/gfx/2D.h" +#include "mozilla/gfx/Logging.h" #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/APZThreadUtils.h" #include "mozilla/layers/CompositorParent.h" @@ -704,6 +705,9 @@ nsWindow::StartRemoteDrawing() mFramebufferTarget = Factory::CreateDrawTargetForData( BackendType::CAIRO, (uint8_t*)vaddr, IntSize(width, height), mFramebuffer->stride * bytepp, format); + if (!mFramebufferTarget) { + MOZ_CRASH("nsWindow::StartRemoteDrawing failed in CreateDrawTargetForData"); + } if (!mBackBuffer || mBackBuffer->GetSize() != mFramebufferTarget->GetSize() || mBackBuffer->GetFormat() != mFramebufferTarget->GetFormat()) { diff --git a/widget/windows/WinUtils.cpp b/widget/windows/WinUtils.cpp index 8fd30660c5d3..fad28a9afa3a 100644 --- a/widget/windows/WinUtils.cpp +++ b/widget/windows/WinUtils.cpp @@ -1198,6 +1198,10 @@ AsyncFaviconDataReady::OnComplete(nsIURI *aFaviconURI, dataSurface->GetSize(), map.mStride, dataSurface->GetFormat()); + if (!dt) { + gfxWarning() << "AsyncFaviconDataReady::OnComplete failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } dt->FillRect(Rect(0, 0, size.width, size.height), ColorPattern(Color(1.0f, 1.0f, 1.0f, 1.0f))); dt->DrawSurface(surface, diff --git a/widget/windows/nsWindowGfx.cpp b/widget/windows/nsWindowGfx.cpp index c6463fe02ad1..923dde200443 100644 --- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -390,6 +390,11 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(targetSurface, IntSize(paintRect.right - paintRect.left, paintRect.bottom - paintRect.top)); + if (!dt) { + gfxWarning() << "nsWindow::OnPaint failed in CreateDrawTargetForSurface"; + return false; + } + // don't need to double buffer with anything but GDI BufferMode doubleBuffering = mozilla::layers::BufferMode::BUFFER_NONE; if (IsRenderMode(gfxWindowsPlatform::RENDER_GDI) || @@ -627,6 +632,10 @@ nsresult nsWindowGfx::CreateIcon(imgIContainer *aContainer, dataSurface->GetSize(), map.mStride, SurfaceFormat::B8G8R8A8); + if (!dt) { + gfxWarning() << "nsWindowGfx::CreatesIcon failed in CreateDrawTargetForData"; + return NS_ERROR_OUT_OF_MEMORY; + } dt->DrawSurface(surface, Rect(0, 0, iconSize.width, iconSize.height), Rect(0, 0, frameSize.width, frameSize.height),