Changeset 225878 in webkit
- Timestamp:
- Dec 13, 2017 4:05:42 PM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r225872 r225878 1 2017-12-13 Ryosuke Niwa <rniwa@webkit.org> 2 3 Crash inside ImageLoader::updateFromElement() 4 https://bugs.webkit.org/show_bug.cgi?id=180769 5 <rdar://problem/35278782> 6 7 Reviewed by Antti Koivisto. 8 9 Fixed the crash by moving all call sites of ImageLoader::updateFromElement() to be post insertion callbacks 10 where it's safe to execute arbitrary scripts. 11 12 No new test since existing tests cover this with a newly added release assert in ImageLoader. 13 14 * html/HTMLImageElement.cpp: 15 (WebCore::HTMLImageElement::insertedIntoAncestor): 16 (WebCore::HTMLImageElement::didFinishInsertingNode): Extracted from insertedIntoAncestor to call 17 selectImageSource or updateFromElement. 18 * html/HTMLImageElement.h: Made many member functions final. 19 * html/HTMLInputElement.cpp: 20 (WebCore::HTMLInputElement::didAttachRenderers): Delay the call to ImageLoader::updateFromElement() in 21 ImageInputType using a post style resolution callback. 22 * html/HTMLMetaElement.h: 23 * html/HTMLPictureElement.cpp: 24 (WebCore::HTMLPictureElement::sourcesChanged): Store the list of child image elements into a vector before 25 calling selectImageSource since each call may execute arbitrary scripts. 26 * html/HTMLSourceElement.cpp: 27 (WebCore::HTMLSourceElement::insertedIntoAncestor): Delay the call to ImageLoader::updateFromElement() 28 using a post style resolution callback. 29 (WebCore::HTMLSourceElement::didFinishInsertingNode): Extracted from insertedIntoAncestor. 30 * html/HTMLSourceElement.h: 31 * html/HTMLVideoElement.cpp: 32 (WebCore::HTMLVideoElement::didAttachRenderers): 33 (WebCore::HTMLVideoElement::updateAfterStyleResolution): Extracted from didAttachRenderers. 34 * html/HTMLVideoElement.h: 35 * html/ImageInputType.cpp: 36 (WebCore::ImageInputType::needsPostStyleResolutionCallback): Added. Returns true so that HTMLInputElement's 37 didAttachRenderers would register a post style resolution callback. 38 (WebCore::ImageInputType::updateAfterStyleResolution): Extracted from attach. 39 (WebCore::ImageInputType::attach): Deleted. 40 * html/ImageInputType.h: 41 * html/InputType.cpp: 42 (WebCore::InputType::needsPostStyleResolutionCallback): Added. All but ImageInputType returns false. 43 (WebCore::InputType::updateAfterStyleResolution): Added. 44 (WebCore::InputType::attach): Deleted. 45 * html/InputType.h: 46 * loader/ImageLoader.cpp: 47 (WebCore::ImageLoader::updateFromElement): Added a release assertion. There is no direct security implication 48 so there is no need to use RELEASE_ASSERT_WITH_SECURITY_IMPLICATION here. 49 * svg/SVGImageElement.cpp: 50 (WebCore::SVGImageElement::insertedIntoAncestor): 51 (WebCore::SVGImageElement::didFinishInsertingNode): 52 * svg/SVGImageElement.h: 53 1 54 2017-12-13 Zalan Bujtas <zalan@apple.com> 2 55 -
trunk/Source/WebCore/html/HTMLImageElement.cpp
r225616 r225878 296 296 Node::InsertedIntoAncestorResult HTMLImageElement::insertedIntoAncestor(InsertionType insertionType, ContainerNode& parentOfInsertedTree) 297 297 { 298 HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree); 299 298 300 if (m_formSetByParser) { 299 301 m_form = m_formSetByParser; … … 312 314 m_form->registerImgElement(this); 313 315 } 314 // Insert needs to complete first, before we start updating the loader. Loader dispatches events which could result315 // in callbacks back to this node.316 Node::InsertedIntoAncestorResult insertNotificationRequest = HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree);317 316 318 317 if (insertionType.connectedToDocument && !m_parsedUsemap.isNull()) … … 321 320 if (is<HTMLPictureElement>(parentNode())) { 322 321 setPictureElement(&downcast<HTMLPictureElement>(*parentNode())); 323 selectImageSource();322 return InsertedIntoAncestorResult::NeedsPostInsertionCallback; 324 323 } 325 324 … … 327 326 // our loader may have not fetched the image, so do it now. 328 327 if (insertionType.connectedToDocument && !m_imageLoader.image()) 328 return InsertedIntoAncestorResult::NeedsPostInsertionCallback; 329 330 return InsertedIntoAncestorResult::Done; 331 } 332 333 void HTMLImageElement::didFinishInsertingNode() 334 { 335 if (pictureElement()) 336 selectImageSource(); 337 else if (isConnected()) 329 338 m_imageLoader.updateFromElement(); 330 331 return insertNotificationRequest;332 339 } 333 340 -
trunk/Source/WebCore/html/HTMLImageElement.h
r225616 r225878 91 91 bool hasPendingActivity() const { return m_imageLoader.hasPendingActivity(); } 92 92 93 bool canContainRangeEndPoint() const override{ return false; }93 bool canContainRangeEndPoint() const final { return false; } 94 94 95 const AtomicString& imageSourceURL() const override;95 const AtomicString& imageSourceURL() const final; 96 96 97 97 bool hasShadowControls() const { return m_experimentalImageMenuEnabled; } … … 106 106 107 107 private: 108 void parseAttribute(const QualifiedName&, const AtomicString&) override;109 bool isPresentationAttribute(const QualifiedName&) const override;110 void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) override;108 void parseAttribute(const QualifiedName&, const AtomicString&) final; 109 bool isPresentationAttribute(const QualifiedName&) const final; 110 void collectStyleForPresentationAttribute(const QualifiedName&, const AtomicString&, MutableStyleProperties&) final; 111 111 112 void didAttachRenderers() override;113 RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;112 void didAttachRenderers() final; 113 RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final; 114 114 void setBestFitURLAndDPRFromImageCandidate(const ImageCandidate&); 115 115 116 bool canStartSelection() const override;116 bool canStartSelection() const final; 117 117 118 bool isURLAttribute(const Attribute&) const override;119 bool attributeContainsURL(const Attribute&) const override;120 String completeURLsInAttributeValue(const URL& base, const Attribute&) const override;118 bool isURLAttribute(const Attribute&) const final; 119 bool attributeContainsURL(const Attribute&) const final; 120 String completeURLsInAttributeValue(const URL& base, const Attribute&) const final; 121 121 122 bool draggable() const override;122 bool draggable() const final; 123 123 124 void addSubresourceAttributeURLs(ListHashSet<URL>&) const override;124 void addSubresourceAttributeURLs(ListHashSet<URL>&) const final; 125 125 126 InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) override; 127 void removedFromAncestor(RemovalType, ContainerNode&) override; 126 InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final; 127 void didFinishInsertingNode() final; 128 void removedFromAncestor(RemovalType, ContainerNode&) final; 128 129 129 130 bool isFormAssociatedElement() const final { return false; } … … 153 154 void destroyImageControls(); 154 155 bool hasImageControls() const; 155 bool childShouldCreateRenderer(const Node&) const override;156 bool childShouldCreateRenderer(const Node&) const final; 156 157 #endif 157 158 -
trunk/Source/WebCore/html/HTMLInputElement.cpp
r225680 r225878 59 59 #include "Settings.h" 60 60 #include "StyleResolver.h" 61 #include "StyleTreeResolver.h" 61 62 #include "TextControlInnerElements.h" 62 63 #include <wtf/Language.h> … … 846 847 HTMLTextFormControlElement::didAttachRenderers(); 847 848 848 m_inputType->attach(); 849 if (m_inputType->needsPostStyleResolutionCallback()) { 850 Style::queuePostResolutionCallback([protectedElement = makeRef(*this)] { 851 protectedElement->m_inputType->updateAfterStyleResolution(); 852 }); 853 } 849 854 850 855 if (document().focusedElement() == this) { -
trunk/Source/WebCore/html/HTMLMetaElement.h
r225723 r225878 41 41 void parseAttribute(const QualifiedName&, const AtomicString&) final; 42 42 InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final; 43 void didFinishInsertingNode() ;43 void didFinishInsertingNode() final; 44 44 45 45 void process(); -
trunk/Source/WebCore/html/HTMLPictureElement.cpp
r224390 r225878 57 57 void HTMLPictureElement::sourcesChanged() 58 58 { 59 Vector<Ref<HTMLImageElement>, 4> imageElements; 59 60 for (auto& element : childrenOfType<HTMLImageElement>(*this)) 60 element.selectImageSource(); 61 imageElements.append(element); 62 for (auto& element : imageElements) 63 element->selectImageSource(); 61 64 } 62 65 -
trunk/Source/WebCore/html/HTMLSourceElement.cpp
r224390 r225878 75 75 #endif 76 76 if (is<HTMLPictureElement>(*parent)) 77 downcast<HTMLPictureElement>(*parent).sourcesChanged(); 77 return InsertedIntoAncestorResult::NeedsPostInsertionCallback; 78 78 79 } 79 80 return InsertedIntoAncestorResult::Done; 81 } 82 83 void HTMLSourceElement::didFinishInsertingNode() 84 { 85 auto* parent = parentElement(); 86 if (is<HTMLPictureElement>(*parent)) 87 downcast<HTMLPictureElement>(*parent).sourcesChanged(); 80 88 } 81 89 -
trunk/Source/WebCore/html/HTMLSourceElement.h
r223802 r225878 47 47 48 48 InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final; 49 void didFinishInsertingNode() final; 49 50 void removedFromAncestor(RemovalType, ContainerNode&) final; 50 51 bool isURLAttribute(const Attribute&) const final; -
trunk/Source/WebCore/html/HTMLVideoElement.cpp
r223960 r225878 44 44 #include "ScriptController.h" 45 45 #include "Settings.h" 46 #include "StyleTreeResolver.h" 46 47 #include <wtf/text/TextStream.h> 47 48 … … 91 92 updateDisplayState(); 92 93 if (shouldDisplayPosterImage()) { 93 if (!m_imageLoader) 94 m_imageLoader = std::make_unique<HTMLImageLoader>(*this); 95 m_imageLoader->updateFromElement(); 96 if (auto* renderer = this->renderer()) 97 renderer->imageResource().setCachedImage(m_imageLoader->image()); 98 } 94 Style::queuePostResolutionCallback([protectedThis = makeRef(*this)] { 95 protectedThis->updateAfterStyleResolution(); 96 }); 97 } 98 } 99 100 void HTMLVideoElement::updateAfterStyleResolution() 101 { 102 if (!m_imageLoader) 103 m_imageLoader = std::make_unique<HTMLImageLoader>(*this); 104 m_imageLoader->updateFromElement(); 105 if (auto* renderer = this->renderer()) 106 renderer->imageResource().setCachedImage(m_imageLoader->image()); 99 107 } 100 108 -
trunk/Source/WebCore/html/HTMLVideoElement.h
r217876 r225878 97 97 bool rendererIsNeeded(const RenderStyle&) final; 98 98 void didAttachRenderers() final; 99 void updateAfterStyleResolution(); 99 100 void parseAttribute(const QualifiedName&, const AtomicString&) final; 100 101 bool isPresentationAttribute(const QualifiedName&) const final; -
trunk/Source/WebCore/html/ImageInputType.cpp
r221914 r225878 127 127 } 128 128 129 void ImageInputType::attach() 130 { 131 BaseButtonInputType::attach(); 132 129 bool ImageInputType::needsPostStyleResolutionCallback() 130 { 131 return true; 132 } 133 134 void ImageInputType::updateAfterStyleResolution() 135 { 133 136 HTMLImageLoader& imageLoader = element().ensureImageLoader(); 134 137 imageLoader.updateFromElement(); -
trunk/Source/WebCore/html/ImageInputType.h
r221914 r225878 51 51 void altAttributeChanged() override; 52 52 void srcAttributeChanged() override; 53 void attach() override; 53 bool needsPostStyleResolutionCallback() override; 54 void updateAfterStyleResolution() override; 54 55 bool shouldRespectAlignAttribute() override; 55 56 bool canBeSuccessfulSubmitButton() override; -
trunk/Source/WebCore/html/InputType.cpp
r225680 r225878 588 588 } 589 589 590 void InputType::attach() 590 bool InputType::needsPostStyleResolutionCallback() 591 { 592 return false; 593 } 594 595 void InputType::updateAfterStyleResolution() 591 596 { 592 597 } -
trunk/Source/WebCore/html/InputType.h
r225680 r225878 236 236 virtual RenderPtr<RenderElement> createInputRenderer(RenderStyle&&); 237 237 virtual void addSearchResult(); 238 virtual void attach(); 238 virtual bool needsPostStyleResolutionCallback(); 239 virtual void updateAfterStyleResolution(); 239 240 virtual void detach(); 240 241 virtual void minOrMaxAttributeChanged(); -
trunk/Source/WebCore/loader/ImageLoader.cpp
r225499 r225878 37 37 #include "HTMLObjectElement.h" 38 38 #include "HTMLParserIdioms.h" 39 #include "NoEventDispatchAssertion.h" 39 40 #include "Page.h" 40 41 #include "RenderImage.h" … … 158 159 void ImageLoader::updateFromElement() 159 160 { 161 RELEASE_ASSERT(NoEventDispatchAssertion::InMainThread::isEventAllowed()); 160 162 // If we're not making renderers for the page, then don't load images. We don't want to slow 161 163 // down the raw HTML parsing case by loading images we don't intend to display. -
trunk/Source/WebCore/svg/SVGImageElement.cpp
r224213 r225878 190 190 { 191 191 SVGGraphicsElement::insertedIntoAncestor(insertionType, parentOfInsertedTree); 192 if (!insertionType.connectedToDocument) 193 return InsertedIntoAncestorResult::Done; 194 // Update image loader, as soon as we're living in the tree. 195 // We can only resolve base URIs properly, after that! 192 if (insertionType.connectedToDocument) 193 return InsertedIntoAncestorResult::NeedsPostInsertionCallback; 194 return InsertedIntoAncestorResult::Done; 195 } 196 197 void SVGImageElement::didFinishInsertingNode() 198 { 196 199 m_imageLoader.updateFromElement(); 197 return InsertedIntoAncestorResult::Done;198 200 } 199 201 -
trunk/Source/WebCore/svg/SVGImageElement.h
r223802 r225878 51 51 void didAttachRenderers() final; 52 52 InsertedIntoAncestorResult insertedIntoAncestor(InsertionType, ContainerNode&) final; 53 void didFinishInsertingNode() final; 53 54 54 55 RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) final;
Note: See TracChangeset
for help on using the changeset viewer.