diff options
author | Robin Watts <robin.watts@artifex.com> | 2012-01-13 15:54:13 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2012-01-13 15:54:13 +0000 |
commit | 6dfcd67f524a1931830a3b01198951a7843462db (patch) | |
tree | 2d45e08d3a37ddd14154bcd9f2af6b386071c919 | |
parent | 5e89e9cc3918b9e7e98045f220320ae044dbdc67 (diff) | |
download | mupdf-6dfcd67f524a1931830a3b01198951a7843462db.tar.xz |
Scavenging fixes; overflow and division by zero.
Ensure we don't get a division by zero (when *phase goes to 16).
Also ensure we don't overflow the bounds of an unsigned int.
Thanks to Zeniko for spotting these problems.
-rw-r--r-- | fitz/res_store.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/fitz/res_store.c b/fitz/res_store.c index 6a38f438..dc9b14a2 100644 --- a/fitz/res_store.c +++ b/fitz/res_store.c @@ -436,23 +436,34 @@ int fz_store_scavenge(fz_context *ctx, unsigned int size, int *phase) #endif do { + unsigned int tofree; + /* Calculate 'max' as the maximum size of the store for this phase */ - if (store->max != FZ_STORE_UNLIMITED) + if (*phase >= 16) + max = 0; + else if (store->max != FZ_STORE_UNLIMITED) max = store->max / 16 * (16 - *phase); else max = store->size / (16 - *phase) * (15 - *phase); (*phase)++; - if (size + store->size > max) - if (scavenge(ctx, size + store->size - max)) - { + /* Slightly baroque calculations to avoid overflow */ + if (size > UINT_MAX - store->size) + tofree = UINT_MAX - max; + else if (size + store->size > max) + continue; + else + tofree = size + store->size - max; + + if (scavenge(ctx, tofree)) + { #ifdef DEBUG_SCAVENGING - printf("scavenged: store=%d\n", store->size); - fz_debug_store(ctx); - Memento_stats(); + printf("scavenged: store=%d\n", store->size); + fz_debug_store(ctx); + Memento_stats(); #endif - return 1; - } + return 1; + } } while (max > 0); |