summaryrefslogtreecommitdiff
path: root/fitz/res_store.c
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-01-13 15:54:13 +0000
committerRobin Watts <robin.watts@artifex.com>2012-01-13 15:54:13 +0000
commit6dfcd67f524a1931830a3b01198951a7843462db (patch)
tree2d45e08d3a37ddd14154bcd9f2af6b386071c919 /fitz/res_store.c
parent5e89e9cc3918b9e7e98045f220320ae044dbdc67 (diff)
downloadmupdf-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.
Diffstat (limited to 'fitz/res_store.c')
-rw-r--r--fitz/res_store.c29
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);