Changeset 97353 in webkit
- Timestamp:
- Oct 13, 2011 1:53:50 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r97352 r97353 1 2011-10-13 Adam Barth <abarth@webkit.org> 2 3 DOMWindow subobjects can be re-created after navigation 4 https://bugs.webkit.org/show_bug.cgi?id=68849 5 6 Reviewed by Sam Weinig. 7 8 * http/tests/security/xss-DENIED-getSelection-from-inactive-domwindow-expected.txt: Added. 9 * http/tests/security/xss-DENIED-getSelection-from-inactive-domwindow.html: Added. 10 1 11 2011-10-13 Kent Tamura <tkent@chromium.org> 2 12 -
trunk/Source/WebCore/ChangeLog
r97351 r97353 1 2011-10-13 Adam Barth <abarth@webkit.org> 2 3 DOMWindow subobjects can be re-created after navigation 4 https://bugs.webkit.org/show_bug.cgi?id=68849 5 6 Reviewed by Sam Weinig. 7 8 Test: http/tests/security/xss-DENIED-getSelection-from-inactive-domwindow.html 9 10 * page/DOMWindow.cpp: 11 (WebCore::DOMWindow::~DOMWindow): 12 - Add ASSERTs to show that we're not recreating these objects. 13 - Add a call to clear() as defense in depth in case we have any of 14 these objects hanging around. 15 (WebCore::DOMWindow::clear): 16 - Clear out a couple of objects that weren't getting cleared. 17 These are actually not likely to cause problems, but clearing 18 them out is the safe thing to do. 19 (WebCore::DOMWindow::isActive): 20 - Add a concept of whether the DOMWindow is "active" in its frame. 21 We had this concept in a couple places already, but centralizing 22 it into a helper function make it easier to use and talk about. 23 (WebCore::DOMWindow::orientation): 24 - Whitespace nit. 25 (WebCore::DOMWindow::screen): 26 (WebCore::DOMWindow::history): 27 (WebCore::DOMWindow::crypto): 28 (WebCore::DOMWindow::locationbar): 29 (WebCore::DOMWindow::menubar): 30 (WebCore::DOMWindow::personalbar): 31 (WebCore::DOMWindow::scrollbars): 32 (WebCore::DOMWindow::statusbar): 33 (WebCore::DOMWindow::toolbar): 34 (WebCore::DOMWindow::console): 35 (WebCore::DOMWindow::applicationCache): 36 (WebCore::DOMWindow::navigator): 37 (WebCore::DOMWindow::performance): 38 (WebCore::DOMWindow::location): 39 (WebCore::DOMWindow::sessionStorage): 40 (WebCore::DOMWindow::localStorage): 41 (WebCore::DOMWindow::webkitNotifications): 42 (WebCore::DOMWindow::webkitIndexedDB): 43 (WebCore::DOMWindow::getSelection): 44 (WebCore::DOMWindow::styleMedia): 45 (WebCore::DOMWindow::webkitURL): 46 (WebCore::DOMWindow::webkitStorageInfo): 47 - Avoid creating these objects when we're not active. That can 48 only lead to sadness. 49 (WebCore::DOMWindow::webkitRequestFileSystem): 50 (WebCore::DOMWindow::webkitResolveLocalFileSystemURL): 51 (WebCore::DOMWindow::openDatabase): 52 (WebCore::DOMWindow::postMessage): 53 - While not techincally creating subobjects, these functions also 54 seem unwise when the DOMWindow is inactive. 55 (WebCore::DOMWindow::find): 56 (WebCore::DOMWindow::length): 57 (WebCore::DOMWindow::getMatchedCSSRules): 58 - These functions operate on the active Document. When we're not 59 active, that's not us! 60 (WebCore::DOMWindow::document): 61 - Update to use the new concept of being active rather than having 62 this function roll its own implementation. 63 (WebCore::DOMWindow::webkitConvertPointFromNodeToPage): 64 (WebCore::DOMWindow::webkitConvertPointFromPageToNode): 65 (WebCore::DOMWindow::scrollBy): 66 (WebCore::DOMWindow::scrollTo): 67 - These functions also look unwise to run when inactive because 68 they're reading information from the active document. 69 - I added a RefPtr for node because the call to 70 updateLayoutIgnorePendingStylesheets() seems likely to be able to 71 run script somehow. 72 (WebCore::DOMWindow::addEventListener): 73 (WebCore::DOMWindow::removeEventListener): 74 (WebCore::DOMWindow::dispatchLoadEvent): 75 (WebCore::DOMWindow::dispatchEvent): 76 - I don't think these functions worked when inactive anyway, but 77 explicitly blocking them seems wise. 78 (WebCore::DOMWindow::setLocation): 79 (WebCore::DOMWindow::isInsecureScriptAccess): 80 (WebCore::DOMWindow::open): 81 (WebCore::DOMWindow::showModalDialog): 82 - These already have checks for being active, but it can't hurt to 83 be explicit at the top of the function. 84 * page/DOMWindow.h: 85 1 86 2011-10-13 Kent Tamura <tkent@chromium.org> 2 87 -
trunk/Source/WebCore/page/DOMWindow.cpp
r95919 r97353 406 406 m_frame->clearFormerDOMWindow(this); 407 407 408 ASSERT(!m_screen); 409 ASSERT(!m_selection); 410 ASSERT(!m_history); 411 ASSERT(!m_crypto); 412 ASSERT(!m_locationbar); 413 ASSERT(!m_menubar); 414 ASSERT(!m_personalbar); 415 ASSERT(!m_scrollbars); 416 ASSERT(!m_statusbar); 417 ASSERT(!m_toolbar); 418 ASSERT(!m_console); 419 ASSERT(!m_navigator); 420 #if ENABLE(WEB_TIMING) 421 ASSERT(!m_performance); 422 #endif 423 ASSERT(!m_location); 424 ASSERT(!m_media); 425 #if ENABLE(DOM_STORAGE) 426 ASSERT(!m_sessionStorage); 427 ASSERT(!m_localStorage); 428 #endif 429 ASSERT(!m_applicationCache); 430 #if ENABLE(NOTIFICATIONS) 431 ASSERT(!m_notifications); 432 #endif 433 #if ENABLE(INDEXED_DATABASE) 434 ASSERT(!m_idbFactory); 435 #endif 436 #if ENABLE(BLOB) 437 ASSERT(!m_domURL); 438 #endif 439 #if ENABLE(QUOTA) 440 ASSERT(!m_storageInfo); 441 #endif 442 443 // This clear should be unnessary given the ASSERTs above, but we don't 444 // want any of these objects to hang around after we've been destroyed. 445 clear(); 446 408 447 removeAllUnloadEventListeners(this); 409 448 removeAllBeforeUnloadEventListeners(this); … … 516 555 m_idbFactory = 0; 517 556 #endif 557 558 #if ENABLE(BLOB) 559 m_domURL = 0; 560 #endif 561 562 #if ENABLE(QUOTA) 563 m_storageInfo = 0; 564 #endif 565 } 566 567 bool DOMWindow::isCurrentlyDisplayedInFrame() const 568 { 569 return m_frame && m_frame->domWindow() == this; 518 570 } 519 571 … … 523 575 if (!m_frame) 524 576 return 0; 525 577 526 578 return m_frame->orientation(); 527 579 } … … 530 582 Screen* DOMWindow::screen() const 531 583 { 532 if (!m_screen )584 if (!m_screen && isCurrentlyDisplayedInFrame()) 533 585 m_screen = Screen::create(m_frame); 534 586 return m_screen.get(); … … 537 589 History* DOMWindow::history() const 538 590 { 539 if (!m_history )591 if (!m_history && isCurrentlyDisplayedInFrame()) 540 592 m_history = History::create(m_frame); 541 593 return m_history.get(); … … 544 596 Crypto* DOMWindow::crypto() const 545 597 { 546 if (!m_crypto )598 if (!m_crypto && isCurrentlyDisplayedInFrame()) 547 599 m_crypto = Crypto::create(); 548 600 return m_crypto.get(); … … 551 603 BarInfo* DOMWindow::locationbar() const 552 604 { 553 if (!m_locationbar )605 if (!m_locationbar && isCurrentlyDisplayedInFrame()) 554 606 m_locationbar = BarInfo::create(m_frame, BarInfo::Locationbar); 555 607 return m_locationbar.get(); … … 558 610 BarInfo* DOMWindow::menubar() const 559 611 { 560 if (!m_menubar )612 if (!m_menubar && isCurrentlyDisplayedInFrame()) 561 613 m_menubar = BarInfo::create(m_frame, BarInfo::Menubar); 562 614 return m_menubar.get(); … … 565 617 BarInfo* DOMWindow::personalbar() const 566 618 { 567 if (!m_personalbar )619 if (!m_personalbar && isCurrentlyDisplayedInFrame()) 568 620 m_personalbar = BarInfo::create(m_frame, BarInfo::Personalbar); 569 621 return m_personalbar.get(); … … 572 624 BarInfo* DOMWindow::scrollbars() const 573 625 { 574 if (!m_scrollbars )626 if (!m_scrollbars && isCurrentlyDisplayedInFrame()) 575 627 m_scrollbars = BarInfo::create(m_frame, BarInfo::Scrollbars); 576 628 return m_scrollbars.get(); … … 579 631 BarInfo* DOMWindow::statusbar() const 580 632 { 581 if (!m_statusbar )633 if (!m_statusbar && isCurrentlyDisplayedInFrame()) 582 634 m_statusbar = BarInfo::create(m_frame, BarInfo::Statusbar); 583 635 return m_statusbar.get(); … … 586 638 BarInfo* DOMWindow::toolbar() const 587 639 { 588 if (!m_toolbar )640 if (!m_toolbar && isCurrentlyDisplayedInFrame()) 589 641 m_toolbar = BarInfo::create(m_frame, BarInfo::Toolbar); 590 642 return m_toolbar.get(); … … 593 645 Console* DOMWindow::console() const 594 646 { 595 if (!m_console )647 if (!m_console && isCurrentlyDisplayedInFrame()) 596 648 m_console = Console::create(m_frame); 597 649 return m_console.get(); … … 600 652 DOMApplicationCache* DOMWindow::applicationCache() const 601 653 { 602 if (!m_applicationCache )654 if (!m_applicationCache && isCurrentlyDisplayedInFrame()) 603 655 m_applicationCache = DOMApplicationCache::create(m_frame); 604 656 return m_applicationCache.get(); … … 607 659 Navigator* DOMWindow::navigator() const 608 660 { 609 if (!m_navigator )661 if (!m_navigator && isCurrentlyDisplayedInFrame()) 610 662 m_navigator = Navigator::create(m_frame); 611 663 return m_navigator.get(); … … 615 667 Performance* DOMWindow::performance() const 616 668 { 617 if (!m_performance )669 if (!m_performance && isCurrentlyDisplayedInFrame()) 618 670 m_performance = Performance::create(m_frame); 619 671 return m_performance.get(); … … 623 675 Location* DOMWindow::location() const 624 676 { 625 if (!m_location )677 if (!m_location && isCurrentlyDisplayedInFrame()) 626 678 m_location = Location::create(m_frame); 627 679 return m_location.get(); … … 631 683 Storage* DOMWindow::sessionStorage(ExceptionCode& ec) const 632 684 { 633 if (m_sessionStorage )685 if (m_sessionStorage || !isCurrentlyDisplayedInFrame()) 634 686 return m_sessionStorage.get(); 635 687 … … 656 708 Storage* DOMWindow::localStorage(ExceptionCode& ec) const 657 709 { 658 if (m_localStorage )710 if (m_localStorage || !isCurrentlyDisplayedInFrame()) 659 711 return m_localStorage.get(); 660 712 … … 686 738 NotificationCenter* DOMWindow::webkitNotifications() const 687 739 { 688 if (m_notifications )740 if (m_notifications || !isCurrentlyDisplayedInFrame()) 689 741 return m_notifications.get(); 690 742 … … 738 790 return 0; 739 791 740 if (!m_idbFactory )792 if (!m_idbFactory && isCurrentlyDisplayedInFrame()) 741 793 m_idbFactory = IDBFactory::create(page->group().idbFactory()); 742 794 return m_idbFactory.get(); … … 747 799 void DOMWindow::webkitRequestFileSystem(int type, long long size, PassRefPtr<FileSystemCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) 748 800 { 801 if (!isCurrentlyDisplayedInFrame()) 802 return; 803 749 804 Document* document = this->document(); 750 805 if (!document) … … 767 822 void DOMWindow::webkitResolveLocalFileSystemURL(const String& url, PassRefPtr<EntryCallback> successCallback, PassRefPtr<ErrorCallback> errorCallback) 768 823 { 824 if (!isCurrentlyDisplayedInFrame()) 825 return; 826 769 827 Document* document = this->document(); 770 828 if (!document) … … 805 863 void DOMWindow::postMessage(PassRefPtr<SerializedScriptValue> message, const MessagePortArray* ports, const String& targetOrigin, DOMWindow* source, ExceptionCode& ec) 806 864 { 807 if (! m_frame)865 if (!isCurrentlyDisplayedInFrame()) 808 866 return; 809 867 … … 857 915 DOMSelection* DOMWindow::getSelection() 858 916 { 859 if (!m_selection )917 if (!m_selection && isCurrentlyDisplayedInFrame()) 860 918 m_selection = DOMSelection::create(m_frame); 861 919 return m_selection.get(); … … 1045 1103 bool DOMWindow::find(const String& string, bool caseSensitive, bool backwards, bool wrap, bool /*wholeWord*/, bool /*searchInFrames*/, bool /*showDialog*/) const 1046 1104 { 1047 if (! m_frame)1105 if (!isCurrentlyDisplayedInFrame()) 1048 1106 return false; 1049 1107 … … 1164 1222 unsigned DOMWindow::length() const 1165 1223 { 1166 if (! m_frame)1224 if (!isCurrentlyDisplayedInFrame()) 1167 1225 return 0; 1168 1226 … … 1262 1320 Document* DOMWindow::document() const 1263 1321 { 1322 if (!isCurrentlyDisplayedInFrame()) 1323 return 0; 1324 1264 1325 // FIXME: This function shouldn't need a frame to work. 1265 if (!m_frame)1266 return 0;1267 1268 // The m_frame pointer is not zeroed out when the window is put into b/f cache, so it can hold an unrelated document/window pair.1269 // FIXME: We should always zero out the frame pointer on navigation to avoid accidentally accessing the new frame content.1270 if (m_frame->domWindow() != this)1271 return 0;1272 1273 1326 ASSERT(m_frame->document()); 1274 1327 return m_frame->document(); … … 1277 1330 PassRefPtr<StyleMedia> DOMWindow::styleMedia() const 1278 1331 { 1279 if (!m_media )1332 if (!m_media && isCurrentlyDisplayedInFrame()) 1280 1333 m_media = StyleMedia::create(m_frame); 1281 1334 return m_media.get(); … … 1292 1345 PassRefPtr<CSSRuleList> DOMWindow::getMatchedCSSRules(Element* element, const String&, bool authorOnly) const 1293 1346 { 1294 if (! m_frame)1347 if (!isCurrentlyDisplayedInFrame()) 1295 1348 return 0; 1296 1349 … … 1311 1364 return 0; 1312 1365 1313 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1366 if (!document()) 1367 return 0; 1368 1369 document()->updateLayoutIgnorePendingStylesheets(); 1314 1370 1315 1371 FloatPoint pagePoint(p->x(), p->y()); … … 1323 1379 return 0; 1324 1380 1325 m_frame->document()->updateLayoutIgnorePendingStylesheets(); 1381 if (!document()) 1382 return 0; 1383 1384 document()->updateLayoutIgnorePendingStylesheets(); 1326 1385 1327 1386 FloatPoint nodePoint(p->x(), p->y()); … … 1345 1404 PassRefPtr<Database> DOMWindow::openDatabase(const String& name, const String& version, const String& displayName, unsigned long estimatedSize, PassRefPtr<DatabaseCallback> creationCallback, ExceptionCode& ec) 1346 1405 { 1406 if (!isCurrentlyDisplayedInFrame()) 1407 return 0; 1408 1347 1409 RefPtr<Database> database = 0; 1348 1410 if (m_frame && AbstractDatabase::isAvailable() && m_frame->document()->securityOrigin()->canAccessDatabase()) … … 1358 1420 void DOMWindow::scrollBy(int x, int y) const 1359 1421 { 1360 if (! m_frame)1361 return; 1362 1363 m_frame->document()->updateLayoutIgnorePendingStylesheets();1422 if (!isCurrentlyDisplayedInFrame()) 1423 return; 1424 1425 document()->updateLayoutIgnorePendingStylesheets(); 1364 1426 1365 1427 FrameView* view = m_frame->view(); … … 1372 1434 void DOMWindow::scrollTo(int x, int y) const 1373 1435 { 1374 if (! m_frame)1375 return; 1376 1377 m_frame->document()->updateLayoutIgnorePendingStylesheets();1436 if (!isCurrentlyDisplayedInFrame()) 1437 return; 1438 1439 document()->updateLayoutIgnorePendingStylesheets(); 1378 1440 1379 1441 RefPtr<FrameView> view = m_frame->view(); … … 1652 1714 void DOMWindow::setLocation(const String& urlString, DOMWindow* activeWindow, DOMWindow* firstWindow, SetLocationLocking locking) 1653 1715 { 1654 if (! m_frame)1716 if (!isCurrentlyDisplayedInFrame()) 1655 1717 return; 1656 1718 … … 1712 1774 return false; 1713 1775 1714 // If m_frame->domWindow() != this, then |this| isn't the DOMWindow that's 1715 // currently active in the frame and there's no way we should allow the 1716 // access. 1776 // If this DOMWindow isn't currently active in the Frame, then there's no 1777 // way we should allow the access. 1717 1778 // FIXME: Remove this check if we're able to disconnect DOMWindow from 1718 1779 // Frame on navigation: https://bugs.webkit.org/show_bug.cgi?id=62054 1719 if ( m_frame->domWindow() == this) {1780 if (isCurrentlyDisplayedInFrame()) { 1720 1781 // FIXME: Is there some way to eliminate the need for a separate "activeWindow == this" check? 1721 1782 if (activeWindow == this) … … 1774 1835 DOMWindow* activeWindow, DOMWindow* firstWindow) 1775 1836 { 1776 if (! m_frame)1837 if (!isCurrentlyDisplayedInFrame()) 1777 1838 return 0; 1778 1839 Frame* activeFrame = activeWindow->frame(); … … 1842 1903 DOMWindow* activeWindow, DOMWindow* firstWindow, PrepareDialogFunction function, void* functionContext) 1843 1904 { 1844 if (! m_frame)1905 if (!isCurrentlyDisplayedInFrame()) 1845 1906 return; 1846 1907 Frame* activeFrame = activeWindow->frame(); … … 1865 1926 DOMURL* DOMWindow::webkitURL() const 1866 1927 { 1867 if (!m_domURL )1928 if (!m_domURL && isCurrentlyDisplayedInFrame()) 1868 1929 m_domURL = DOMURL::create(this->scriptExecutionContext()); 1869 1930 return m_domURL.get(); … … 1874 1935 StorageInfo* DOMWindow::webkitStorageInfo() const 1875 1936 { 1876 if (!m_storageInfo )1937 if (!m_storageInfo && isCurrentlyDisplayedInFrame()) 1877 1938 m_storageInfo = StorageInfo::create(); 1878 1939 return m_storageInfo.get(); -
trunk/Source/WebCore/page/DOMWindow.h
r95919 r97353 415 415 DOMWindow(Frame*); 416 416 417 // FIXME: When this DOMWindow is no longer the active DOMWindow (i.e., 418 // when its document is no longer the document that is displayed in its 419 // frame), we would like to zero out m_frame to avoid being confused 420 // by the document that is currently active in m_frame. 421 bool isCurrentlyDisplayedInFrame() const; 422 417 423 virtual void refEventTarget() { ref(); } 418 424 virtual void derefEventTarget() { deref(); }
Note: See TracChangeset
for help on using the changeset viewer.