diff --git a/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp b/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp index cb7c17fcb72..2214a10cde3 100644 --- a/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp +++ b/mozilla/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -74,6 +74,7 @@ nsSVGMaskFrame::InitSVG() return rv; mMaskParentMatrix = nsnull; + mInUse = PR_FALSE; nsCOMPtr mask = do_QueryInterface(mContent); NS_ASSERTION(mask, "wrong content element"); @@ -88,6 +89,15 @@ nsSVGMaskFrame::ComputeMaskAlpha(nsSVGRenderState *aContext, nsIDOMSVGMatrix* aMatrix, float aOpacity) { + // If the flag is set when we get here, it means this mask frame + // has already been used painting the current mask, and the document + // has a mask reference loop. + if (mInUse) { + NS_WARNING("Mask loop detected!"); + return nsnull; + } + AutoMaskReferencer maskRef(this); + gfxContext *gfx = aContext->GetGfxContext(); gfx->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA); diff --git a/mozilla/layout/svg/base/src/nsSVGMaskFrame.h b/mozilla/layout/svg/base/src/nsSVGMaskFrame.h index 2c616dd3686..88bad7a7c29 100644 --- a/mozilla/layout/svg/base/src/nsSVGMaskFrame.h +++ b/mozilla/layout/svg/base/src/nsSVGMaskFrame.h @@ -75,8 +75,29 @@ class nsSVGMaskFrame : public nsSVGMaskFrameBase #endif private: + // A helper class to allow us to paint masks safely. The helper + // automatically sets and clears the mInUse flag on the mask frame + // (to prevent nasty reference loops). It's easy to mess this up + // and break things, so this helper makes the code far more robust. + class AutoMaskReferencer + { + public: + AutoMaskReferencer(nsSVGMaskFrame *aFrame) + : mFrame(aFrame) { + NS_ASSERTION(mFrame->mInUse == PR_FALSE, "reference loop!"); + mFrame->mInUse = PR_TRUE; + } + ~AutoMaskReferencer() { + mFrame->mInUse = PR_FALSE; + } + private: + nsSVGMaskFrame *mFrame; + }; + nsISVGChildFrame *mMaskParent; nsCOMPtr mMaskParentMatrix; + // recursion prevention flag + PRPackedBool mInUse; // nsSVGContainerFrame methods: virtual already_AddRefed GetCanvasTM();