diff options
Diffstat (limited to 'source/pdf')
-rw-r--r-- | source/pdf/pdf-graft.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/source/pdf/pdf-graft.c b/source/pdf/pdf-graft.c index bbe5e17b..758addde 100644 --- a/source/pdf/pdf-graft.c +++ b/source/pdf/pdf-graft.c @@ -1,5 +1,13 @@ #include "mupdf/pdf.h" +struct pdf_graft_map_s +{ + int refs; + int len; + pdf_document *src; + int *dst_from_src; +}; + pdf_graft_map * pdf_new_graft_map(fz_context *ctx, pdf_document *src) { @@ -9,6 +17,7 @@ pdf_new_graft_map(fz_context *ctx, pdf_document *src) fz_try(ctx) { + map->src = (pdf_document*) fz_keep_document(ctx, (fz_document*)src); map->len = pdf_xref_len(ctx, src); map->dst_from_src = fz_calloc(ctx, map->len, sizeof(int)); } @@ -34,6 +43,7 @@ pdf_drop_graft_map(fz_context *ctx, pdf_graft_map *map) { if (map && --map->refs == 0) { + fz_drop_document(ctx, (fz_document*)map->src); fz_free(ctx, map->dst_from_src); fz_free(ctx, map); } @@ -50,15 +60,32 @@ pdf_graft_object(fz_context *ctx, pdf_document *dst, pdf_document *src, pdf_obj pdf_obj *ref = NULL; fz_buffer *buffer = NULL; pdf_graft_map *drop_map = NULL; + pdf_document *bound; int new_num, src_num, len, i; + /* Primitive objects are not bound to a document, so can be re-used as is. */ + if (!pdf_is_indirect(ctx, obj_ref) && !pdf_is_dict(ctx, obj_ref) && !pdf_is_array(ctx, obj_ref)) + return pdf_keep_obj(ctx, obj_ref); + if (map == NULL) drop_map = map = pdf_new_graft_map(ctx, src); + else if (src != map->src) + fz_throw(ctx, FZ_ERROR_GENERIC, "graft map does not belong to the source document"); + + bound = pdf_get_bound_document(ctx, obj_ref); + if (bound && bound != src) + fz_throw(ctx, FZ_ERROR_GENERIC, "grafted object does not belong to the source document"); if (pdf_is_indirect(ctx, obj_ref)) { src_num = pdf_to_num(ctx, obj_ref); + if (src_num < 1 || src_num >= map->len) + { + pdf_drop_graft_map(ctx, drop_map); + fz_throw(ctx, FZ_ERROR_GENERIC, "source object number out of range"); + } + /* Check if we have done this one. If yes, then drop map (if allocated) * and return our indirect ref */ if (map->dst_from_src[src_num] != 0) |