Commit d458b69d authored by dino@apple.com's avatar dino@apple.com

Don't process filters if the input region is exceptionally large.

https://bugs.webkit.org/show_bug.cgi?id=83317

Reviewed by Simon Fraser.

Source/WebCore:

An extremely large element causes problems with filters, either by
taking too long to compute the output or using too much memory. The
filter engine already has some constants for maximum expected size.
Make sure the render tree checks them before deciding to apply
effects.

Tests: css3/filters/huge-region-composited.html
       css3/filters/huge-region.html

* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::apply):
* rendering/FilterEffectRenderer.cpp:
(WebCore):
(WebCore::isFilterSizeValid):
(WebCore::FilterEffectRenderer::build):
(WebCore::FilterEffectRenderer::updateBackingStore):
(WebCore::FilterEffectRendererHelper::beginFilterEffect):
* rendering/FilterEffectRenderer.h:
(FilterEffectRenderer):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateOrRemoveFilterEffect):

LayoutTests:

* css3/filters/huge-region-composited-expected.txt: Added.
* css3/filters/huge-region-composited.html: Added.
* css3/filters/huge-region-expected.txt: Added.
* css3/filters/huge-region.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@114172 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 086b2942
2012-04-13 Dean Jackson <dino@apple.com>
Don't process filters if the input region is exceptionally large.
https://bugs.webkit.org/show_bug.cgi?id=83317
Reviewed by Simon Fraser.
* css3/filters/huge-region-composited-expected.txt: Added.
* css3/filters/huge-region-composited.html: Added.
* css3/filters/huge-region-expected.txt: Added.
* css3/filters/huge-region.html: Added.
2012-04-13 Anna Cavender <annacc@chromium.org>
Queue the cuechange event on HTMLTrackElement for proper sorting.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.big {
width: 50px;
height: 50px;
padding-bottom: 65536%;
-webkit-filter: blur(2147483648px);
-webkit-transform: translate3d(0, 0, 0);
}
</style>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText(true);
</script>
</head>
<body>
<div class="big">This element is too big to filter.</div>
</body>
</html>
This element is too big to filter.
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.big {
width: 50px;
height: 50px;
padding-bottom: 65536%;
-webkit-filter: blur(2147483648px);
}
</style>
<script>
if (window.layoutTestController)
layoutTestController.dumpAsText(true);
</script>
</head>
<body>
<div class="big">This element is too big to filter.</div>
</body>
</html>
2012-04-13 Dean Jackson <dino@apple.com>
Don't process filters if the input region is exceptionally large.
https://bugs.webkit.org/show_bug.cgi?id=83317
Reviewed by Simon Fraser.
An extremely large element causes problems with filters, either by
taking too long to compute the output or using too much memory. The
filter engine already has some constants for maximum expected size.
Make sure the render tree checks them before deciding to apply
effects.
Tests: css3/filters/huge-region-composited.html
css3/filters/huge-region.html
* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::apply):
* rendering/FilterEffectRenderer.cpp:
(WebCore):
(WebCore::isFilterSizeValid):
(WebCore::FilterEffectRenderer::build):
(WebCore::FilterEffectRenderer::updateBackingStore):
(WebCore::FilterEffectRendererHelper::beginFilterEffect):
* rendering/FilterEffectRenderer.h:
(FilterEffectRenderer):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::updateOrRemoveFilterEffect):
2012-04-13 Anna Cavender <annacc@chromium.org>
Queue the cuechange event on HTMLTrackElement for proper sorting.
......@@ -103,6 +103,9 @@ void FilterEffect::apply()
}
determineAbsolutePaintRect();
if (!isFilterSizeValid(m_absolutePaintRect))
return;
if (requiresValidPreMultipliedPixels()) {
for (unsigned i = 0; i < size; ++i)
inputEffect(i)->correctFilterResultIfNeeded();
......
......@@ -66,8 +66,15 @@ static inline void lastMatrixRow(Vector<float>& parameters)
parameters.append(1);
parameters.append(0);
}
inline bool isFilterSizeValid(FloatRect rect)
{
if (rect.width() < 0 || rect.width() > kMaxFilterSize
|| rect.height() < 0 || rect.height() > kMaxFilterSize)
return false;
return true;
}
#if ENABLE(CSS_SHADERS) && ENABLE(WEBGL)
static bool isCSSCustomFilterEnabled(Document* document)
{
......@@ -98,7 +105,7 @@ GraphicsContext* FilterEffectRenderer::inputContext()
return sourceImage() ? sourceImage()->context() : 0;
}
void FilterEffectRenderer::build(Document* document, const FilterOperations& operations)
bool FilterEffectRenderer::build(Document* document, const FilterOperations& operations)
{
#if !ENABLE(CSS_SHADERS) || !ENABLE(WEBGL)
UNUSED_PARAM(document);
......@@ -284,9 +291,9 @@ void FilterEffectRenderer::build(Document* document, const FilterOperations& ope
}
}
// If we didn't make a real filter, create a null-op (FEMerge with one input).
// If we didn't make any effects, tell our caller we are not valid
if (!previousEffect)
m_effects.append(FEMerge::create(this));
return false;
m_effects.first()->inputEffects().append(m_sourceGraphic);
setMaxEffectRects(m_sourceDrawingRegion);
......@@ -295,11 +302,12 @@ void FilterEffectRenderer::build(Document* document, const FilterOperations& ope
removeCustomFilterClients();
m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
#endif
return true;
}
bool FilterEffectRenderer::updateBackingStore(const FloatRect& filterRect)
{
if (!filterRect.isZero()) {
if (!filterRect.isZero() && isFilterSizeValid(filterRect)) {
FloatRect currentSourceRect = sourceImageRect();
if (filterRect != currentSourceRect) {
setSourceImageRect(filterRect);
......@@ -380,8 +388,8 @@ GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext*
FilterEffectRenderer* filter = m_renderLayer->filter();
// Paint into the context that represents the SourceGraphic of the filter.
GraphicsContext* sourceGraphicsContext = filter->inputContext();
if (!sourceGraphicsContext) {
// Could not allocate a new graphics context. Disable the filters and continue.
if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) {
// Disable the filters and continue.
m_haveFilterEffect = false;
return oldContext;
}
......
......@@ -106,7 +106,7 @@ public:
GraphicsContext* inputContext();
ImageBuffer* output() const { return lastEffect()->asImageBuffer(); }
void build(Document*, const FilterOperations&);
bool build(Document*, const FilterOperations&);
bool updateBackingStore(const FloatRect& filterRect);
void clearIntermediateResults();
void prepare();
......
......@@ -4851,7 +4851,10 @@ void RenderLayer::updateOrRemoveFilterEffect()
m_filter->setRenderingMode(renderingMode);
}
m_filter->build(renderer()->document(), renderer()->style()->filter());
// If the filter fails to build, remove it from the layer. It will still attempt to
// go through regular processing (e.g. compositing), but never apply anything.
if (!m_filter->build(renderer()->document(), renderer()->style()->filter()))
m_filter = 0;
} else {
m_filter = 0;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment