summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2012-05-04 15:10:56 +0100
committerRobin Watts <robin.watts@artifex.com>2012-05-08 15:14:56 +0100
commit2433a4d16d114a0576e6a4ff9ca61ae4f29fdda0 (patch)
tree6b181530e563c9445116252cf5945804e934161a
parent6c5d7cb79054f2bea8c109b143e9d453fb2ca1bc (diff)
downloadmupdf-2433a4d16d114a0576e6a4ff9ca61ae4f29fdda0.tar.xz
Update seeking behaviour of null streams.
In order to (hopefully) allow page content streams to be interpreted without having to preload them all into memory before we run them, we need to make the stream reading code cope with other users moving the stream pointer. For example: Consider the case where we are midway through interpreting a contents stream, and us hitting an operator that requires something to be read from Resources. This will move the underlying stream file pointer, and cause the contents stream to read incorrectly when control returns to the interpreter. The solution to this seems to be fairly simple; whenever we create a filter out of the file stream, the existing code puts in a 'null' filter first, to enforce a length limit on the stream. This null filter already does most of the work we need it to, in that by it being there, the buffering of data is done in the null filter rather than in the underlying stream layer. All we need to do is to keep track of where in the underlying stream the null filter thinks it is, and ensure that it seeks there before each read (in case anyone else has moved it). We move the setting of the offset to be explicit in the pdf_open_filter (and associated) call(s), rather than requiring fz_seeks elsewhere.
-rw-r--r--fitz/filt_basic.c10
-rw-r--r--fitz/fitz-internal.h2
-rw-r--r--pdf/pdf_stream.c24
3 files changed, 17 insertions, 19 deletions
diff --git a/fitz/filt_basic.c b/fitz/filt_basic.c
index 09d63402..ac6a5903 100644
--- a/fitz/filt_basic.c
+++ b/fitz/filt_basic.c
@@ -14,6 +14,7 @@ struct null_filter
{
fz_stream *chain;
int remain;
+ int pos;
};
static int
@@ -21,8 +22,12 @@ read_null(fz_stream *stm, unsigned char *buf, int len)
{
struct null_filter *state = stm->state;
int amount = MIN(len, state->remain);
- int n = fz_read(state->chain, buf, amount);
+ int n;
+
+ fz_seek(state->chain, state->pos, 0);
+ n = fz_read(state->chain, buf, amount);
state->remain -= n;
+ state->pos += n;
return n;
}
@@ -36,7 +41,7 @@ close_null(fz_context *ctx, void *state_)
}
fz_stream *
-fz_open_null(fz_stream *chain, int len)
+fz_open_null(fz_stream *chain, int len, int offset)
{
struct null_filter *state;
fz_context *ctx = chain->ctx;
@@ -46,6 +51,7 @@ fz_open_null(fz_stream *chain, int len)
state = fz_malloc_struct(ctx, struct null_filter);
state->chain = chain;
state->remain = len;
+ state->pos = offset;
}
fz_catch(ctx)
{
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 1e54c900..197d0279 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -520,7 +520,7 @@ static inline int fz_is_eof_bits(fz_stream *stm)
*/
fz_stream *fz_open_copy(fz_stream *chain);
-fz_stream *fz_open_null(fz_stream *chain, int len);
+fz_stream *fz_open_null(fz_stream *chain, int len, int offset);
fz_stream *fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen);
fz_stream *fz_open_a85d(fz_stream *chain);
diff --git a/pdf/pdf_stream.c b/pdf/pdf_stream.c
index 84f966ec..5338d81c 100644
--- a/pdf/pdf_stream.c
+++ b/pdf/pdf_stream.c
@@ -226,7 +226,7 @@ build_filter_chain(fz_stream *chain, pdf_document *xref, pdf_obj *fs, pdf_obj *p
* stream length, followed by a decryption filter.
*/
static fz_stream *
-pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen)
+pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, int offset)
{
int hascrypt;
int len;
@@ -236,7 +236,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int n
fz_keep_stream(chain);
len = pdf_to_int(pdf_dict_gets(stmobj, "Length"));
- chain = fz_open_null(chain, len);
+ chain = fz_open_null(chain, len, offset);
fz_try(ctx)
{
@@ -258,7 +258,7 @@ pdf_open_raw_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int n
* to stream length and decrypting.
*/
static fz_stream *
-pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, pdf_image_params *imparams)
+pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num, int gen, int offset, pdf_image_params *imparams)
{
pdf_obj *filters;
pdf_obj *params;
@@ -266,7 +266,7 @@ pdf_open_filter(fz_stream *chain, pdf_document *xref, pdf_obj *stmobj, int num,
filters = pdf_dict_getsa(stmobj, "Filter", "F");
params = pdf_dict_getsa(stmobj, "DecodeParms", "DP");
- chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen);
+ chain = pdf_open_raw_filter(chain, xref, stmobj, num, gen, offset);
if (pdf_is_name(filters))
chain = build_filter(chain, xref, filters, params, num, gen, imparams);
@@ -298,7 +298,7 @@ pdf_open_inline_stream(pdf_document *xref, pdf_obj *stmobj, int length, fz_strea
if (pdf_array_len(filters) > 0)
return build_filter_chain(chain, xref, filters, params, 0, 0, imparams);
- return fz_open_null(chain, length);
+ return fz_open_null(chain, length, fz_tell(chain));
}
/*
@@ -324,9 +324,8 @@ pdf_open_raw_stream(pdf_document *xref, int num, int gen)
if (x->stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_raw_filter(xref->file, xref, x->obj, num, gen);
+ stm = pdf_open_raw_filter(xref->file, xref, x->obj, num, gen, x->stm_ofs);
fz_lock_stream(stm);
- fz_seek(xref->file, x->stm_ofs, 0);
return stm;
}
@@ -345,7 +344,6 @@ fz_stream *
pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *params)
{
pdf_xref_entry *x;
- fz_stream *stm;
if (num < 0 || num >= xref->len)
fz_throw(xref->ctx, "object id out of range (%d %d R)", num, gen);
@@ -358,9 +356,7 @@ pdf_open_image_stream(pdf_document *xref, int num, int gen, pdf_image_params *pa
if (x->stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, x->obj, num, gen, params);
- fz_seek(xref->file, x->stm_ofs, 0);
- return stm;
+ return pdf_open_filter(xref->file, xref, x->obj, num, gen, x->stm_ofs, params);
}
fz_stream *
@@ -410,14 +406,10 @@ pdf_open_image_decomp_stream(fz_context *ctx, fz_buffer *buffer, pdf_image_param
fz_stream *
pdf_open_stream_with_offset(pdf_document *xref, int num, int gen, pdf_obj *dict, int stm_ofs)
{
- fz_stream *stm;
-
if (stm_ofs == 0)
fz_throw(xref->ctx, "object is not a stream");
- stm = pdf_open_filter(xref->file, xref, dict, num, gen, NULL);
- fz_seek(xref->file, stm_ofs, 0);
- return stm;
+ return pdf_open_filter(xref->file, xref, dict, num, gen, stm_ofs, NULL);
}
/*