Title: [119037] branches/safari-536-branch/Source/WebKit2

Diff

Modified: branches/safari-536-branch/Source/WebKit2/ChangeLog (119036 => 119037)


--- branches/safari-536-branch/Source/WebKit2/ChangeLog	2012-05-31 03:22:19 UTC (rev 119036)
+++ branches/safari-536-branch/Source/WebKit2/ChangeLog	2012-05-31 03:23:54 UTC (rev 119037)
@@ -1,5 +1,31 @@
 2012-05-30  Lucas Forschler  <[email protected]>
 
+    Merge 118441
+
+    2012-05-24  Brady Eidson  <[email protected]>
+
+            <rdar://problem/10090764> and https://bugs.webkit.org/show_bug.cgi?id=87417
+            (Unrepro) Crashes saving session state in WebBackForwardList
+
+            Reviewed by Darin Adler.
+
+            * UIProcess/WebBackForwardList.cpp:
+            (WebKit::WebBackForwardList::addItem): Null check the proposed item and also m_page, to make
+              sure the page hasn't been closed making this list inactive. Be more aggressive about
+              clearing the current entries out if there is no current item index.
+            (WebKit::WebBackForwardList::itemAtIndex): Early null return if there is no current index.
+            (WebKit::WebBackForwardList::clear): Don't put the current item back in the array if there was
+              no current item.
+
+            * UIProcess/cf/WebBackForwardListCF.cpp:
+            (WebKit::WebBackForwardList::createCFDictionaryRepresentation): Don't create a meaningless WebURL.
+              Don't successfully return a dictionary if any of the entries were null. Be more aggressive about
+              validating the current index we plan to return in the dictionary.
+            (WebKit::WebBackForwardList::restoreFromCFDictionaryRepresentation): More aggressively validate the
+              current index read from disk. Replace a meaningless sanity check with our typical ASSERT.
+
+2012-05-30  Lucas Forschler  <[email protected]>
+
     Merge 118439
 
     2012-05-24  Anders Carlsson  <[email protected]>

Modified: branches/safari-536-branch/Source/WebKit2/UIProcess/WebBackForwardList.cpp (119036 => 119037)


--- branches/safari-536-branch/Source/WebKit2/UIProcess/WebBackForwardList.cpp	2012-05-31 03:22:19 UTC (rev 119036)
+++ branches/safari-536-branch/Source/WebKit2/UIProcess/WebBackForwardList.cpp	2012-05-31 03:23:54 UTC (rev 119037)
@@ -39,7 +39,7 @@
     , m_closed(true)
     , m_enabled(true)
 {
-    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
+    ASSERT(m_page);
 }
 
 WebBackForwardList::~WebBackForwardList()
@@ -61,40 +61,51 @@
 {
     ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
 
-    if (m_capacity == 0 || !m_enabled)
+    if (!m_capacity || !m_enabled || !newItem || !m_page)
         return;
 
     Vector<RefPtr<APIObject> > removedItems;
     
-    // Toss anything in the forward list    
     if (m_current != NoCurrentItemIndex) {
+        // Toss everything in the forward list.
         unsigned targetSize = m_current + 1;
         removedItems.reserveCapacity(m_entries.size() - targetSize);
         while (m_entries.size() > targetSize) {
-            if (m_page)
-                m_page->backForwardRemovedItem(m_entries.last()->itemID());
+            m_page->backForwardRemovedItem(m_entries.last()->itemID());
             removedItems.append(m_entries.last().release());
             m_entries.removeLast();
         }
-    }
 
-    // Toss the first item if the list is getting too big, as long as we're not using it
-    // (or even if we are, if we only want 1 entry).
-    if (m_entries.size() == m_capacity && (m_current != 0 || m_capacity == 1)) {
-        if (m_page)
+        // Toss the first item if the list is getting too big, as long as we're not using it
+        // (or even if we are, if we only want 1 entry).
+        if (m_entries.size() == m_capacity && (m_current || m_capacity == 1)) {
             m_page->backForwardRemovedItem(m_entries[0]->itemID());
-        removedItems.append(m_entries[0].release());
-        m_entries.remove(0);
-        m_current--;
+            removedItems.append(m_entries[0].release());
+            m_entries.remove(0);
+            m_current--;
+        }
+    } else {
+        // If we have no current item index, we should have no other entries before adding this new item.
+        size_t size = m_entries.size();
+        for (size_t i = 0; i < size; ++i) {
+            m_page->backForwardRemovedItem(m_entries[i]->itemID());
+            removedItems.append(m_entries[i].release());
+        }
+        m_entries.clear();
     }
+    
+    if (m_current == NoCurrentItemIndex)
+        m_current = 0;
+    else
+        m_current++;
 
-    m_entries.insert(m_current + 1, newItem);
-    m_current++;
+    // m_current never be pointing more than 1 past the end of the entries Vector.
+    // If it is, something has gone wrong and we should not try to insert the new item.
+    ASSERT(m_current <= m_entries.size());
+    if (m_current <= m_entries.size())
+        m_entries.insert(m_current, newItem);
 
-    if (m_page)
-        m_page->didChangeBackForwardList(newItem, &removedItems);
-
-    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
+    m_page->didChangeBackForwardList(newItem, &removedItems);
 }
 
 void WebBackForwardList::goToItem(WebBackForwardListItem* item)
@@ -147,8 +158,11 @@
 {
     ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());
 
+    if (m_current == NoCurrentItemIndex)
+        return 0;
+    
     // Do range checks without doing math on index to avoid overflow.
-    if (index < -static_cast<int>(m_current))
+    if (index < -backListCount())
         return 0;
     
     if (index > forwardListCount())
@@ -232,12 +246,17 @@
         if (i != m_current)
             removedItems.append(m_entries[i].release());
     }
-    
-    m_entries.shrink(1);
-    m_entries[0] = currentItem.release();
 
     m_current = 0;
 
+    if (currentItem) {
+        m_entries.shrink(1);
+        m_entries[0] = currentItem.release();
+    } else {
+        m_entries.clear();
+        m_current = NoCurrentItemIndex;
+    }
+
     if (m_page)
         m_page->didChangeBackForwardList(0, &removedItems);
 }

Modified: branches/safari-536-branch/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp (119036 => 119037)


--- branches/safari-536-branch/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp	2012-05-31 03:22:19 UTC (rev 119036)
+++ branches/safari-536-branch/Source/WebKit2/UIProcess/cf/WebBackForwardListCF.cpp	2012-05-31 03:23:54 UTC (rev 119037)
@@ -58,10 +58,14 @@
     RetainPtr<CFMutableArrayRef> entries(AdoptCF, CFArrayCreateMutable(0, m_entries.size(), &kCFTypeArrayCallBacks));
 
     // We may need to update the current index to account for entries that are filtered by the callback.
-    int currentIndex = m_current;
+    CFIndex currentIndex = m_current;
 
     for (size_t i = 0; i < m_entries.size(); ++i) {
-        RefPtr<WebURL> webURL = WebURL::create(m_entries[i]->url());
+        // If we somehow ended up with a null entry then we should consider the data invalid and not save session history at all.
+        ASSERT(m_entries[i]);
+        if (!m_entries[i])
+            return 0;
+
         if (filter && !filter(toAPI(m_page), WKPageGetSessionHistoryURLValueType(), toURLRef(m_entries[i]->originalURL().impl()), context)) {
             if (i <= static_cast<size_t>(m_current))
                 currentIndex--;
@@ -82,10 +86,19 @@
         RetainPtr<CFDictionaryRef> entryDictionary(AdoptCF, CFDictionaryCreate(0, keys, values, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
         CFArrayAppendValue(entries.get(), entryDictionary.get());
     }
+        
+    // If all items before and including the current item were filtered then currentIndex will be -1.
+    // Assuming we didn't start out with NoCurrentItemIndex, we should store "current" to point at the first item.
+    if (currentIndex == -1 && m_current != NoCurrentItemIndex && CFArrayGetCount(entries.get()))
+        currentIndex = 0;
 
-    ASSERT(currentIndex < CFArrayGetCount(entries.get()) && currentIndex >= static_cast<int>(NoCurrentItemIndex));
-    RetainPtr<CFNumberRef> currentIndexNumber(AdoptCF, CFNumberCreate(0, kCFNumberIntType, &currentIndex));
+    // FIXME: We're relying on currentIndex == -1 to mean the exact same thing as NoCurrentItemIndex (UINT_MAX) in unsigned form.
+    // That seems implicit and fragile and we should find a better way of representing the NoCurrentItemIndex case.
+    if (m_current == NoCurrentItemIndex || !CFArrayGetCount(entries.get()))
+        currentIndex = -1;
 
+    RetainPtr<CFNumberRef> currentIndexNumber(AdoptCF, CFNumberCreate(0, kCFNumberCFIndexType, &currentIndex));
+
     const void* keys[2] = { SessionHistoryCurrentIndexKey(), SessionHistoryEntriesKey() };
     const void* values[2] = { currentIndexNumber.get(), entries.get() };
 
@@ -100,11 +113,16 @@
         return false;
     }
 
-    CFIndex currentIndex;
-    if (!CFNumberGetValue(cfIndex, kCFNumberCFIndexType, &currentIndex)) {
+    CFIndex currentCFIndex;
+    if (!CFNumberGetValue(cfIndex, kCFNumberCFIndexType, &currentCFIndex)) {
         LOG(SessionState, "WebBackForwardList dictionary representation does not have a valid integer current index");
         return false;
     }
+    
+    if (currentCFIndex < -1) {
+        LOG(SessionState, "WebBackForwardList dictionary representation contains a negative current index that is bogus (%ld)", currentCFIndex);
+        return false;
+    }
 
     CFArrayRef cfEntries = (CFArrayRef)CFDictionaryGetValue(dictionary, SessionHistoryEntriesKey());
     if (!cfEntries || CFGetTypeID(cfEntries) != CFArrayGetTypeID()) {
@@ -113,12 +131,16 @@
     }
 
     CFIndex size = CFArrayGetCount(cfEntries);
-    if (currentIndex != static_cast<CFIndex>(NoCurrentItemIndex) && currentIndex >= size) {
-        LOG(SessionState, "WebBackForwardList dictionary representation contains an invalid current index (%ld) for the number of entries (%ld)", currentIndex, size);
+    if (currentCFIndex != -1 && currentCFIndex >= size) {
+        LOG(SessionState, "WebBackForwardList dictionary representation contains an invalid current index (%ld) for the number of entries (%ld)", currentCFIndex, size);
         return false;
     }
 
-    if (currentIndex == static_cast<CFIndex>(NoCurrentItemIndex) && size) {
+    // FIXME: We're relying on currentIndex == -1 to mean the exact same thing as NoCurrentItemIndex (UINT_MAX) in unsigned form.
+    // That seems implicit and fragile and we should find a better way of representing the NoCurrentItemIndex case.
+    uint32_t currentIndex = currentCFIndex == -1 ? NoCurrentItemIndex : currentCFIndex;
+
+    if (currentIndex == NoCurrentItemIndex && size) {
         LOG(SessionState, "WebBackForwardList dictionary representation says there is no current item index, but there is a list of %ld entries - this is bogus", size);
         return false;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to