summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Rasmussen <sebras@gmail.com>2017-09-12 22:26:00 +0800
committerSebastian Rasmussen <sebras@gmail.com>2017-09-13 17:42:00 +0200
commit2707fa9e8e6d17d794330e719dec1b08161fb045 (patch)
tree63b1dfc46e596d0ee6e6f34dec971c62ecbe1f16
parent7c8151b6d42f036644a49245ffd6abf02422ac64 (diff)
downloadmupdf-2707fa9e8e6d17d794330e719dec1b08161fb045.tar.xz
Consistently drop filter chain upon error.
-rw-r--r--include/mupdf/fitz/filter.h2
-rw-r--r--source/fitz/filter-basic.c5
-rw-r--r--source/pdf/pdf-crypt.c22
-rw-r--r--source/pdf/pdf-stream.c111
4 files changed, 91 insertions, 49 deletions
diff --git a/include/mupdf/fitz/filter.h b/include/mupdf/fitz/filter.h
index 58dc3e21..2f73f02f 100644
--- a/include/mupdf/fitz/filter.h
+++ b/include/mupdf/fitz/filter.h
@@ -12,7 +12,7 @@ typedef struct fz_jbig2_globals_s fz_jbig2_globals;
fz_stream *fz_open_copy(fz_context *ctx, fz_stream *chain);
fz_stream *fz_open_null(fz_context *ctx, fz_stream *chain, int len, fz_off_t offset);
fz_stream *fz_open_concat(fz_context *ctx, int max, int pad);
-void fz_concat_push(fz_context *ctx, fz_stream *concat, fz_stream *chain); /* Ownership of chain is passed in */
+void fz_concat_push_drop(fz_context *ctx, fz_stream *concat, fz_stream *chain); /* Ownership of chain is passed in */
fz_stream *fz_open_arc4(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_aesd(fz_context *ctx, fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_a85d(fz_context *ctx, fz_stream *chain);
diff --git a/source/fitz/filter-basic.c b/source/fitz/filter-basic.c
index 5630c37b..959006f9 100644
--- a/source/fitz/filter-basic.c
+++ b/source/fitz/filter-basic.c
@@ -162,12 +162,15 @@ fz_open_concat(fz_context *ctx, int len, int pad)
}
void
-fz_concat_push(fz_context *ctx, fz_stream *concat, fz_stream *chain)
+fz_concat_push_drop(fz_context *ctx, fz_stream *concat, fz_stream *chain)
{
struct concat_filter *state = (struct concat_filter *)concat->state;
if (state->count == state->max)
+ {
+ fz_drop_stream(ctx, chain);
fz_throw(ctx, FZ_ERROR_GENERIC, "Concat filter size exceeded");
+ }
state->chain[state->count++] = chain;
}
diff --git a/source/pdf/pdf-crypt.c b/source/pdf/pdf-crypt.c
index e7f5f7a9..9f3b05e9 100644
--- a/source/pdf/pdf-crypt.c
+++ b/source/pdf/pdf-crypt.c
@@ -1023,12 +1023,26 @@ 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)
{
- if (!pdf_name_eq(ctx, name, PDF_NAME_Identity))
+ 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)
{
- pdf_crypt_filter cf;
- pdf_parse_crypt_filter(ctx, &cf, crypt, name);
- return pdf_open_crypt_imp(ctx, chain, crypt, &cf, num, gen);
+ fz_drop_stream(ctx, chain);
+ fz_rethrow(ctx);
}
+
return chain;
}
diff --git a/source/pdf/pdf-stream.c b/source/pdf/pdf-stream.c
index 34757aa8..baf9f0a6 100644
--- a/source/pdf/pdf-stream.c
+++ b/source/pdf/pdf-stream.c
@@ -155,58 +155,82 @@ 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;
- if (params == NULL)
- params = &local_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 chain;
+ fz_var(chain);
- if (params->type != FZ_IMAGE_RAW)
- return fz_open_image_decomp_stream(ctx, chain, params, NULL);
+ fz_try(ctx)
+ {
+ if (params == NULL)
+ params = &local_params;
- if (pdf_name_eq(ctx, f, PDF_NAME_ASCIIHexDecode) || pdf_name_eq(ctx, f, PDF_NAME_AHx))
- return fz_open_ahxd(ctx, chain);
+ build_compression_params(ctx, f, p, params);
- else if (pdf_name_eq(ctx, f, PDF_NAME_ASCII85Decode) || pdf_name_eq(ctx, f, PDF_NAME_A85))
- return fz_open_a85d(ctx, chain);
+ /* 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 (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 (pdf_is_indirect(ctx, obj))
- globals = pdf_load_jbig2_globals(ctx, doc, obj);
- /* fz_open_jbig2d takes possession of globals */
- return fz_open_jbig2d(ctx, chain, globals);
- }
+ 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_JPXDecode))
- return chain; /* JPX decoding is special cased in the image loading code */
+ 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_Crypt))
- {
- pdf_obj *name;
+ 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);
+ }
- if (!doc->crypt)
+ else if (pdf_name_eq(ctx, f, PDF_NAME_JBIG2Decode))
{
- fz_warn(ctx, "crypt filter in unencrypted document");
- return chain;
+ fz_jbig2_globals *globals = NULL;
+ pdf_obj *obj = pdf_dict_get(ctx, p, PDF_NAME_JBIG2Globals);
+ if (pdf_is_indirect(ctx, obj))
+ globals = pdf_load_jbig2_globals(ctx, doc, obj);
+ tmp = chain;
+ chain = NULL;
+ chain = fz_open_jbig2d(ctx, tmp, globals);
}
- 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 if (pdf_name_eq(ctx, f, PDF_NAME_JPXDecode))
+ break; /* JPX decoding is special cased in the image loading code */
- return chain;
+ else if (pdf_name_eq(ctx, f, PDF_NAME_Crypt))
+ {
+ 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);
+ }
+ }
+ }
+ else
+ fz_warn(ctx, "unknown filter name (%s)", pdf_to_name(ctx, f));
+ }
+ fz_catch(ctx)
+ {
+ fz_drop_stream(ctx, chain);
+ fz_rethrow(ctx);
}
- fz_warn(ctx, "unknown filter name (%s)", pdf_to_name(ctx, f));
return chain;
}
@@ -635,14 +659,15 @@ pdf_open_object_array(fz_context *ctx, pdf_document *doc, pdf_obj *list)
{
pdf_obj *obj = pdf_array_get(ctx, list, i);
fz_try(ctx)
- {
- fz_concat_push(ctx, stm, pdf_open_stream(ctx, obj));
- }
+ fz_concat_push_drop(ctx, stm, pdf_open_stream(ctx, obj));
fz_catch(ctx)
{
- fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
+ if (fz_caught(ctx) == FZ_ERROR_TRYLATER)
+ {
+ fz_drop_stream(ctx, stm);
+ fz_rethrow(ctx);
+ }
fz_warn(ctx, "cannot load content stream part %d/%d", i + 1, n);
- continue;
}
}