diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-07-01 17:33:30 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-07-06 15:45:16 +0200 |
commit | 5983a7de30e84af04dab3c7835c04dba493391fa (patch) | |
tree | 67381a4cb938d86b88c116739bcc54a0bcc9de23 /source/pdf/pdf-xref.c | |
parent | 255776a778b519183d6935ff0cb4b766644fa830 (diff) | |
download | mupdf-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.c | 41 |
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; } |