author | Jonathan Watt <jwatt@jwatt.org> |
Wed, 09 Mar 2016 10:26:48 +0000 | |
changeset 290198 | d6e3295ba91596dece2b32f76526433a16ad39cd |
parent 290197 | 1ec19ec66b5dbf8224a0f3a5dbf1ca890d64cf6f |
child 290199 | ad88856cdfdc498bf299d5ac074699a4061b5ada |
push id | 30114 |
push user | cbook@mozilla.com |
push date | Thu, 24 Mar 2016 15:15:54 +0000 |
treeherder | mozilla-central@24c5fbde4488 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | longsonr |
bugs | 1253590 |
milestone | 48.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
|
--- 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);