https://bugs.webkit.org/show_bug.cgi?id=214715
<rdar://problem/
65467702>
Reviewed by Geoffrey Garen.
Source/WebCore:
Test: security/mutation-observer-frame-detach.html
* dom/Document.cpp:
(WebCore::Document::didBecomeCurrentDocumentInFrame):
(WebCore::Document::initContentSecurityPolicy):
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::commitData):
Add some null checks and early returns if the frame detaches.
* loader/SubframeLoader.cpp:
(WebCore::FrameLoader::SubframeLoader::loadSubframe):
Balance the call to incrementLoadEventDelayCount in the early return case or this test never finishes loading.
LayoutTests:
* security/mutation-observer-frame-detach-expected.txt: Added.
* security/mutation-observer-frame-detach.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@264880
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2020-07-24 Alex Christensen <achristensen@webkit.org>
+
+ Null check frame in Document::dispatchDisabledAdaptationsDidChangeForMainFrame and a few other places
+ https://bugs.webkit.org/show_bug.cgi?id=214715
+ <rdar://problem/65467702>
+
+ Reviewed by Geoffrey Garen.
+
+ * security/mutation-observer-frame-detach-expected.txt: Added.
+ * security/mutation-observer-frame-detach.html: Added.
+
2020-07-24 Alex Christensen <achristensen@webkit.org>
Fix assertion when highlighting in detached frames and make loads complete
--- /dev/null
+ALERT: test passed because nothing crashed
+
--- /dev/null
+<script>
+ function runTest() {
+ var observer = new MutationObserver(()=>{p1.replaceWith(p2)});
+ observer.observe(select,{childList:true});
+ select[2] = option;
+ document.head.appendChild(p2);
+ var object = document.createElement("object");
+ var frame = document.createElement("frame");
+ audio.appendChild(option);
+ p1.appendChild(object);
+ object.data = "abc";
+ document.all[9].appendChild(frame);
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ alert("test passed because nothing crashed");
+ }
+ }
+</script>
+<body onload=runTest()>
+ <p id="p1">
+ <p id="p2">
+ <audio id="audio">
+ <select id="select">
+ <option id="option"></option>
+ </select>
+ </audio>
+ </p>
+ </p>
+</body>
+2020-07-24 Alex Christensen <achristensen@webkit.org>
+
+ Null check frame in Document::dispatchDisabledAdaptationsDidChangeForMainFrame and a few other places
+ https://bugs.webkit.org/show_bug.cgi?id=214715
+ <rdar://problem/65467702>
+
+ Reviewed by Geoffrey Garen.
+
+ Test: security/mutation-observer-frame-detach.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::didBecomeCurrentDocumentInFrame):
+ (WebCore::Document::initContentSecurityPolicy):
+ * loader/DocumentLoader.cpp:
+ (WebCore::DocumentLoader::commitData):
+ Add some null checks and early returns if the frame detaches.
+ * loader/SubframeLoader.cpp:
+ (WebCore::FrameLoader::SubframeLoader::loadSubframe):
+ Balance the call to incrementLoadEventDelayCount in the early return case or this test never finishes loading.
+
2020-07-24 Alex Christensen <achristensen@webkit.org>
Fix assertion when highlighting in detached frames and make loads complete
void Document::didBecomeCurrentDocumentInFrame()
{
- // FIXME: Are there cases where the document can be dislodged from the frame during the event handling below?
- // If so, then m_frame could become 0, and we need to do something about that.
-
m_frame->script().updateDocument();
+ // Many of these functions have event handlers which can detach the frame synchronously, so we must check repeatedly in this function.
+ if (!m_frame)
+ return;
+
if (!hasLivingRenderTree())
createRenderTree();
+ if (!m_frame)
+ return;
dispatchDisabledAdaptationsDidChangeForMainFrame();
+ if (!m_frame)
+ return;
+
updateViewportArguments();
+ if (!m_frame)
+ return;
// FIXME: Doing this only for the main frame is insufficient.
// Changing a subframe can also change the wheel event handler count.
// unless the documents they are replacing had wheel event handlers.
if (page() && m_frame->isMainFrame())
wheelEventHandlersChanged();
+ if (!m_frame)
+ return;
// Ensure that the scheduled task state of the document matches the DOM suspension state of the frame. It can
// be out of sync if the DOM suspension state changed while the document was not in the frame (possibly in the
void Document::initContentSecurityPolicy()
{
+ if (!m_frame)
+ return;
auto* parentFrame = m_frame->tree().parent();
if (parentFrame)
contentSecurityPolicy()->copyUpgradeInsecureRequestStateFrom(*parentFrame->document()->contentSecurityPolicy());
bool hasBegun = m_writer.begin(documentURL(), false);
m_writer.setDocumentWasLoadedAsPartOfNavigation();
- auto& document = *m_frame->document();
+ auto* documentOrNull = m_frame ? m_frame->document() : nullptr;
+ if (!documentOrNull)
+ return;
+ auto& document = *documentOrNull;
if (SecurityPolicy::allowSubstituteDataAccessToLocal() && m_originalSubstituteDataWasValid) {
// If this document was loaded with substituteData, then the document can