Changeset 241121 in webkit
- Timestamp:
- Feb 7, 2019 8:07:03 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r241120 r241121 1 2019-02-07 Antti Koivisto <antti@apple.com> 2 3 Infinite recursion via CachedResource::~CachedResource 4 https://bugs.webkit.org/show_bug.cgi?id=194378 5 <rdar://problem/42023295> 6 7 Reviewed by Daniel Bates. 8 9 I don't know the exact steps to trigger this but the mechanism seems clear. 10 11 1) An existing resource is removed from or replaced in CachedResourceLoader::m_documentResources map. 12 2) This decrements the handle count of resource and causes it be deleted. 13 3) CachedResource::~CachedResource calls m_owningCachedResourceLoader->removeCachedResource(*this). This only happens with 14 resources that are "owned" by CachedResourceLoader which is a rare special case (used by image document and if memory cache is disabled). 15 4) CachedResourceLoader::removeCachedResource looks up the resource from the map which causes a temporary CachedResourceHandle to be created. 16 This increments the handle count of the resource from 0 back to 1. 17 5) When the temporary dies, CachedResource::~CachedResource is called again and we cycle back to 3). 18 19 The fix here is simply to remove CachedResourceLoader::removeCachedResource call from ~CachedResource. 20 It is a leftover from when the map contained raw pointers instead of owning CachedResourceHandles. 21 22 Since m_documentResources map has a handle to the resource, the only way we are in the destructor is that the resource 23 has been removed from the map already (or is in process of being removed like in this crash). Any call that does anything 24 other than bail out is going to crash. 25 26 CachedResource::n_owningCachedResourceLoader member and CachedResourceLoader::removeCachedResource function only exist to 27 support this erranous call so they are removed as well. 28 29 * loader/ImageLoader.cpp: 30 (WebCore::ImageLoader::updateFromElement): 31 * loader/cache/CachedResource.cpp: 32 (WebCore::CachedResource::~CachedResource): 33 34 This is the substantive change. The rest just removes now-dead code. 35 36 * loader/cache/CachedResource.h: 37 (WebCore::CachedResource::setOwningCachedResourceLoader): Deleted. 38 * loader/cache/CachedResourceLoader.cpp: 39 (WebCore::CachedResourceLoader::~CachedResourceLoader): 40 (WebCore::CachedResourceLoader::requestUserCSSStyleSheet): 41 (WebCore::CachedResourceLoader::requestResource): 42 (WebCore::CachedResourceLoader::loadResource): 43 (WebCore::CachedResourceLoader::garbageCollectDocumentResources): 44 (WebCore::CachedResourceLoader::removeCachedResource): Deleted. 45 * loader/cache/CachedResourceLoader.h: 46 1 47 2019-02-07 Miguel Gomez <magomez@igalia.com> 2 48 -
trunk/Source/WebCore/loader/ImageLoader.cpp
r240014 r241121 195 195 newImage->setStatus(CachedResource::Pending); 196 196 newImage->setLoading(true); 197 newImage->setOwningCachedResourceLoader(&document.cachedResourceLoader());198 197 document.cachedResourceLoader().m_documentResources.set(newImage->url(), newImage.get()); 199 198 document.cachedResourceLoader().setAutoLoadImages(autoLoadOtherImages); -
trunk/Source/WebCore/loader/cache/CachedResource.cpp
r240641 r241121 175 175 cachedResourceLeakCounter.decrement(); 176 176 #endif 177 178 if (m_owningCachedResourceLoader)179 m_owningCachedResourceLoader->removeCachedResource(*this);180 177 } 181 178 -
trunk/Source/WebCore/loader/cache/CachedResource.h
r241113 r241121 235 235 virtual void destroyDecodedData() { } 236 236 237 void setOwningCachedResourceLoader(CachedResourceLoader* cachedResourceLoader) { m_owningCachedResourceLoader = cachedResourceLoader; }238 239 237 bool isPreloaded() const { return m_preloadCount; } 240 238 void increasePreloadCount() { ++m_preloadCount; } … … 334 332 Vector<std::pair<String, String>> m_varyingHeaderValues; 335 333 336 CachedResourceLoader* m_owningCachedResourceLoader { nullptr }; // only non-null for resources that are not in the cache337 338 334 // If this field is non-null we are using the resource as a proxy for checking whether an existing resource is still up to date 339 335 // using HTTP If-Modified-Since/If-None-Match headers. If the response is 304 all clients of this resource are moved -
trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp
r240014 r241121 162 162 163 163 clearPreloads(ClearPreloadsMode::ClearAllPreloads); 164 for (auto& resource : m_documentResources.values())165 resource->setOwningCachedResourceLoader(nullptr);166 164 167 165 // Make sure no requests still point to this CachedResourceLoader … … 259 257 if (userSheet->allowsCaching()) 260 258 memoryCache.add(*userSheet); 261 // FIXME: loadResource calls setOwningCachedResourceLoader() if the resource couldn't be added to cache. Does this function need to call it, too?262 259 263 260 userSheet->load(*this); … … 862 859 863 860 auto& memoryCache = MemoryCache::singleton(); 864 if (request.allowsCaching() && memoryCache.disabled()) { 865 if (auto handle = m_documentResources.take(url.string())) 866 handle->setOwningCachedResourceLoader(nullptr); 867 } 861 if (request.allowsCaching() && memoryCache.disabled()) 862 m_documentResources.remove(url.string()); 868 863 869 864 // See if we can use an existing resource from the cache. … … 1014 1009 CachedResourceHandle<CachedResource> resource = createResource(type, WTFMove(request), sessionID(), cookieJar); 1015 1010 1016 if (resource->allowsCaching() && !memoryCache.add(*resource))1017 resource->setOwningCachedResourceLoader(this);1011 if (resource->allowsCaching()) 1012 memoryCache.add(*resource); 1018 1013 1019 1014 if (RuntimeEnabledFeatures::sharedFeatures().resourceTimingEnabled()) … … 1303 1298 } 1304 1299 1305 void CachedResourceLoader::removeCachedResource(CachedResource& resource)1306 {1307 if (m_documentResources.contains(resource.url()) && m_documentResources.get(resource.url()).get() != &resource)1308 return;1309 m_documentResources.remove(resource.url());1310 }1311 1312 1300 void CachedResourceLoader::loadDone(LoadCompletionType type, bool shouldPerformPostLoadActions) 1313 1301 { … … 1343 1331 LOG(ResourceLoading, " cached resource %p - hasOneHandle %d", resource.value.get(), resource.value->hasOneHandle()); 1344 1332 1345 if (resource.value->hasOneHandle()) {1333 if (resource.value->hasOneHandle()) 1346 1334 resourcesToDelete.append(resource.key); 1347 resource.value->setOwningCachedResourceLoader(nullptr);1348 }1349 1335 } 1350 1336 -
trunk/Source/WebCore/loader/cache/CachedResourceLoader.h
r240014 r241121 130 130 void clearDocumentLoader() { m_documentLoader = nullptr; } 131 131 PAL::SessionID sessionID() const; 132 133 void removeCachedResource(CachedResource&);134 132 135 133 void loadDone(LoadCompletionType, bool shouldPerformPostLoadActions = true);
Note: See TracChangeset
for help on using the changeset viewer.