Bug 1365189 - Prevent painting of non-displayable SVG elements. r=dholbert
☠☠ backed out by 3b51e0c8b6cc ☠ ☠
authorJonathan Watt <jwatt@jwatt.org>
Fri, 28 Apr 2017 17:03:36 +0100
changeset 409586 7b3e7c43611ba7c586eacfd00af7dce905f97b92
parent 409585 77d2dd511cf91661f82d944349657b2e25f30fdc
child 409587 61bea8a3b2dbe040462ea430d17e09427827d62f
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1365189
milestone55.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 1365189 - Prevent painting of non-displayable SVG elements. r=dholbert
layout/painting/nsImageRenderer.cpp
layout/svg/nsSVGIntegrationUtils.cpp
--- a/layout/painting/nsImageRenderer.cpp
+++ b/layout/painting/nsImageRenderer.cpp
@@ -14,16 +14,17 @@
 #include "ImageOps.h"
 #include "mozilla/layers/StackingContextHelper.h"
 #include "nsContentUtils.h"
 #include "nsCSSRendering.h"
 #include "nsCSSRenderingGradients.h"
 #include "nsIFrame.h"
 #include "nsRenderingContext.h"
 #include "nsStyleStructInlines.h"
+#include "nsSVGDisplayableFrame.h"
 #include "nsSVGEffects.h"
 #include "nsSVGIntegrationUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::image;
 using namespace mozilla::layers;
 
@@ -187,21 +188,26 @@ nsImageRenderer::PrepareImage()
         return false;
       }
 
       // If the referenced element is an <img>, <canvas>, or <video> element,
       // prefer SurfaceFromElement as it's more reliable.
       mImageElementSurface =
         nsLayoutUtils::SurfaceFromElement(property->GetReferencedElement());
       if (!mImageElementSurface.GetSourceSurface()) {
-        mPaintServerFrame = property->GetReferencedFrame();
-        if (!mPaintServerFrame) {
+        nsIFrame* paintServerFrame = property->GetReferencedFrame();
+        // If there's no referenced frame, or the referenced frame is
+        // non-displayable SVG, then we have nothing valid to paint.
+        if (!paintServerFrame ||
+            (paintServerFrame->IsFrameOfType(nsIFrame::eSVG) &&
+             !static_cast<nsSVGDisplayableFrame*>(do_QueryFrame(paintServerFrame)))) {
           mPrepareResult = DrawResult::BAD_IMAGE;
           return false;
         }
+        mPaintServerFrame = paintServerFrame;
       }
 
       mPrepareResult = DrawResult::SUCCESS;
       break;
     }
     case eStyleImageType_Null:
     default:
       break;
--- a/layout/svg/nsSVGIntegrationUtils.cpp
+++ b/layout/svg/nsSVGIntegrationUtils.cpp
@@ -1239,15 +1239,22 @@ nsSVGIntegrationUtils::DrawableFromPaint
     gfxFloat scaleY = overrideBounds.Height() / aRenderSize.height;
     gfxMatrix scaleMatrix = gfxMatrix::Scaling(scaleX, scaleY);
     pattern->SetMatrix(scaleMatrix * pattern->GetMatrix());
     RefPtr<gfxDrawable> drawable =
       new gfxPatternDrawable(pattern, aRenderSize);
     return drawable.forget();
   }
 
+  if (aFrame->IsFrameOfType(nsIFrame::eSVG) &&
+      !static_cast<nsSVGDisplayableFrame*>(do_QueryFrame(aFrame))) {
+    MOZ_ASSERT_UNREACHABLE("We should prevent painting of unpaintable SVG "
+                           "before we get here");
+    return nullptr;
+  }
+
   // We don't want to paint into a surface as long as we don't need to, so we
   // set up a drawing callback.
   RefPtr<gfxDrawingCallback> cb =
     new PaintFrameCallback(aFrame, aPaintServerSize, aRenderSize, aFlags);
   RefPtr<gfxDrawable> drawable = new gfxCallbackDrawable(cb, aRenderSize);
   return drawable.forget();
 }