Summary: | [CSS Gradients] Crash due to out-of-memory with repeating-linear-gradient and latter stop positioned before former | ||||||||
---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | Rafał Chłodnicki <rchl2k> | ||||||
Component: | CSS | Assignee: | Simon Fraser (smfr) <simon.fraser> | ||||||
Status: | RESOLVED FIXED | ||||||||
Severity: | Critical | CC: | abarth, aroben, eric, simon.fraser, webkit.review.bot | ||||||
Priority: | P2 | Keywords: | InRadar | ||||||
Version: | 528+ (Nightly build) | ||||||||
Hardware: | All | ||||||||
OS: | All | ||||||||
Attachments: |
|
Description
Rafał Chłodnicki
2011-01-19 12:24:43 PST
Created attachment 79466 [details]
Testcase
Testcase works fine on Mac. I've actually tested Chrome (10.0.634.0). Maybe it doesn't have latest fixes yet... This crashes on Windows due to a failed allocation. Here's the backtrace:
JavaScriptCore.dll!WTF::fastMalloc(unsigned int n=379677936) Line 260 C++
WebKit.dll!WTF::VectorBufferBase<WebCore::GradientStop>::allocateBuffer(unsigned int newCapacity=23729871) Line 287 + 0xc bytes C++
WebKit.dll!WTF::Vector<WebCore::GradientStop,0>::reserveCapacity(unsigned int newCapacity=23729871) Line 872 C++
WebKit.dll!WTF::Vector<WebCore::GradientStop,0>::expandCapacity(unsigned int newMinCapacity=18983897) Line 789 C++
WebKit.dll!WTF::Vector<WebCore::GradientStop,0>::expandCapacity(unsigned int newMinCapacity=18983897, const WebCore::GradientStop * ptr=0x0012e8c8) Line 796 C++
WebKit.dll!WTF::Vector<WebCore::GradientStop,0>::append<WebCore::GradientStop>(const WebCore::GradientStop & val={...}) Line 967 + 0x18 bytes C++
> WebKit.dll!WebCore::CSSGradientValue::addStops(WebCore::Gradient * gradient=0x06eb8b38, WebCore::RenderObject * renderer=0x05c0e7bc, WebCore::RenderStyle * rootStyle=0x06917ae0, float maxLengthForRepeat=1.0000000) Line 280 C++
WebKit.dll!WebCore::CSSLinearGradientValue::createGradient(WebCore::RenderObject * renderer=0x05c0e7bc, const WebCore::IntSize & size={...}) Line 532 C++
WebKit.dll!WebCore::CSSGradientValue::image(WebCore::RenderObject * renderer=0x05c0e7bc, const WebCore::IntSize & size={...}) Line 60 + 0x1f bytes C++
WebKit.dll!WebCore::StyleGeneratedImage::image(WebCore::RenderObject * renderer=0x05c0e7bc, const WebCore::IntSize & size={...}) Line 77 + 0x1d bytes C++
WebKit.dll!WebCore::RenderBoxModelObject::paintFillLayerExtended(const WebCore::PaintInfo & paintInfo={...}, const WebCore::Color & c={...}, const WebCore::FillLayer * bgLayer=0x06e37a80, int tx=8, int ty=8, int w=100, int h=100, WebCore::InlineFlowBox * box=0x00000000, WebCore::CompositeOperator op=CompositeSourceOver, WebCore::RenderObject * backgroundObject=0x00000000) Line 695 + 0x23 bytes C++
WebKit.dll!WebCore::RenderBox::paintFillLayer(const WebCore::PaintInfo & paintInfo={...}, const WebCore::Color & c={...}, const WebCore::FillLayer * fillLayer=0x06e37a80, int tx=8, int ty=8, int width=100, int height=100, WebCore::CompositeOperator op=CompositeSourceOver, WebCore::RenderObject * backgroundObject=0x00000000) Line 943 C++
WebKit.dll!WebCore::RenderBox::paintFillLayers(const WebCore::PaintInfo & paintInfo={...}, const WebCore::Color & c={...}, const WebCore::FillLayer * fillLayer=0x06e37a80, int tx=8, int ty=8, int width=100, int height=100, WebCore::CompositeOperator op=CompositeSourceOver, WebCore::RenderObject * backgroundObject=0x00000000) Line 938 C++
WebKit.dll!WebCore::RenderBox::paintBoxDecorationsWithSize(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8, int width=100, int height=100) Line 821 C++
WebKit.dll!WebCore::RenderBox::paintBoxDecorations(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 800 C++
WebKit.dll!WebCore::RenderBlock::paintObject(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2396 + 0x1e bytes C++
WebKit.dll!WebCore::RenderBlock::paint(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2205 + 0x1e bytes C++
WebKit.dll!WebCore::RenderBlock::paintChildren(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2357 + 0x28 bytes C++
WebKit.dll!WebCore::RenderBlock::paintContents(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2317 C++
WebKit.dll!WebCore::RenderBlock::paintObject(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2429 C++
WebKit.dll!WebCore::RenderBlock::paint(WebCore::PaintInfo & paintInfo={...}, int tx=8, int ty=8) Line 2205 + 0x1e bytes C++
WebKit.dll!WebCore::RenderBlock::paintChildren(WebCore::PaintInfo & paintInfo={...}, int tx=0, int ty=0) Line 2357 + 0x28 bytes C++
WebKit.dll!WebCore::RenderBlock::paintContents(WebCore::PaintInfo & paintInfo={...}, int tx=0, int ty=0) Line 2317 C++
WebKit.dll!WebCore::RenderBlock::paintObject(WebCore::PaintInfo & paintInfo={...}, int tx=0, int ty=0) Line 2429 C++
WebKit.dll!WebCore::RenderBlock::paint(WebCore::PaintInfo & paintInfo={...}, int tx=0, int ty=0) Line 2205 + 0x1e bytes C++
WebKit.dll!WebCore::RenderLayer::paintLayer(WebCore::RenderLayer * rootLayer=0x05c3cc14, WebCore::GraphicsContext * p=0x0012fb38, const WebCore::IntRect & paintDirtyRect={...}, unsigned int paintBehavior=0, WebCore::RenderObject * paintingRoot=0x00000000, WTF::HashMap<WebCore::OverlapTestRequestClient *,WebCore::IntRect,WTF::PtrHash<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::IntRect> > * overlapTestRequests=0x0012f968, unsigned int paintFlags=0) Line 2506 + 0x3b bytes C++
WebKit.dll!WebCore::RenderLayer::paintList(WTF::Vector<WebCore::RenderLayer *,0> * list=[1](0x023f8dd4 {m_renderer=0x067cc784 m_parent=0x05c3cc14 m_previous=0x00000000 ...}), WebCore::RenderLayer * rootLayer=0x05c3cc14, WebCore::GraphicsContext * p=0x0012fb38, const WebCore::IntRect & paintDirtyRect={...}, unsigned int paintBehavior=0, WebCore::RenderObject * paintingRoot=0x00000000, WTF::HashMap<WebCore::OverlapTestRequestClient *,WebCore::IntRect,WTF::PtrHash<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::IntRect> > * overlapTestRequests=0x0012f968, unsigned int paintFlags=0) Line 2566 C++
WebKit.dll!WebCore::RenderLayer::paintLayer(WebCore::RenderLayer * rootLayer=0x05c3cc14, WebCore::GraphicsContext * p=0x0012fb38, const WebCore::IntRect & paintDirtyRect={...}, unsigned int paintBehavior=0, WebCore::RenderObject * paintingRoot=0x00000000, WTF::HashMap<WebCore::OverlapTestRequestClient *,WebCore::IntRect,WTF::PtrHash<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::OverlapTestRequestClient *>,WTF::HashTraits<WebCore::IntRect> > * overlapTestRequests=0x0012f968, unsigned int paintFlags=0) Line 2535 C++
WebKit.dll!WebCore::RenderLayer::paint(WebCore::GraphicsContext * p=0x0012fb38, const WebCore::IntRect & damageRect={...}, unsigned int paintBehavior=0, WebCore::RenderObject * paintingRoot=0x00000000) Line 2318 C++
WebKit.dll!WebCore::FrameView::paintContents(WebCore::GraphicsContext * p=0x0012fb38, const WebCore::IntRect & rect={...}) Line 2186 C++
WebKit.dll!WebCore::ScrollView::paint(WebCore::GraphicsContext * context=0x0012fb38, const WebCore::IntRect & rect={...}) Line 895 + 0x1a bytes C++
At the point when we crashed, the stops Vector in CSSGradientValue::addStops had 19 million items.
When we enter this bit of code: // Work forwards from the end, adding stops until we get one after 1. float lastOffset = stops[stops.size() - 1].offset; if (lastOffset < maxExtent) { float currOffset = lastOffset; size_t srcStopOrdinal = 0; while (true) { GradientStop newStop = stops[srcStopOrdinal]; newStop.offset = currOffset; stops.append(newStop); if (currOffset > maxExtent) break; if (srcStopOrdinal < originalNumStops - 1) currOffset += stops[originalFirstStopIndex + srcStopOrdinal + 1].offset - stops[originalFirstStopIndex + srcStopOrdinal].offset; srcStopOrdinal = (srcStopOrdinal + 1) % originalNumStops; } } stops has two items, both of which have offset 0. maxExtent is 1. So we basically keep doing 0 += 0, and then if (0 > 1) break; Created attachment 79472 [details]
Patch
Comment on attachment 79472 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=79472&action=review > Source/WebCore/css/CSSGradientValue.cpp:240 > + float gradientRange = stops[numStops - 1].offset - stops[0].offset; > + if (!gradientRange) { > + stops[0].offset = 0; > + stops[0].color = stops[numStops - 1].color; > + stops.shrink(1); > + numStops = 1; I think using .first() and .last() would be clearer than [0] and [numStops - 1]. http://trac.webkit.org/changeset/76154 might have broken GTK Linux 32-bit Release The following tests are not passing: fast/forms/input-text-scroll-left-on-blur.html fast/forms/plaintext-mode-2.html |