summaryrefslogtreecommitdiffstats
path: root/libass/ass_cache.c
diff options
context:
space:
mode:
authorgreg <greg@blackbox>2009-06-19 05:13:07 +0200
committergreg <greg@blackbox>2009-06-19 05:13:07 +0200
commit457a9146ee07060a8c45b850a69ea5c6bbdae70e (patch)
tree0c643447b6f4ceddc2ba7508f43660d6f3edb8a1 /libass/ass_cache.c
parente7e108672381007c2beaec5c436d757cca0017a2 (diff)
downloadlibass-457a9146ee07060a8c45b850a69ea5c6bbdae70e.tar.bz2
libass-457a9146ee07060a8c45b850a69ea5c6bbdae70e.tar.xz
From uau: libass: Fix cache lookup problem causing memory bloat
The cache code did hash lookups by storing key values in struct fields and then hashing and comparing the struct as a single memory block. In at least one case such a struct contained uninitialized padding bytes which prevented the complete memory area of the struct from matching even though the fields did. As a result the code failed to find existing objects in the cache and stored new versions of them, causing gigabytes of memory use in some circumstances. Initializing the struct memory to zero before writing the fields avoided such memory use in tests but is not guaranteed to work if I interpret the C standard correctly (the compiler is allowed to write garbage over padding bytes when changing struct member values). Change the code to use struct-specific hashing and comparison functions that work field by field to guarantee correct behavior. Create these by replacing the struct definition with a template that lists the fields and can be used the generate each of struct definition, hash function and compare function with some preprocessor magic (otherwise every field would need to be listed separately in all three).
Diffstat (limited to 'libass/ass_cache.c')
-rw-r--r--libass/ass_cache.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index dc217bd..2e941c0 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -230,6 +230,13 @@ void ass_font_cache_done(void)
hashmap_done(font_cache);
}
+
+// Create hash/compare functions for bitmap and glyph
+#define CREATE_HASH_FUNCTIONS
+#include "ass_cache_template.c"
+#define CREATE_COMPARISON_FUNCTIONS
+#include "ass_cache_template.c"
+
//---------------------------------
// bitmap cache
@@ -265,7 +272,8 @@ void ass_bitmap_cache_init(void)
bitmap_cache = hashmap_init(sizeof(bitmap_hash_key_t),
sizeof(bitmap_hash_val_t),
0xFFFF + 13,
- bitmap_hash_dtor, NULL, NULL);
+ bitmap_hash_dtor, bitmap_compare,
+ bitmap_hash);
}
void ass_bitmap_cache_done(void)
@@ -313,7 +321,7 @@ void ass_glyph_cache_init(void)
glyph_cache = hashmap_init(sizeof(glyph_hash_key_t),
sizeof(glyph_hash_val_t),
0xFFFF + 13,
- glyph_hash_dtor, NULL, NULL);
+ glyph_hash_dtor, glyph_compare, glyph_hash);
}
void ass_glyph_cache_done(void)