From /third_party/WebKit/Source/core/dom/Document.cpp: `` void Document::dispatchUnloadEvents() { PluginScriptForbiddenScope forbidPluginDestructorScripting; RefPtrWillBeRawPtrprotect(this); if (m_parser) m_parser->stopParsing();
if (m_loadEventProgress == LoadEventNotRun)
return;
if (m_loadEventProgress <= UnloadEventInProgress) {
(...)
if (m_loadEventProgress < PageHideInProgress) {
(...)
}
m_loadEventProgress = UnloadEventHandled;
}
(…) } ``
If this method is called while the document’s |m_loadEventProgress| is still at |LoadEventNotRun| then it returns without advancing |m_loadEventProgress|. It is possible to take this branch by calling document. open() (which sets |m_loadEventProgress| to LoadEventNotRun), and then navigating the document without the body element (the presence of which would allow |m_loadEventProgress| to change to BeforeUnloadEventCompleted before Document::dispatchUnloadEvents is called).
Since FrameLoader::prepareForCommit relies on Document::dispatchUnloadEvents to advance |m_loadEventProgress| to block the creation of new frames, this allows an attacker to attach subframes that will persist in the frame tree of a cross-origin document.
Chrome 47.0.2526.106 (Stable) Chrome 48.0.2564.71 (Beta) Chrome 49.0.2618.8.0 (Dev) Chromium 49.0.2621.0 (Release build compiled today)
Attachment: CVE-2016-1623.zip