summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-01-17 13:40:17 +0000
committerRobin Watts <robin.watts@artifex.com>2014-01-17 13:48:01 +0000
commit776ee05584156f6737ec7603b2f2f68d3a301bab (patch)
tree458ddbbc304f320034459da14f77f1f1472bd3e0
parent207c58162fe0bece0412325d3dfefe3bd12528ba (diff)
downloadmupdf-776ee05584156f6737ec7603b2f2f68d3a301bab.tar.xz
Bug 694896: Ensure that repairs don't lose trailer dict.
When we find certain classes of flaw in the file while attempting to read an object, we trigger an automatic repair of the file. This leaves almost all objects unchanged; the sole exception is that of the trailer object (and its sub objects) which can get dropped and recreated. To avoid leaving people holding handles to objects within the trailer dict high and dry, we introduce a 'pre_repair_trailer' object to each xref entry. On a repair, we copy the existing trailer object to this. As we only ever repair once, this is safe. The only known place where this is a problem is when setting up the pdf_crypt for a document; we adapt the code here to allow for potential problems. The example file that shows this up is: 048d14d2f5f0ae31e9a2cde0be66f16a_asan_heap-uaf_86d4ed_3961_3661.pdf Thanks to Mateusz Jurczyk and Gynvael Coldwind of the Google Security Team for providing the fuzzing files.
-rw-r--r--include/mupdf/pdf/xref.h1
-rw-r--r--source/pdf/pdf-xref.c9
2 files changed, 9 insertions, 1 deletions
diff --git a/include/mupdf/pdf/xref.h b/include/mupdf/pdf/xref.h
index de53da7c..f9e1657f 100644
--- a/include/mupdf/pdf/xref.h
+++ b/include/mupdf/pdf/xref.h
@@ -47,6 +47,7 @@ struct pdf_xref_s
int len;
pdf_xref_entry *table;
pdf_obj *trailer;
+ pdf_obj *pre_repair_trailer;
};
void pdf_cache_object(pdf_document *doc, int num, int gen);
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index 735f2e2e..881826b9 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -41,6 +41,7 @@ static void pdf_free_xref_sections(pdf_document *doc)
}
fz_free(ctx, xref->table);
+ pdf_drop_obj(xref->pre_repair_trailer);
pdf_drop_obj(xref->trailer);
}
@@ -76,6 +77,7 @@ static void pdf_populate_next_xref_level(pdf_document *doc)
xref->len = 0;
xref->table = NULL;
xref->trailer = NULL;
+ xref->pre_repair_trailer = NULL;
}
pdf_obj *pdf_trailer(pdf_document *doc)
@@ -90,7 +92,11 @@ void pdf_set_populating_xref_trailer(pdf_document *doc, pdf_obj *trailer)
{
/* Update the trailer of the xref section being populated */
pdf_xref *xref = &doc->xref_sections[doc->num_xref_sections - 1];
- pdf_drop_obj(xref->trailer);
+ if (xref->trailer)
+ {
+ pdf_drop_obj(xref->pre_repair_trailer);
+ xref->pre_repair_trailer = xref->trailer;
+ }
xref->trailer = pdf_keep_obj(trailer);
}
@@ -186,6 +192,7 @@ static void ensure_incremental_xref(pdf_document *doc)
/* xref->len is already correct */
xref->table = new_table;
xref->trailer = trailer;
+ xref->pre_repair_trailer = NULL;
doc->num_xref_sections++;
doc->xref_altered = 1;
}