From 17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Mon, 25 Oct 2010 16:02:36 +0200 Subject: Fix possible crash on llassert_always(purge_list.size() >= entries_to_purge) This horrible noobish code checked if num_entries > sCacheMaxEntries and then goes on to assign (num_entries-empty_entries) - sCacheMaxEntries to an U32 entries_to_purge. Obviously this can lead to an abitrary large value of entries_to_purge with as result a crash due to the llassert_always. This bug must have been extremely rare since it only happens when someone decreases their cache size and has more empty entries in their entries file than the total number of entries minus the new cache size. --- linden/indra/newview/lltexturecache.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'linden') diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp index b0d8412..ae0a63f 100644 --- a/linden/indra/newview/lltexturecache.cpp +++ b/linden/indra/newview/lltexturecache.cpp @@ -1172,7 +1172,7 @@ void LLTextureCache::readHeaderCache() U32 empty_entries = 0; typedef std::pair lru_data_t; std::set lru; - std::vector purge_list; + std::set purge_list; for (U32 i=0; i sCacheMaxEntries) + if (num_entries - empty_entries > sCacheMaxEntries) { // Special case: cache size was reduced, need to remove entries // Note: After we prune entries, we will call this again and create the LRU - U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; + U32 entries_to_purge = (num_entries - empty_entries) - sCacheMaxEntries; llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; - if (entries_to_purge > 0) + // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have: + // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge + for (std::set::iterator iter = lru.begin(); purge_list.size() < entries_to_purge; ++iter) { - for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) - { - purge_list.push_back(iter->second); - if (purge_list.size() >= entries_to_purge) - break; - } + purge_list.insert(iter->second); } - llassert_always(purge_list.size() >= entries_to_purge); } else { @@ -1227,7 +1223,7 @@ void LLTextureCache::readHeaderCache() if (purge_list.size() > 0) { - for (std::vector::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) + for (std::set::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) { mHeaderMutex.unlock(); removeFromCache(*iter); -- cgit v1.1