summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2015-04-03 16:30:19 +0100
committerRobin Watts <robin.watts@artifex.com>2015-04-03 16:37:18 +0100
commitd4ae4095cc1121b9a7a5ca9a444adaa08906e846 (patch)
treee75ad74124830f429df2a8200ce37be66f75c2ea /source
parent57121ca1cc81b502f3a4a0f79759404d0fb0d846 (diff)
downloadmupdf-d4ae4095cc1121b9a7a5ca9a444adaa08906e846.tar.xz
Bug 694713: Avoid assert when using pdf_page_write
When writing a pdf page, we pass page->contents to pdf_new_pdf_device. This object is assumed to be a dictionary (stream) that can be updated with the Length and stream contents once the page writing process has completed. When we are rewriting a pdf page however, this can go wrong; page->contents can be an array of objects. Not only this, in general it would be possible for several pages to share the same page contents (or maybe some of the elements of a page contents array). Updating one page should not update the others. We therefore update pdf_page_write to always create a new page->contents object and use that. Thanks to Michael Cadilhac for spotting the basic problem here.
Diffstat (limited to 'source')
-rw-r--r--source/pdf/pdf-device.c33
-rw-r--r--source/pdf/pdf-page.c5
2 files changed, 23 insertions, 15 deletions
diff --git a/source/pdf/pdf-device.c b/source/pdf/pdf-device.c
index e3b63dc5..8b99c4f0 100644
--- a/source/pdf/pdf-device.c
+++ b/source/pdf/pdf-device.c
@@ -1350,6 +1350,8 @@ fz_device *pdf_page_write(fz_context *ctx, pdf_document *doc, pdf_page *page)
{
pdf_obj *resources = pdf_dict_get(ctx, page->me, PDF_NAME_Resources);
fz_matrix ctm;
+ pdf_obj *obj;
+
fz_pre_translate(fz_scale(&ctm, 1, -1), 0, page->mediabox.y0-page->mediabox.y1);
if (resources == NULL)
@@ -1358,22 +1360,23 @@ fz_device *pdf_page_write(fz_context *ctx, pdf_document *doc, pdf_page *page)
pdf_dict_put_drop(ctx, page->me, PDF_NAME_Resources, resources);
}
- if (page->contents == NULL)
+ /* We always make a new object for page->contents here, in case
+ * the existing one is an array, or is shared. */
+ obj = pdf_new_dict(ctx, doc, 0);
+ fz_try(ctx)
{
- pdf_obj *obj = pdf_new_dict(ctx, doc, 0);
- fz_try(ctx)
- {
- page->contents = pdf_new_ref(ctx, doc, obj);
- pdf_dict_put(ctx, page->me, PDF_NAME_Contents, page->contents);
- }
- fz_always(ctx)
- {
- pdf_drop_obj(ctx, obj);
- }
- fz_catch(ctx)
- {
- fz_rethrow(ctx);
- }
+ pdf_obj *new_contents = pdf_new_ref(ctx, doc, obj);
+ pdf_dict_put(ctx, page->me, PDF_NAME_Contents, new_contents);
+ pdf_drop_obj(ctx, page->contents);
+ page->contents = new_contents;
+ }
+ fz_always(ctx)
+ {
+ pdf_drop_obj(ctx, obj);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
}
return pdf_new_pdf_device(ctx, doc, page->contents, resources, &ctm, NULL);
diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c
index 588ba093..9d5eb863 100644
--- a/source/pdf/pdf-page.c
+++ b/source/pdf/pdf-page.c
@@ -420,6 +420,11 @@ pdf_drop_page_imp(fz_context *ctx, pdf_page *page)
fz_drop_document(ctx, &page->doc->super);
}
+void pdf_drop_page(fz_context *ctx, pdf_page *page)
+{
+ fz_drop_page(ctx, &page->super);
+}
+
pdf_page *
pdf_load_page(fz_context *ctx, pdf_document *doc, int number)
{