From ef3cfb2a49b5be82d56d783f505319754dc65cb8 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 28 Mar 2018 15:17:27 +0200 Subject: Don't implicitly drop in fz_open_* chained filters. --- source/pdf/pdf-crypt.c | 26 +---- source/pdf/pdf-form.c | 2 +- source/pdf/pdf-stream.c | 287 ++++++++++++++++++++---------------------------- 3 files changed, 128 insertions(+), 187 deletions(-) (limited to 'source/pdf') diff --git a/source/pdf/pdf-crypt.c b/source/pdf/pdf-crypt.c index 2e31f356..1056b4fe 100644 --- a/source/pdf/pdf-crypt.c +++ b/source/pdf/pdf-crypt.c @@ -1023,7 +1023,7 @@ pdf_open_crypt_imp(fz_context *ctx, fz_stream *chain, pdf_crypt *crypt, pdf_cryp if (stmf->method == PDF_CRYPT_AESV2 || stmf->method == PDF_CRYPT_AESV3) return fz_open_aesd(ctx, chain, key, len); - return chain; + return fz_keep_stream(ctx, chain); } fz_stream * @@ -1035,27 +1035,13 @@ pdf_open_crypt(fz_context *ctx, fz_stream *chain, pdf_crypt *crypt, int num, int fz_stream * pdf_open_crypt_with_filter(fz_context *ctx, fz_stream *chain, pdf_crypt *crypt, pdf_obj *name, int num, int gen) { - fz_var(chain); - - fz_try(ctx) - { - if (!pdf_name_eq(ctx, name, PDF_NAME_Identity)) - { - pdf_crypt_filter cf; - fz_stream *tmp; - pdf_parse_crypt_filter(ctx, &cf, crypt, name); - tmp = chain; - chain = NULL; - chain = pdf_open_crypt_imp(ctx, tmp, crypt, &cf, num, gen); - } - } - fz_catch(ctx) + if (!pdf_name_eq(ctx, name, PDF_NAME_Identity)) { - fz_drop_stream(ctx, chain); - fz_rethrow(ctx); + pdf_crypt_filter cf; + pdf_parse_crypt_filter(ctx, &cf, crypt, name); + return pdf_open_crypt_imp(ctx, chain, crypt, &cf, num, gen); } - - return chain; + return fz_keep_stream(ctx, chain); } void diff --git a/source/pdf/pdf-form.c b/source/pdf/pdf-form.c index f3d4e3c6..6c2e0434 100644 --- a/source/pdf/pdf-form.c +++ b/source/pdf/pdf-form.c @@ -1292,7 +1292,7 @@ fz_stream *pdf_signature_widget_hash_bytes(fz_context *ctx, pdf_document *doc, p pdf_signature_widget_byte_range(ctx, doc, widget, byte_range); } - bytes = fz_open_null_n(ctx, fz_keep_stream(ctx, doc->file), byte_range, byte_range_len); + bytes = fz_open_null_n(ctx, doc->file, byte_range, byte_range_len); } fz_always(ctx) { diff --git a/source/pdf/pdf-stream.c b/source/pdf/pdf-stream.c index 34ffe7af..379ed504 100644 --- a/source/pdf/pdf-stream.c +++ b/source/pdf/pdf-stream.c @@ -158,116 +158,93 @@ static fz_stream * build_filter(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *f, pdf_obj *p, int num, int gen, fz_compression_params *params) { fz_compression_params local_params; - fz_stream *tmp; - fz_var(chain); + if (params == NULL) + params = &local_params; - fz_try(ctx) - { - if (params == NULL) - params = &local_params; + build_compression_params(ctx, f, p, params); - build_compression_params(ctx, f, p, params); + /* If we were using params we were passed in, and we successfully + * recognised the image type, we can use the existing filter and + * shortstop here. */ + if (params != &local_params && params->type != FZ_IMAGE_RAW) + return fz_keep_stream(ctx, chain); /* nothing to do */ - /* If we were using params we were passed in, and we successfully - * recognised the image type, we can use the existing filter and - * shortstop here. */ - if (params != &local_params && params->type != FZ_IMAGE_RAW) - break; /* nothing to do */ + else if (params->type != FZ_IMAGE_RAW) + return fz_open_image_decomp_stream(ctx, chain, params, NULL); - else if (params->type != FZ_IMAGE_RAW) - { - tmp = chain; - chain = NULL; - chain = fz_open_image_decomp_stream(ctx, tmp, params, NULL); - } + else if (pdf_name_eq(ctx, f, PDF_NAME_ASCIIHexDecode) || pdf_name_eq(ctx, f, PDF_NAME_AHx)) + return fz_open_ahxd(ctx, chain); - else if (pdf_name_eq(ctx, f, PDF_NAME_ASCIIHexDecode) || pdf_name_eq(ctx, f, PDF_NAME_AHx)) - { - tmp = chain; - chain = NULL; - chain = fz_open_ahxd(ctx, tmp); - } - - else if (pdf_name_eq(ctx, f, PDF_NAME_ASCII85Decode) || pdf_name_eq(ctx, f, PDF_NAME_A85)) - { - tmp = chain; - chain = NULL; - chain = fz_open_a85d(ctx, tmp); - } + else if (pdf_name_eq(ctx, f, PDF_NAME_ASCII85Decode) || pdf_name_eq(ctx, f, PDF_NAME_A85)) + return fz_open_a85d(ctx, chain); - else if (pdf_name_eq(ctx, f, PDF_NAME_JBIG2Decode)) + else if (pdf_name_eq(ctx, f, PDF_NAME_JBIG2Decode)) + { + fz_jbig2_globals *globals = NULL; + pdf_obj *obj = pdf_dict_get(ctx, p, PDF_NAME_JBIG2Globals); + if (obj) { - fz_jbig2_globals *globals = NULL; - pdf_obj *obj = pdf_dict_get(ctx, p, PDF_NAME_JBIG2Globals); - if (obj) - { - if (!pdf_is_stream(ctx, obj)) - fz_warn(ctx, "jbig2 globals is not a stream, skipping globals"); - else - globals = pdf_load_jbig2_globals(ctx, doc, obj); - } - tmp = chain; - chain = NULL; - chain = fz_open_jbig2d(ctx, tmp, globals); + if (!pdf_is_stream(ctx, obj)) + fz_warn(ctx, "jbig2 globals is not a stream, skipping globals"); + else + globals = pdf_load_jbig2_globals(ctx, doc, obj); } + return fz_open_jbig2d(ctx, chain, globals); /* takes ownership of jbig2_globals */ + } - else if (pdf_name_eq(ctx, f, PDF_NAME_JPXDecode)) - break; /* JPX decoding is special cased in the image loading code */ + else if (pdf_name_eq(ctx, f, PDF_NAME_JPXDecode)) + return fz_keep_stream(ctx, chain); /* JPX decoding is special cased in the image loading code */ - else if (pdf_name_eq(ctx, f, PDF_NAME_Crypt)) + else if (pdf_name_eq(ctx, f, PDF_NAME_Crypt)) + { + if (!doc->crypt) + fz_warn(ctx, "crypt filter in unencrypted document"); + else { - if (!doc->crypt) - fz_warn(ctx, "crypt filter in unencrypted document"); - else - { - pdf_obj *name = pdf_dict_get(ctx, p, PDF_NAME_Name); - if (pdf_is_name(ctx, name)) - { - tmp = chain; - chain = NULL; - chain = pdf_open_crypt_with_filter(ctx, tmp, doc->crypt, name, num, gen); - } - } + pdf_obj *name = pdf_dict_get(ctx, p, PDF_NAME_Name); + if (pdf_is_name(ctx, name)) + return pdf_open_crypt_with_filter(ctx, chain, doc->crypt, name, num, gen); } - else - fz_warn(ctx, "unknown filter name (%s)", pdf_to_name(ctx, f)); } + + else + fz_warn(ctx, "unknown filter name (%s)", pdf_to_name(ctx, f)); + + return fz_keep_stream(ctx, chain); +} + +/* Build filter, and assume ownership of chain */ +static fz_stream * +build_filter_drop(fz_context *ctx, fz_stream *tail, pdf_document *doc, pdf_obj *f, pdf_obj *p, int num, int gen, fz_compression_params *params) +{ + fz_stream *head; + fz_try(ctx) + head = build_filter(ctx, tail, doc, f, p, num, gen, params); + fz_always(ctx) + fz_drop_stream(ctx, tail); fz_catch(ctx) - { - fz_drop_stream(ctx, chain); fz_rethrow(ctx); - } - - return chain; + return head; } /* * Build a chain of filters given filter names and param dicts. - * If head is given, start filter chain with it. - * Assume ownership of head. + * If chain is given, start filter chain with it. + * Assume ownership of chain. */ static fz_stream * -build_filter_chain(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *fs, pdf_obj *ps, int num, int gen, fz_compression_params *params) +build_filter_chain_drop(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *fs, pdf_obj *ps, int num, int gen, fz_compression_params *params) { - pdf_obj *f; - pdf_obj *p; - int i, n; - fz_var(chain); - fz_try(ctx) { - n = pdf_array_len(ctx, fs); + int i, n = pdf_array_len(ctx, fs); for (i = 0; i < n; i++) { - fz_stream *chain2; - - f = pdf_array_get(ctx, fs, i); - p = pdf_array_get(ctx, ps, i); - chain2 = chain; - chain = NULL; - chain = build_filter(ctx, chain2, doc, f, p, num, gen, (i == n-1 ? params : NULL)); + pdf_obj *f = pdf_array_get(ctx, fs, i); + pdf_obj *p = pdf_array_get(ctx, ps, i); + chain = build_filter_drop(ctx, chain, doc, f, p, num, gen, (i == n-1 ? params : NULL)); } } fz_catch(ctx) @@ -275,10 +252,15 @@ build_filter_chain(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj fz_drop_stream(ctx, chain); fz_rethrow(ctx); } - return chain; } +static fz_stream * +build_filter_chain(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *fs, pdf_obj *ps, int num, int gen, fz_compression_params *params) +{ + return build_filter_chain_drop(ctx, fz_keep_stream(ctx, chain), doc, fs, ps, num, gen, params); +} + /* * Build a filter for reading raw stream data. * This is a null filter to constrain reading to the stream length (and to @@ -288,10 +270,10 @@ build_filter_chain(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj * orig_num and orig_gen are used purely to seed the encryption. */ static fz_stream * -pdf_open_raw_filter(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_obj *stmobj, int num, int *orig_num, int *orig_gen, int64_t offset) +pdf_open_raw_filter(fz_context *ctx, fz_stream *file_stm, pdf_document *doc, pdf_obj *stmobj, int num, int *orig_num, int *orig_gen, int64_t offset) { pdf_xref_entry *x = NULL; - fz_stream *chain2; + fz_stream *null_stm, *crypt_stm; int hascrypt; int len; @@ -311,33 +293,20 @@ pdf_open_raw_filter(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_ob *orig_gen = 0; } - chain = fz_keep_stream(ctx, chain); - - fz_var(chain); - - fz_try(ctx) + hascrypt = pdf_stream_has_crypt(ctx, stmobj); + len = pdf_to_int(ctx, pdf_dict_get(ctx, stmobj, PDF_NAME_Length)); + null_stm = fz_open_null(ctx, file_stm, len, offset); + if (doc->crypt && !hascrypt) { - len = pdf_to_int(ctx, pdf_dict_get(ctx, stmobj, PDF_NAME_Length)); - - chain2 = chain; - chain = NULL; - chain = fz_open_null(ctx, chain2, len, offset); - - hascrypt = pdf_stream_has_crypt(ctx, stmobj); - if (doc->crypt && !hascrypt) - { - chain2 = chain; - chain = NULL; - chain = pdf_open_crypt(ctx, chain2, doc->crypt, *orig_num, *orig_gen); - } - } - fz_catch(ctx) - { - fz_drop_stream(ctx, chain); - fz_rethrow(ctx); + fz_try(ctx) + crypt_stm = pdf_open_crypt(ctx, null_stm, doc->crypt, *orig_num, *orig_gen); + fz_always(ctx) + fz_drop_stream(ctx, null_stm); + fz_catch(ctx) + fz_rethrow(ctx); + return crypt_stm; } - - return chain; + return null_stm; } /* @@ -345,41 +314,29 @@ pdf_open_raw_filter(fz_context *ctx, fz_stream *chain, pdf_document *doc, pdf_ob * to stream length and decrypting. */ static fz_stream * -pdf_open_filter(fz_context *ctx, pdf_document *doc, fz_stream *chain, pdf_obj *stmobj, int num, int64_t offset, fz_compression_params *imparams) +pdf_open_filter(fz_context *ctx, pdf_document *doc, fz_stream *file_stm, pdf_obj *stmobj, int num, int64_t offset, fz_compression_params *imparams) { - pdf_obj *filters; - pdf_obj *params; + pdf_obj *filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F); + pdf_obj *params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP); int orig_num, orig_gen; + fz_stream *rstm, *fstm; - filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F); - params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP); - - chain = pdf_open_raw_filter(ctx, chain, doc, stmobj, num, &orig_num, &orig_gen, offset); - - fz_var(chain); - + rstm = pdf_open_raw_filter(ctx, file_stm, doc, stmobj, num, &orig_num, &orig_gen, offset); fz_try(ctx) { if (pdf_is_name(ctx, filters)) - { - fz_stream *chain2 = chain; - chain = NULL; - chain = build_filter(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams); - } + fstm = build_filter(ctx, rstm, doc, filters, params, orig_num, orig_gen, imparams); else if (pdf_array_len(ctx, filters) > 0) - { - fz_stream *chain2 = chain; - chain = NULL; - chain = build_filter_chain(ctx, chain2, doc, filters, params, orig_num, orig_gen, imparams); - } + fstm = build_filter_chain(ctx, rstm, doc, filters, params, orig_num, orig_gen, imparams); + else + fstm = fz_keep_stream(ctx, rstm); } + fz_always(ctx) + fz_drop_stream(ctx, rstm); fz_catch(ctx) - { - fz_drop_stream(ctx, chain); fz_rethrow(ctx); - } - return chain; + return fstm; } /* @@ -387,54 +344,52 @@ pdf_open_filter(fz_context *ctx, pdf_document *doc, fz_stream *chain, pdf_obj *s * constraining to stream length, and without decryption. */ fz_stream * -pdf_open_inline_stream(fz_context *ctx, pdf_document *doc, pdf_obj *stmobj, int length, fz_stream *chain, fz_compression_params *imparams) +pdf_open_inline_stream(fz_context *ctx, pdf_document *doc, pdf_obj *stmobj, int length, fz_stream *file_stm, fz_compression_params *imparams) { - pdf_obj *filters; - pdf_obj *params; - int64_t offset; - - filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F); - params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP); - - /* don't close chain when we close this filter */ - fz_keep_stream(ctx, chain); + pdf_obj *filters = pdf_dict_geta(ctx, stmobj, PDF_NAME_Filter, PDF_NAME_F); + pdf_obj *params = pdf_dict_geta(ctx, stmobj, PDF_NAME_DecodeParms, PDF_NAME_DP); if (pdf_is_name(ctx, filters)) - return build_filter(ctx, chain, doc, filters, params, 0, 0, imparams); - if (pdf_array_len(ctx, filters) > 0) - return build_filter_chain(ctx, chain, doc, filters, params, 0, 0, imparams); + return build_filter(ctx, file_stm, doc, filters, params, 0, 0, imparams); + else if (pdf_array_len(ctx, filters) > 0) + return build_filter_chain(ctx, file_stm, doc, filters, params, 0, 0, imparams); if (imparams) imparams->type = FZ_IMAGE_RAW; - - fz_try(ctx) - offset = fz_tell(ctx, chain); - fz_catch(ctx) - { - fz_drop_stream(ctx, chain); - fz_rethrow(ctx); - } - - return fz_open_null(ctx, chain, length, offset); + return fz_open_null(ctx, file_stm, length, fz_tell(ctx, file_stm)); } void -pdf_load_compressed_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int length, fz_stream *stm, int indexed, fz_compressed_image *image) +pdf_load_compressed_inline_image(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int length, fz_stream *file_stm, int indexed, fz_compressed_image *image) { - fz_compressed_buffer *bc = fz_malloc_struct(ctx, fz_compressed_buffer); + fz_stream *istm, *leech, *decomp; + fz_pixmap *pixmap; + fz_compressed_buffer *bc; + int dummy_l2factor = 0; + fz_var(istm); + fz_var(leech); + fz_var(decomp); + fz_var(pixmap); + + bc = fz_malloc_struct(ctx, fz_compressed_buffer); fz_try(ctx) { - int dummy_l2factor = 0; bc->buffer = fz_new_buffer(ctx, 1024); - - stm = pdf_open_inline_stream(ctx, doc, dict, length, stm, &bc->params); - stm = fz_open_leecher(ctx, stm, bc->buffer); - stm = fz_open_image_decomp_stream(ctx, stm, &bc->params, &dummy_l2factor); - - fz_set_compressed_image_tile(ctx, image, fz_decomp_image_from_stream(ctx, stm, image, NULL, indexed, 0)); + istm = pdf_open_inline_stream(ctx, doc, dict, length, file_stm, &bc->params); + leech = fz_open_leecher(ctx, istm, bc->buffer); + decomp = fz_open_image_decomp_stream(ctx, leech, &bc->params, &dummy_l2factor); + pixmap = fz_decomp_image_from_stream(ctx, leech, image, NULL, indexed, 0); + fz_set_compressed_image_tile(ctx, image, pixmap); fz_set_compressed_image_buffer(ctx, image, bc); } + fz_always(ctx) + { + fz_drop_stream(ctx, istm); + fz_drop_stream(ctx, leech); + fz_drop_stream(ctx, decomp); + fz_drop_pixmap(ctx, pixmap); + } fz_catch(ctx) { fz_drop_compressed_buffer(ctx, bc); -- cgit v1.2.3