summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-xref.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-07-01 17:33:30 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-07-06 15:45:16 +0200
commit5983a7de30e84af04dab3c7835c04dba493391fa (patch)
tree67381a4cb938d86b88c116739bcc54a0bcc9de23 /source/pdf/pdf-xref.c
parent255776a778b519183d6935ff0cb4b766644fa830 (diff)
downloadmupdf-5983a7de30e84af04dab3c7835c04dba493391fa.tar.xz
Fix garbage collection and page grafting for indirect reference chains.
The mark & sweep pass of garbage collection, and resolving indirect objects when grafting objects was following the full chain of indirect references. In the unusual case where a numbered object is itself only an indirect reference to another object, this intermediate numbered object would be missed both when marking for garbage collection, and when copying objects for grafting. Add a function to resolve only one step for these two uses. The following is an example of a file that would break during garbage collection if we follow full indirect reference chains: %PDF-1.3 1 0 obj <</Type/Catalog /Foo[2 0 R 3 0 R]>> endobj 2 0 obj 4 0 R endobj 3 0 obj 5 0 R endobj 4 0 obj <</Length 1>> stream A endstream endobj 5 0 obj <</Length 1>> stream B endstream endobj
Diffstat (limited to 'source/pdf/pdf-xref.c')
-rw-r--r--source/pdf/pdf-xref.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index 54dbc4b6..19b1f4f7 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -2097,25 +2097,14 @@ pdf_load_object(fz_context *ctx, pdf_document *doc, int num)
pdf_obj *
pdf_resolve_indirect(fz_context *ctx, pdf_obj *ref)
{
- int sanity = 10;
- int num;
- pdf_xref_entry *entry;
-
- while (pdf_is_indirect(ctx, ref))
+ if (pdf_is_indirect(ctx, ref))
{
- pdf_document *doc;
-
- if (--sanity == 0)
- {
- fz_warn(ctx, "too many indirections (possible indirection cycle involving %d 0 R)", num);
- return NULL;
- }
+ pdf_document *doc = pdf_get_indirect_document(ctx, ref);
+ int num = pdf_to_num(ctx, ref);
+ pdf_xref_entry *entry;
- doc = pdf_get_indirect_document(ctx, ref);
if (!doc)
return NULL;
- num = pdf_to_num(ctx, ref);
-
if (num <= 0)
{
fz_warn(ctx, "invalid indirect reference (%d 0 R)", num);
@@ -2123,9 +2112,7 @@ pdf_resolve_indirect(fz_context *ctx, pdf_obj *ref)
}
fz_try(ctx)
- {
entry = pdf_cache_object(ctx, doc, num);
- }
fz_catch(ctx)
{
fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
@@ -2133,10 +2120,26 @@ pdf_resolve_indirect(fz_context *ctx, pdf_obj *ref)
return NULL;
}
- if (entry->obj == NULL)
- return NULL;
ref = entry->obj;
}
+ return ref;
+}
+
+pdf_obj *
+pdf_resolve_indirect_chain(fz_context *ctx, pdf_obj *ref)
+{
+ int sanity = 10;
+
+ while (pdf_is_indirect(ctx, ref))
+ {
+ if (--sanity == 0)
+ {
+ fz_warn(ctx, "too many indirections (possible indirection cycle involving %d 0 R)", pdf_to_num(ctx, ref));
+ return NULL;
+ }
+
+ ref = pdf_resolve_indirect(ctx, ref);
+ }
return ref;
}