diff options
author | Aleric Inglewood | 2010-10-25 16:02:36 +0200 |
---|---|---|
committer | Aleric Inglewood | 2010-10-25 16:02:36 +0200 |
commit | 17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e (patch) | |
tree | bb00d82b96d5cfc7c272c28deeeb00c0ec996592 /linden | |
parent | Validate textures starting with 00 too. (diff) | |
download | meta-impy-17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e.zip meta-impy-17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e.tar.gz meta-impy-17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e.tar.bz2 meta-impy-17e2c3f8999d93bb59deb7ac0c289ed2157a3f5e.tar.xz |
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.
Diffstat (limited to '')
-rw-r--r-- | linden/indra/newview/lltexturecache.cpp | 22 |
1 files changed, 9 insertions, 13 deletions
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() | |||
1172 | U32 empty_entries = 0; | 1172 | U32 empty_entries = 0; |
1173 | typedef std::pair<U32, LLUUID> lru_data_t; | 1173 | typedef std::pair<U32, LLUUID> lru_data_t; |
1174 | std::set<lru_data_t> lru; | 1174 | std::set<lru_data_t> lru; |
1175 | std::vector<LLUUID> purge_list; | 1175 | std::set<LLUUID> purge_list; |
1176 | for (U32 i=0; i<num_entries; i++) | 1176 | for (U32 i=0; i<num_entries; i++) |
1177 | { | 1177 | { |
1178 | Entry& entry = entries[i]; | 1178 | Entry& entry = entries[i]; |
@@ -1191,27 +1191,23 @@ void LLTextureCache::readHeaderCache() | |||
1191 | { | 1191 | { |
1192 | // Shouldn't happen, failsafe only | 1192 | // Shouldn't happen, failsafe only |
1193 | llwarns << "Bad entry: " << i << ": " << entry.mID << ": BodySize: " << entry.mBodySize << llendl; | 1193 | llwarns << "Bad entry: " << i << ": " << entry.mID << ": BodySize: " << entry.mBodySize << llendl; |
1194 | purge_list.push_back(id); | 1194 | purge_list.insert(id); |
1195 | } | 1195 | } |
1196 | } | 1196 | } |
1197 | } | 1197 | } |
1198 | } | 1198 | } |
1199 | if (num_entries > sCacheMaxEntries) | 1199 | if (num_entries - empty_entries > sCacheMaxEntries) |
1200 | { | 1200 | { |
1201 | // Special case: cache size was reduced, need to remove entries | 1201 | // Special case: cache size was reduced, need to remove entries |
1202 | // Note: After we prune entries, we will call this again and create the LRU | 1202 | // Note: After we prune entries, we will call this again and create the LRU |
1203 | U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; | 1203 | U32 entries_to_purge = (num_entries - empty_entries) - sCacheMaxEntries; |
1204 | llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; | 1204 | llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; |
1205 | if (entries_to_purge > 0) | 1205 | // We can exit the following loop with the given condition, since if we'd reach the end of the lru set we'd have: |
1206 | // purge_list.size() = lru.size() = num_entries - empty_entries = entries_to_purge + sCacheMaxEntries >= entries_to_purge | ||
1207 | for (std::set<lru_data_t>::iterator iter = lru.begin(); purge_list.size() < entries_to_purge; ++iter) | ||
1206 | { | 1208 | { |
1207 | for (std::set<lru_data_t>::iterator iter = lru.begin(); iter != lru.end(); ++iter) | 1209 | purge_list.insert(iter->second); |
1208 | { | ||
1209 | purge_list.push_back(iter->second); | ||
1210 | if (purge_list.size() >= entries_to_purge) | ||
1211 | break; | ||
1212 | } | ||
1213 | } | 1210 | } |
1214 | llassert_always(purge_list.size() >= entries_to_purge); | ||
1215 | } | 1211 | } |
1216 | else | 1212 | else |
1217 | { | 1213 | { |
@@ -1227,7 +1223,7 @@ void LLTextureCache::readHeaderCache() | |||
1227 | 1223 | ||
1228 | if (purge_list.size() > 0) | 1224 | if (purge_list.size() > 0) |
1229 | { | 1225 | { |
1230 | for (std::vector<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) | 1226 | for (std::set<LLUUID>::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) |
1231 | { | 1227 | { |
1232 | mHeaderMutex.unlock(); | 1228 | mHeaderMutex.unlock(); |
1233 | removeFromCache(*iter); | 1229 | removeFromCache(*iter); |