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 290198 d6e3295ba91596dece2b32f76526433a16ad39cd
parent 290197 1ec19ec66b5dbf8224a0f3a5dbf1ca890d64cf6f
child 290199 ad88856cdfdc498bf299d5ac074699a4061b5ada
push id30114
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:15:54 +0000
treeherdermozilla-central@24c5fbde4488 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslongsonr
bugs1253590
milestone48.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 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);