Changeset 85413 in webkit
- Timestamp:
- May 1, 2011 7:38:44 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r85411 r85413 1 2011-05-01 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Dirk Schulze. 4 5 LEAK: SVGElement leaks when detaching it in a pending resource state 6 https://bugs.webkit.org/show_bug.cgi?id=59072 7 8 Add testcase that used to leak, the leaks bot will assure they won't in future. 9 10 * svg/custom/pending-resource-leak-2-expected.txt: Added. 11 * svg/custom/pending-resource-leak-2.svg: Added. 12 * svg/custom/pending-resource-leak-3-expected.txt: Added. 13 * svg/custom/pending-resource-leak-3.svg: Added. 14 * svg/custom/pending-resource-leak-expected.txt: Added. 15 * svg/custom/pending-resource-leak.svg: Added. 16 1 17 2011-05-01 Dan Bernstein <mitz@apple.com> 2 18 -
trunk/Source/WebCore/ChangeLog
r85412 r85413 1 2011-05-01 Nikolas Zimmermann <nzimmermann@rim.com> 2 3 Reviewed by Dirk Schulze. 4 5 LEAK: SVGElement leaks when detaching it in a pending resource state 6 https://bugs.webkit.org/show_bug.cgi?id=59072 7 8 Make the pending resources set non-refcounted again. We made it refcounted a while ago 9 to fix a security bug, as we had dangling pointers in the set in SVGDocumentExtensions. 10 Fix the underlying problem, by removing all pending resources referencing to a particular 11 SVGElement, upon its destruction or upon removing it from the document. 12 13 Example: <rect fill="url(#foo)" id="rect"> 14 When we try to render the rect, the foo paint server can't be found and thus "foo" will be 15 added to the pending resource set, with "rect" as client. When "foo" appears, it would remove 16 itself from the pending resource set, and a ref count to the "rect" would be released. 17 If "foo" never appears, SVGDocumentExtensions still holds a ref to the <rect>, thus keeping 18 it and the associated document alive. 19 20 Tests: svg/custom/pending-resource-leak-2.svg 21 svg/custom/pending-resource-leak-3.svg 22 svg/custom/pending-resource-leak.svg 23 24 These tests cover several scenarios where we used to leak. Should fix several SVG*Element leaks on the bots. 25 I manually tested reloading above testcases dozens of times, before the leak count was incremented by 2 nodes on every reload, that's gone now. 26 27 * rendering/svg/RenderSVGResourceContainer.cpp: 28 (WebCore::RenderSVGResourceContainer::registerResource): 29 * rendering/svg/RenderSVGShadowTreeRootContainer.cpp: 30 (WebCore::RenderSVGShadowTreeRootContainer::updateFromElement): 31 * rendering/svg/SVGResources.cpp: 32 (WebCore::registerPendingResource): 33 * svg/SVGDocumentExtensions.cpp: 34 (WebCore::SVGDocumentExtensions::addPendingResource): 35 (WebCore::SVGDocumentExtensions::hasPendingResources): 36 (WebCore::SVGDocumentExtensions::removeElementFromPendingResources): 37 (WebCore::SVGDocumentExtensions::removePendingResource): 38 * svg/SVGDocumentExtensions.h: 39 * svg/SVGElement.cpp: 40 * svg/SVGElement.h: 41 * svg/SVGElementRareData.h: 42 (WebCore::SVGElementRareData::SVGElementRareData): 43 (WebCore::SVGElementRareData::hasPendingResources): 44 (WebCore::SVGElementRareData::setHasPendingResources): 45 * svg/SVGStyledElement.cpp: 46 (WebCore::SVGStyledElement::~SVGStyledElement): 47 (WebCore::SVGStyledElement::insertedIntoDocument): 48 (WebCore::SVGStyledElement::removedFromDocument): 49 (WebCore::SVGStyledElement::hasPendingResources): 50 (WebCore::SVGStyledElement::setHasPendingResources): 51 * svg/SVGStyledElement.h: 52 (WebCore::SVGStyledElement::needsPendingResourceHandling): 53 (WebCore::SVGStyledElement::buildPendingResource): 54 * svg/SVGUseElement.cpp: 55 (WebCore::SVGUseElement::SVGUseElement): 56 (WebCore::SVGUseElement::insertedIntoDocument): 57 (WebCore::SVGUseElement::svgAttributeChanged): 58 (WebCore::SVGUseElement::buildPendingResource): 59 * svg/SVGUseElement.h: 60 1 61 2011-05-01 Rafael Brandao <rafael.lobo@openbossa.org> 2 62 -
trunk/Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
r76146 r85413 155 155 { 156 156 SVGDocumentExtensions* extensions = svgExtensionsFromNode(node()); 157 if (!extensions-> isPendingResource(m_id)) {157 if (!extensions->hasPendingResources(m_id)) { 158 158 extensions->addResource(m_id, this); 159 159 return; … … 168 168 const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end(); 169 169 for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) { 170 ASSERT((*it)->hasPendingResources()); 171 (*it)->setHasPendingResources(false); 170 172 RenderObject* renderer = (*it)->renderer(); 171 173 if (!renderer) -
trunk/Source/WebCore/rendering/svg/RenderSVGShadowTreeRootContainer.cpp
r84350 r85413 74 74 // If the use element is a pending resource, and a) or b) is true, do nothing, and wait for the use 75 75 // element to be asked to buildPendingResource(), this will call us again, with m_recreateTrue=true. 76 if ((shouldRecreateTree || !hadExistingTree) && !useElement-> isPendingResource()) {76 if ((shouldRecreateTree || !hadExistingTree) && !useElement->hasPendingResources()) { 77 77 useElement->buildShadowAndInstanceTree(m_shadowRoot.get()); 78 78 -
trunk/Source/WebCore/rendering/svg/SVGResources.cpp
r84815 r85413 172 172 { 173 173 ASSERT(element); 174 if (!element->isStyled()) 175 return; 176 174 ASSERT(element->isStyled()); 177 175 extensions->addPendingResource(id, static_cast<SVGStyledElement*>(element)); 178 176 } -
trunk/Source/WebCore/svg/SVGDocumentExtensions.cpp
r84891 r85413 212 212 } 213 213 214 void SVGDocumentExtensions::addPendingResource(const AtomicString& id, PassRefPtr<SVGStyledElement> obj)215 { 216 ASSERT( obj);214 void SVGDocumentExtensions::addPendingResource(const AtomicString& id, SVGStyledElement* element) 215 { 216 ASSERT(element); 217 217 218 218 if (id.isEmpty()) … … 220 220 221 221 if (m_pendingResources.contains(id)) 222 m_pendingResources.get(id)->add( obj);222 m_pendingResources.get(id)->add(element); 223 223 else { 224 224 SVGPendingElements* set = new SVGPendingElements; 225 set->add( obj);225 set->add(element); 226 226 227 227 m_pendingResources.add(id, set); 228 228 } 229 } 230 231 bool SVGDocumentExtensions::isPendingResource(const AtomicString& id) const 229 230 element->setHasPendingResources(true); 231 } 232 233 bool SVGDocumentExtensions::hasPendingResources(const AtomicString& id) const 232 234 { 233 235 if (id.isEmpty()) … … 237 239 } 238 240 239 PassOwnPtr<HashSet<RefPtr<SVGStyledElement> > > SVGDocumentExtensions::removePendingResource(const AtomicString& id) 241 void SVGDocumentExtensions::removeElementFromPendingResources(SVGStyledElement* element) 242 { 243 ASSERT(element); 244 245 if (m_pendingResources.isEmpty() || !element->hasPendingResources()) 246 return; 247 248 element->setHasPendingResources(false); 249 250 Vector<AtomicString> toBeRemoved; 251 HashMap<AtomicString, SVGPendingElements*>::iterator end = m_pendingResources.end(); 252 for (HashMap<AtomicString, SVGPendingElements*>::iterator it = m_pendingResources.begin(); it != end; ++it) { 253 SVGPendingElements* elements = it->second; 254 ASSERT(elements); 255 ASSERT(!elements->isEmpty()); 256 257 elements->remove(element); 258 if (elements->isEmpty()) 259 toBeRemoved.append(it->first); 260 } 261 262 if (toBeRemoved.isEmpty()) 263 return; 264 265 Vector<AtomicString>::iterator endVector = toBeRemoved.end(); 266 for (Vector<AtomicString>::iterator it = toBeRemoved.begin(); it != endVector; ++it) 267 m_pendingResources.remove(*it); 268 } 269 270 PassOwnPtr<SVGDocumentExtensions::SVGPendingElements> SVGDocumentExtensions::removePendingResource(const AtomicString& id) 240 271 { 241 272 ASSERT(m_pendingResources.contains(id)); -
trunk/Source/WebCore/svg/SVGDocumentExtensions.h
r79569 r85413 43 43 WTF_MAKE_NONCOPYABLE(SVGDocumentExtensions); WTF_MAKE_FAST_ALLOCATED; 44 44 public: 45 typedef HashSet< RefPtr<SVGStyledElement>> SVGPendingElements;45 typedef HashSet<SVGStyledElement*> SVGPendingElements; 46 46 SVGDocumentExtensions(Document*); 47 47 ~SVGDocumentExtensions(); … … 80 80 // which are referenced by any object in the SVG document, but do NOT exist yet. 81 81 // For instance, dynamically build gradients / patterns / clippers... 82 void addPendingResource(const AtomicString& id, PassRefPtr<SVGStyledElement>); 83 bool isPendingResource(const AtomicString& id) const; 82 void addPendingResource(const AtomicString& id, SVGStyledElement*); 83 bool hasPendingResources(const AtomicString& id) const; 84 void removeElementFromPendingResources(SVGStyledElement*); 84 85 PassOwnPtr<SVGPendingElements> removePendingResource(const AtomicString& id); 85 86 }; -
trunk/Source/WebCore/svg/SVGElement.cpp
r81932 r85413 339 339 } 340 340 341 void SVGElement::insertedIntoDocument()342 {343 StyledElement::insertedIntoDocument();344 345 if (!needsPendingResourceHandling())346 return;347 348 SVGDocumentExtensions* extensions = document()->accessSVGExtensions();349 String resourceId = getIdAttribute();350 if (!extensions->isPendingResource(resourceId))351 return;352 353 OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(resourceId));354 if (clients->isEmpty())355 return;356 357 const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();358 for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it)359 (*it)->buildPendingResource();360 }361 362 341 void SVGElement::attributeChanged(Attribute* attr, bool preserveDecls) 363 342 { -
trunk/Source/WebCore/svg/SVGElement.h
r79569 r85413 116 116 117 117 virtual void finishParsingChildren(); 118 virtual void insertedIntoDocument();119 118 virtual void attributeChanged(Attribute*, bool preserveDecls = false); 120 119 virtual bool childShouldCreateRenderer(Node*) const; … … 132 131 virtual bool isSupported(StringImpl* feature, StringImpl* version) const; 133 132 134 virtual bool needsPendingResourceHandling() const { return true; }135 virtual void buildPendingResource() { }136 137 133 void mapInstanceToElement(SVGElementInstance*); 138 134 void removeInstanceMapping(SVGElementInstance*); -
trunk/Source/WebCore/svg/SVGElementRareData.h
r76248 r85413 39 39 , m_cursorImageValue(0) 40 40 , m_instancesUpdatesBlocked(false) 41 , m_hasPendingResources(false) 41 42 { 42 43 } … … 61 62 void setInstanceUpdatesBlocked(bool value) { m_instancesUpdatesBlocked = value; } 62 63 64 bool hasPendingResources() const { return m_hasPendingResources; } 65 void setHasPendingResources(bool value) { m_hasPendingResources = value; } 66 63 67 SVGCursorElement* cursorElement() const { return m_cursorElement; } 64 68 void setCursorElement(SVGCursorElement* cursorElement) { m_cursorElement = cursorElement; } … … 72 76 CSSCursorImageValue* m_cursorImageValue; 73 77 bool m_instancesUpdatesBlocked : 1; 78 bool m_hasPendingResources : 1; 74 79 }; 75 80 -
trunk/Source/WebCore/svg/SVGStyledElement.cpp
r84225 r85413 67 67 SVGStyledElement::~SVGStyledElement() 68 68 { 69 if (needsPendingResourceHandling() && hasPendingResources() && document()) 70 document()->accessSVGExtensions()->removeElementFromPendingResources(this); 71 72 ASSERT(!hasPendingResources()); 69 73 } 70 74 … … 360 364 SVGElement::insertedIntoDocument(); 361 365 updateRelativeLengthsInformation(); 366 367 Document* document = this->document(); 368 if (!needsPendingResourceHandling() || !document) 369 return; 370 371 SVGDocumentExtensions* extensions = document->accessSVGExtensions(); 372 String resourceId = getIdAttribute(); 373 if (!extensions->hasPendingResources(resourceId)) 374 return; 375 376 OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(resourceId)); 377 ASSERT(!clients->isEmpty()); 378 379 const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end(); 380 for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) { 381 ASSERT((*it)->hasPendingResources()); 382 (*it)->buildPendingResource(); 383 (*it)->setHasPendingResources(false); 384 } 362 385 } 363 386 … … 366 389 updateRelativeLengthsInformation(false, this); 367 390 SVGElement::removedFromDocument(); 391 392 Document* document = this->document(); 393 if (!needsPendingResourceHandling() || !document) 394 return; 395 396 document->accessSVGExtensions()->removeElementFromPendingResources(this); 368 397 } 369 398 … … 420 449 } 421 450 451 bool SVGStyledElement::hasPendingResources() const 452 { 453 return hasRareSVGData() && rareSVGData()->hasPendingResources(); 454 } 455 456 void SVGStyledElement::setHasPendingResources(bool value) 457 { 458 ensureRareSVGData()->setHasPendingResources(value); 459 } 460 422 461 AffineTransform SVGStyledElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const 423 462 { -
trunk/Source/WebCore/svg/SVGStyledElement.h
r78543 r85413 53 53 void setInstanceUpdatesBlocked(bool); 54 54 55 bool hasPendingResources() const; 56 void setHasPendingResources(bool); 57 55 58 AnimatedAttributeType animatedPropertyTypeForCSSProperty(const QualifiedName&); 56 59 static bool isAnimatableCSSProperty(const QualifiedName&); … … 59 62 60 63 virtual CSSStyleDeclaration* style() { return StyledElement::style(); } 64 virtual bool needsPendingResourceHandling() const { return true; } 61 65 62 66 protected: … … 82 86 83 87 virtual bool selfHasRelativeLengths() const { return false; } 88 virtual void buildPendingResource() { } 84 89 85 90 private: -
trunk/Source/WebCore/svg/SVGUseElement.cpp
r84899 r85413 73 73 , m_height(LengthModeHeight) 74 74 , m_updatesBlocked(false) 75 , m_isPendingResource(false)76 75 , m_needsShadowTreeRecreation(false) 77 76 { … … 140 139 SVGStyledTransformableElement::insertedIntoDocument(); 141 140 ASSERT(!m_targetElementInstance || !isWellFormedDocument(document())); 142 ASSERT(! m_isPendingResource|| !isWellFormedDocument(document()));141 ASSERT(!hasPendingResources() || !isWellFormedDocument(document())); 143 142 } 144 143 … … 167 166 168 167 if (SVGURIReference::isKnownAttribute(attrName)) { 169 if (m_isPendingResource) { 170 document()->accessSVGExtensions()->removePendingResource(m_resourceId); 168 if (hasPendingResources()) { 169 OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(document()->accessSVGExtensions()->removePendingResource(m_resourceId)); 170 ASSERT(!clients->isEmpty()); 171 172 const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end(); 173 for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) { 174 ASSERT((*it)->hasPendingResources()); 175 (*it)->setHasPendingResources(false); 176 } 177 171 178 m_resourceId = String(); 172 m_isPendingResource = false;179 setHasPendingResources(false); 173 180 } 174 181 … … 471 478 472 479 if (!targetElement) { 473 if ( m_isPendingResource|| id.isEmpty())480 if (hasPendingResources() || id.isEmpty()) 474 481 return; 475 482 476 m_isPendingResource = true;477 483 m_resourceId = id; 484 ASSERT(!hasPendingResources()); 478 485 document()->accessSVGExtensions()->addPendingResource(id, this); 479 return; 480 } 481 482 if (m_isPendingResource) { 486 ASSERT(hasPendingResources()); 487 return; 488 } 489 490 491 if (hasPendingResources()) { 483 492 ASSERT(!m_targetElementInstance); 484 m_isPendingResource = false;485 493 m_resourceId = String(); 486 494 invalidateShadowTree(); -
trunk/Source/WebCore/svg/SVGUseElement.h
r81950 r85413 78 78 79 79 friend class RenderSVGShadowTreeRootContainer; 80 bool isPendingResource() const { return m_isPendingResource; }81 80 void buildShadowAndInstanceTree(SVGShadowTreeRootElement*); 82 81 void detachInstance(); … … 119 118 120 119 bool m_updatesBlocked; 121 bool m_isPendingResource;122 120 bool m_needsShadowTreeRecreation; 123 121 String m_resourceId;
Note: See TracChangeset
for help on using the changeset viewer.