diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index d52d8ebba3e..b572a96ae67 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -51,6 +51,13 @@ #include "gfxContext.h" #include "gfxImageSurface.h" +// maximum dimension of a filter - choose so that +// 4*(FILTER_RES_MAX^2) < UINT_MAX, it's small +// enough that it could be computed in a reasonable +// amount of time, and large enough for most content +// window sizes. +#define FILTER_RES_MAX 16384 + nsIFrame* NS_NewSVGFilterFrame(nsIPresShell* aPresShell, nsIContent* aContent, nsStyleContext* aContext) { @@ -197,6 +204,10 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, if (filterResX <= 0.0f || filterResY <= 0.0f) return NS_OK; + // prevent filters from overflowing or generally using excessive memory + filterResX = PR_MIN(FILTER_RES_MAX, filterResX); + filterResY = PR_MIN(FILTER_RES_MAX, filterResY); + #ifdef DEBUG_tor fprintf(stderr, "filter bbox: %f,%f %fx%f\n", x, y, width, height); fprintf(stderr, "filterRes: %u %u\n", filterResX, filterResY); @@ -213,7 +224,7 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, // paint the target geometry nsRefPtr tmpSurface = new gfxImageSurface(gfxIntSize(filterResX, filterResY), gfxASurface::ImageFormatARGB32); - if (!tmpSurface) { + if (!tmpSurface || !tmpSurface->Data()) { FilterFailCleanup(aContext, aTarget); return NS_OK; } @@ -239,7 +250,9 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, cairo_image_surface_create(CAIRO_FORMAT_ARGB32, filterResX, filterResY); - if (!alpha) { + if (!alpha || cairo_surface_status(alpha)) { + if (alpha) + cairo_surface_destroy(alpha); FilterFailCleanup(aContext, aTarget); return NS_OK; } @@ -248,8 +261,8 @@ nsSVGFilterFrame::FilterPaint(nsSVGRenderState *aContext, PRUint8 *alphaData = cairo_image_surface_get_data(alpha); PRUint32 stride = tmpSurface->Stride(); - for (PRUint32 yy=0; yy