Bug 1253590, part 2 - Use the new AutoReferenceLimiter helper to limit clip path reference chain lengths. r=longsonr
authorJonathan Watt <jwatt@jwatt.org>
Wed, 09 Mar 2016 10:26:48 +0000
changeset 290222 d6e3295ba91596dece2b32f76526433a16ad39cd
parent 290221 1ec19ec66b5dbf8224a0f3a5dbf1ca890d64cf6f
child 290223 ad88856cdfdc498bf299d5ac074699a4061b5ada
push id18353
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:20:25 +0000
treeherderfx-team@40ae8489939e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1253590
milestone48.0a1
Bug 1253590, part 2 - Use the new AutoReferenceLimiter helper to limit clip path reference chain lengths. r=longsonr
layout/svg/nsSVGClipPathFrame.cpp
--- a/layout/svg/nsSVGClipPathFrame.cpp
+++ b/layout/svg/nsSVGClipPathFrame.cpp
@@ -14,16 +14,19 @@
 #include "nsSVGPathGeometryElement.h"
 #include "nsSVGPathGeometryFrame.h"
 #include "nsSVGUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
+// Arbitrary number
+#define MAX_SVG_CLIP_PATH_REFERENCE_CHAIN_LENGTH int16_t(512)
+
 //----------------------------------------------------------------------
 // Implementation
 
 nsIFrame*
 NS_NewSVGClipPathFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsSVGClipPathFrame(aContext);
 }
@@ -85,17 +88,27 @@ nsSVGClipPathFrame::GetClipMask(gfxConte
                                 Matrix* aMaskTransform,
                                 SourceSurface* aExtraMask,
                                 const Matrix& aExtraMasksTransform)
 {
   MOZ_ASSERT(!IsTrivial(), "Caller needs to use ApplyClipPath");
 
   DrawTarget& aReferenceDT = *aReferenceContext.GetDrawTarget();
 
-  // To prevent reference loops we check that this clipPath only appears
+  // A clipPath can reference another clipPath.  We re-enter this method for
+  // each clipPath in a reference chain, so here we limit chain length:
+  static int16_t sRefChainLengthCounter = AutoReferenceLimiter::notReferencing;
+  AutoReferenceLimiter
+    refChainLengthLimiter(&sRefChainLengthCounter,
+                          MAX_SVG_CLIP_PATH_REFERENCE_CHAIN_LENGTH);
+  if (!refChainLengthLimiter.Reference()) {
+    return false; // Reference chain is too long!
+  }
+
+  // And to prevent reference loops we check that this clipPath only appears
   // once in the reference chain (if any) that we're currently processing:
   AutoReferenceLimiter refLoopDetector(&mReferencing, 1);
   if (!refLoopDetector.Reference()) {
     return nullptr; // Reference loop!
   }
 
   IntRect devSpaceClipExtents;
   {
@@ -234,17 +247,27 @@ nsSVGClipPathFrame::GetClipMask(gfxConte
   *aMaskTransform = ToMatrix(mat);
   return maskDT->Snapshot();
 }
 
 bool
 nsSVGClipPathFrame::PointIsInsideClipPath(nsIFrame* aClippedFrame,
                                           const gfxPoint &aPoint)
 {
-  // To prevent reference loops we check that this clipPath only appears
+  // A clipPath can reference another clipPath.  We re-enter this method for
+  // each clipPath in a reference chain, so here we limit chain length:
+  static int16_t sRefChainLengthCounter = AutoReferenceLimiter::notReferencing;
+  AutoReferenceLimiter
+    refChainLengthLimiter(&sRefChainLengthCounter,
+                          MAX_SVG_CLIP_PATH_REFERENCE_CHAIN_LENGTH);
+  if (!refChainLengthLimiter.Reference()) {
+    return false; // Reference chain is too long!
+  }
+
+  // And to prevent reference loops we check that this clipPath only appears
   // once in the reference chain (if any) that we're currently processing:
   AutoReferenceLimiter refLoopDetector(&mReferencing, 1);
   if (!refLoopDetector.Reference()) {
     return true; // Reference loop!
   }
 
   gfxMatrix matrix = GetClipPathTransform(aClippedFrame);
   if (!matrix.Invert()) {
@@ -318,17 +341,27 @@ nsSVGClipPathFrame::IsTrivial(nsISVGChil
     *aSingleChild = foundChild;
   }
   return true;
 }
 
 bool
 nsSVGClipPathFrame::IsValid()
 {
-  // To prevent reference loops we check that this clipPath only appears
+  // A clipPath can reference another clipPath.  We re-enter this method for
+  // each clipPath in a reference chain, so here we limit chain length:
+  static int16_t sRefChainLengthCounter = AutoReferenceLimiter::notReferencing;
+  AutoReferenceLimiter
+    refChainLengthLimiter(&sRefChainLengthCounter,
+                          MAX_SVG_CLIP_PATH_REFERENCE_CHAIN_LENGTH);
+  if (!refChainLengthLimiter.Reference()) {
+    return false; // Reference chain is too long!
+  }
+
+  // And to prevent reference loops we check that this clipPath only appears
   // once in the reference chain (if any) that we're currently processing:
   AutoReferenceLimiter refLoopDetector(&mReferencing, 1);
   if (!refLoopDetector.Reference()) {
     return false; // Reference loop!
   }
 
   bool isOK = true;
   nsSVGEffects::GetEffectProperties(this).GetClipPathFrame(&isOK);