Bug 592118 - Don't stack-allocate gfxContexts that are passed to other functions. r=roc a=blocking2.0:final
authorMarkus Stange <mstange@themasta.com>
Fri, 15 Oct 2010 12:20:22 +0200
changeset 55854 d27d7109949888415f956c13d640070157a227bc
parent 55853 01c8100757c444f5209dc47680aa6b11877ac3fd
child 55855 8130457aed614e10b985554d5b4ef45fe5d16b3a
push idunknown
push userunknown
push dateunknown
reviewersroc, blocking2
bugs592118
milestone2.0b8pre
Bug 592118 - Don't stack-allocate gfxContexts that are passed to other functions. r=roc a=blocking2.0:final
content/svg/content/src/nsSVGFilters.cpp
content/svg/content/src/nsSVGPathElement.cpp
gfx/thebes/gfxUtils.cpp
layout/generic/crashtests/592118.html
layout/generic/crashtests/crashtests.list
layout/svg/base/src/nsSVGPathGeometryFrame.cpp
--- a/content/svg/content/src/nsSVGFilters.cpp
+++ b/content/svg/content/src/nsSVGFilters.cpp
@@ -5560,18 +5560,18 @@ nsSVGFEImageElement::Filter(nsSVGFilterI
                                       filterSubregion.Width(), filterSubregion.Height(),
                                       0,0, nativeWidth, nativeHeight,
                                       mPreserveAspectRatio);
 
     gfxMatrix xyTM = gfxMatrix().Translate(gfxPoint(filterSubregion.X(), filterSubregion.Y()));
 
     gfxMatrix TM = viewBoxTM * xyTM;
     
-    gfxContext ctx(aTarget->mImage);
-    nsSVGUtils::CompositePatternMatrix(&ctx, thebesPattern, TM, nativeWidth, nativeHeight, 1.0);
+    nsRefPtr<gfxContext> ctx = new gfxContext(aTarget->mImage);
+    nsSVGUtils::CompositePatternMatrix(ctx, thebesPattern, TM, nativeWidth, nativeHeight, 1.0);
   }
 
   return NS_OK;
 }
 
 nsIntRect
 nsSVGFEImageElement::ComputeTargetBBox(const nsTArray<nsIntRect>& aSourceBBoxes,
         const nsSVGFilterInstance& aInstance)
--- a/content/svg/content/src/nsSVGPathElement.cpp
+++ b/content/svg/content/src/nsSVGPathElement.cpp
@@ -1037,16 +1037,17 @@ nsSVGPathList::Playback(gfxContext *aCtx
       break;
     }
   }
 }
 
 already_AddRefed<gfxFlattenedPath>
 nsSVGPathList::GetFlattenedPath(const gfxMatrix& aMatrix)
 {
-  gfxContext ctx(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+  nsRefPtr<gfxContext> ctx =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
-  ctx.SetMatrix(aMatrix);
-  Playback(&ctx);
-  ctx.IdentityMatrix();
+  ctx->SetMatrix(aMatrix);
+  Playback(ctx);
+  ctx->IdentityMatrix();
 
-  return ctx.GetFlattenedPath();
+  return ctx->GetFlattenedPath();
 }
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -265,19 +265,19 @@ CreateSamplingRestrictedDrawable(gfxDraw
         return nsnull;
 
     gfxIntSize size(PRInt32(needed.Width()), PRInt32(needed.Height()));
     nsRefPtr<gfxASurface> temp =
         gfxPlatform::GetPlatform()->CreateOffscreenSurface(size, gfxASurface::ContentFromFormat(aFormat));
     if (!temp || temp->CairoStatus())
         return nsnull;
 
-    gfxContext tmpCtx(temp);
-    tmpCtx.SetOperator(OptimalFillOperator());
-    aDrawable->Draw(&tmpCtx, needed - needed.pos, PR_TRUE,
+    nsRefPtr<gfxContext> tmpCtx = new gfxContext(temp);
+    tmpCtx->SetOperator(OptimalFillOperator());
+    aDrawable->Draw(tmpCtx, needed - needed.pos, PR_TRUE,
                     gfxPattern::FILTER_FAST, gfxMatrix().Translate(needed.pos));
 
     nsRefPtr<gfxPattern> resultPattern = new gfxPattern(temp);
     if (!resultPattern)
         return nsnull;
 
     nsRefPtr<gfxDrawable> drawable = 
         new gfxSurfaceDrawable(temp, size, gfxMatrix().Translate(-needed.pos));
new file mode 100755
--- /dev/null
+++ b/layout/generic/crashtests/592118.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<title>Stack pointer free with -moz-element</title>
+<div id="paintServer" style="width: 20px; height: 20px; background: red;"></div>
+<div style="-moz-transform: scale(1.01); width: 100px; height: 100px; background: -moz-element(#paintServer) -5px -3px; background-size: 20px 32769px;"></div>
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -333,8 +333,9 @@ load 580504-1.xhtml
 load 585598-1.xhtml
 load 586806-1.html
 load 586806-2.html
 load 586806-3.html
 load 586973-1.html
 load 589002-1.html
 load 590404.html
 load 591141.html
+asserts(0-1) load 592118.html
--- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp
+++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp
@@ -165,33 +165,34 @@ nsSVGPathGeometryFrame::GetFrameForPoint
     if (!mask || (!(mask & HITTEST_MASK_FORCE_TEST) &&
                   !mRect.Contains(aPoint)))
       return nsnull;
     fillRule = GetStyleSVG()->mFillRule;
   }
 
   PRBool isHit = PR_FALSE;
 
-  gfxContext context(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+  nsRefPtr<gfxContext> context =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
-  GeneratePath(&context);
+  GeneratePath(context);
   gfxPoint userSpacePoint =
-    context.DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
-                                  PresContext()->AppUnitsToGfxUnits(aPoint.y)));
+    context->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
+                                   PresContext()->AppUnitsToGfxUnits(aPoint.y)));
 
   if (fillRule == NS_STYLE_FILL_RULE_EVENODD)
-    context.SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
+    context->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
   else
-    context.SetFillRule(gfxContext::FILL_RULE_WINDING);
+    context->SetFillRule(gfxContext::FILL_RULE_WINDING);
 
   if (mask & HITTEST_MASK_FILL)
-    isHit = context.PointInFill(userSpacePoint);
+    isHit = context->PointInFill(userSpacePoint);
   if (!isHit && (mask & HITTEST_MASK_STROKE)) {
-    SetupCairoStrokeHitGeometry(&context);
-    isHit = context.PointInStroke(userSpacePoint);
+    SetupCairoStrokeHitGeometry(context);
+    isHit = context->PointInStroke(userSpacePoint);
   }
 
   if (isHit && nsSVGUtils::HitTestClip(this, aPoint))
     return this;
 
   return nsnull;
 }
 
@@ -245,42 +246,43 @@ nsSVGPathGeometryFrame::GetCoveredRegion
   return mRect;
 }
 
 NS_IMETHODIMP
 nsSVGPathGeometryFrame::UpdateCoveredRegion()
 {
   mRect.Empty();
 
-  gfxContext context(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+  nsRefPtr<gfxContext> context =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
 
-  GeneratePath(&context);
-  context.IdentityMatrix();
+  GeneratePath(context);
+  context->IdentityMatrix();
 
-  gfxRect extent = context.GetUserPathExtent();
+  gfxRect extent = context->GetUserPathExtent();
 
   // Be careful when replacing the following logic to get the fill and stroke
   // extents independently (instead of computing the stroke extents from the
   // path extents). You may think that you can just use the stroke extents if
   // there is both a fill and a stroke. In reality it's necessary to calculate
   // both the fill and stroke extents, and take the union of the two. There are
   // two reasons for this:
   //
   // # Due to stroke dashing, in certain cases the fill extents could actually
   //   extend outside the stroke extents.
   // # If the stroke is very thin, cairo won't paint any stroke, and so the
   //   stroke bounds that it will return will be empty.
 
   if (HasStroke()) {
-    SetupCairoStrokeGeometry(&context);
+    SetupCairoStrokeGeometry(context);
     if (extent.Width() <= 0 && extent.Height() <= 0) {
       // If 'extent' is empty, its position will not be set. Although
       // GetUserStrokeExtent gets the extents wrong we can still use it
       // to get the device space position of zero length stroked paths.
-      extent = context.GetUserStrokeExtent();
+      extent = context->GetUserStrokeExtent();
       extent.pos.x += extent.size.width / 2;
       extent.pos.y += extent.size.height / 2;
       extent.size.width = 0;
       extent.size.height = 0;
     }
     extent = nsSVGUtils::PathExtentsToMaxStrokeExtents(extent, this);
   } else if (GetStyleSVG()->mFill.mType == eStyleSVGPaintType_None) {
     extent = gfxRect(0, 0, 0, 0);
@@ -357,20 +359,21 @@ nsSVGPathGeometryFrame::GetMatrixPropaga
 
 gfxRect
 nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace)
 {
   if (aToBBoxUserspace.IsSingular()) {
     // XXX ReportToConsole
     return gfxRect(0.0, 0.0, 0.0, 0.0);
   }
-  gfxContext context(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
-  GeneratePath(&context, &aToBBoxUserspace);
-  context.IdentityMatrix();
-  return context.GetUserPathExtent();
+  nsRefPtr<gfxContext> context =
+    new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
+  GeneratePath(context, &aToBBoxUserspace);
+  context->IdentityMatrix();
+  return context->GetUserPathExtent();
 }
 
 //----------------------------------------------------------------------
 // nsSVGGeometryFrame methods:
 
 gfxMatrix
 nsSVGPathGeometryFrame::GetCanvasTM()
 {