summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-03-06 19:34:06 +0000
committerRobin Watts <robin@ghostscript.com>2012-03-06 19:49:48 +0000
commitdae93920d513842f6c9a96e833043f3f6f8e0681 (patch)
treea54fb901c5cab53fbbf97deced91d1db75984654
parenta958c1e2effd97d8f17779ab975d72ee67b1ab09 (diff)
downloadmupdf-dae93920d513842f6c9a96e833043f3f6f8e0681.tar.xz
Fix ref counting bugs in race condition correction code.
When we attempt to insert a key/value pair into the store, we have to allow for the possibility that a racing thread may have already inserted an equivalent key/value. We have special code in place to handle this eventuality; if we spot an existing entry, we take the existing one in preference to our new key/value pair. This means that fz_store_item needs to take a new reference to any existing thing it finds before returning it. Currently the only store user that is exposed to this possibility is pdf_image; it spots an existing tile being returned, and was inadvertently double freeing the key.
-rw-r--r--fitz/res_store.c5
-rw-r--r--pdf/pdf_image.c1
-rw-r--r--pdf/pdf_store.c4
3 files changed, 6 insertions, 4 deletions
diff --git a/fitz/res_store.c b/fitz/res_store.c
index 2a7680e3..cc635052 100644
--- a/fitz/res_store.c
+++ b/fitz/res_store.c
@@ -266,14 +266,15 @@ fz_store_item(fz_context *ctx, void *key, void *val_, unsigned int itemsize, fz_
}
if (existing)
{
+ /* Take a new reference */
+ existing->val->refs++;
fz_unlock(ctx, FZ_LOCK_ALLOC);
fz_free(ctx, item);
return existing->val;
}
}
/* Now we can never fail, bump the ref */
- if (val->refs > 0)
- val->refs++;
+ val->refs++;
/* Regardless of whether it's indexed, it goes into the linked list */
item->next = store->head;
if (item->next)
diff --git a/pdf/pdf_image.c b/pdf/pdf_image.c
index 1702cd30..4cdd374a 100644
--- a/pdf/pdf_image.c
+++ b/pdf/pdf_image.c
@@ -204,7 +204,6 @@ decomp_image_from_stream(fz_context *ctx, fz_stream *stm, pdf_image *image, int
/* We already have a tile. This must have been produced by a
* racing thread. We'll throw away ours and use that one. */
fz_drop_pixmap(ctx, tile);
- fz_free(ctx, key);
tile = existing_tile;
}
}
diff --git a/pdf/pdf_store.c b/pdf/pdf_store.c
index faa81b80..38abe10b 100644
--- a/pdf/pdf_store.c
+++ b/pdf/pdf_store.c
@@ -55,7 +55,9 @@ static fz_store_type pdf_obj_store_type =
void
pdf_store_item(fz_context *ctx, pdf_obj *key, void *val, unsigned int itemsize)
{
- fz_store_item(ctx, key, val, itemsize, &pdf_obj_store_type);
+ void *existing;
+ existing = fz_store_item(ctx, key, val, itemsize, &pdf_obj_store_type);
+ assert(existing == NULL);
}
void *