summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2014-03-11 19:04:17 +0000
committerRobin Watts <robin.watts@artifex.com>2014-03-17 19:38:40 +0000
commit551de42088c58dc69fba06fb53e36c2ddb12367f (patch)
treef073b5ac7d3dee2de2f5609a13fd9c47e605d3d8 /source
parent8fdcb140930c3027841af28a4632ce6d23aa44b6 (diff)
downloadmupdf-551de42088c58dc69fba06fb53e36c2ddb12367f.tar.xz
Rework fz_streams.
Currently fz_streams have a 4K buffer within their header. The call to read from a stream fills this buffer, resulting in more data being pulled from any underlying stream than we might like. This causes problems with the forthcoming 'leech' filter. Here we simplify the fields available in the public stream header. No specific buffer is given; simply the read and write pointers. The underlying 'read' function is replaced by a 'next' function that makes the next block of data available and returns the first character of it (or EOF). A caller to the 'next' function should supply the maximum number of bytes that it knows it will need (possibly not now, but eventually). This enables the underlying stream to efficiently decode just enough. The underlying stream is free to return fewer, or a greater number if it wants to. The exact size of the 'block' of data returned will depend on the filter in use and (possibly) the data therein. Callers can get the currently available amount of data by calling fz_available (but again should pass the maximum amount of data they know they will need). The only time this will ever return 0 is if we have hit EOF.
Diffstat (limited to 'source')
-rw-r--r--source/fitz/filter-basic.c268
-rw-r--r--source/fitz/filter-dct.c25
-rw-r--r--source/fitz/filter-fax.c54
-rw-r--r--source/fitz/filter-flate.c35
-rw-r--r--source/fitz/filter-jbig2.c19
-rw-r--r--source/fitz/filter-lzw.c23
-rw-r--r--source/fitz/filter-predict.c23
-rw-r--r--source/fitz/stream-open.c85
-rw-r--r--source/fitz/stream-prog.c19
-rw-r--r--source/fitz/stream-read.c97
-rw-r--r--source/pdf/pdf-op-run.c25
11 files changed, 395 insertions, 278 deletions
diff --git a/source/fitz/filter-basic.c b/source/fitz/filter-basic.c
index 3a64ee93..5defe066 100644
--- a/source/fitz/filter-basic.c
+++ b/source/fitz/filter-basic.c
@@ -14,21 +14,34 @@ struct null_filter
{
fz_stream *chain;
int remain;
- int pos;
+ int offset;
+ unsigned char buffer[4096];
};
static int
-read_null(fz_stream *stm, unsigned char *buf, int len)
+next_null(fz_stream *stm, int max)
{
struct null_filter *state = stm->state;
- int amount = fz_mini(len, state->remain);
int n;
- fz_seek(state->chain, state->pos, 0);
- n = fz_read(state->chain, buf, amount);
+ if (state->remain == 0)
+ return EOF;
+ fz_seek(state->chain, state->offset, 0);
+ n = fz_available(state->chain, max);
+ if (n > state->remain)
+ n = state->remain;
+ if (n > sizeof(state->buffer))
+ n = sizeof(state->buffer);
+ memcpy(state->buffer, state->chain->rp, n);
+ stm->rp = state->buffer;
+ stm->wp = stm->rp + n;
+ if (n == 0)
+ return EOF;
+ state->chain->rp += n;
state->remain -= n;
- state->pos += n;
- return n;
+ state->offset += n;
+ stm->pos += n;
+ return *stm->rp++;
}
static void
@@ -60,7 +73,7 @@ fz_open_null(fz_stream *chain, int len, int offset)
state = fz_malloc_struct(ctx, struct null_filter);
state->chain = chain;
state->remain = len;
- state->pos = offset;
+ state->offset = offset;
}
fz_catch(ctx)
{
@@ -68,7 +81,7 @@ fz_open_null(fz_stream *chain, int len, int offset)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_null, close_null, rebind_null);
+ return fz_new_stream(ctx, state, next_null, close_null, rebind_null);
}
/* Concat filter concatenates several streams into one */
@@ -79,48 +92,51 @@ struct concat_filter
int count;
int current;
int pad; /* 1 if we should add whitespace padding between streams */
- int ws; /* 1 if we should send a whitespace padding byte next */
+ unsigned char ws_buf;
fz_stream *chain[1];
};
static int
-read_concat(fz_stream *stm, unsigned char *buf, int len)
+next_concat(fz_stream *stm, int max)
{
struct concat_filter *state = (struct concat_filter *)stm->state;
int n;
- int read = 0;
- if (len <= 0)
- return 0;
-
- while (state->current != state->count && len > 0)
+ while (state->current < state->count)
{
- /* If we need to send a whitespace char, do that */
- if (state->ws)
+ /* Read the next block of underlying data. */
+ if (stm->wp == state->chain[state->current]->wp)
+ state->chain[state->current]->rp = stm->wp;
+ n = fz_available(state->chain[state->current], max);
+ if (n)
{
- *buf++ = 32;
- read++;
- len--;
- state->ws = 0;
- continue;
+ stm->rp = state->chain[state->current]->rp;
+ stm->wp = state->chain[state->current]->wp;
+ stm->pos += n;
+ return *stm->rp++;
}
- /* Otherwise, read as much data as will fit in the buffer */
- n = fz_read(state->chain[state->current], buf, len);
- read += n;
- buf += n;
- len -= n;
- /* If we didn't read any, then we must have hit the end of
- * our buffer space. Move to the next stream, and remember to
- * pad. */
- if (n == 0)
+ else
{
- fz_close(state->chain[state->current]);
+ if (state->chain[state->current]->error)
+ {
+ stm->error = 1;
+ break;
+ }
state->current++;
- state->ws = state->pad;
+ fz_close(state->chain[state->current-1]);
+ if (state->pad)
+ {
+ stm->rp = &state->ws_buf;
+ stm->wp = stm->rp + 1;
+ stm->pos++;
+ return 32;
+ }
}
}
- return read;
+ stm->rp = stm->wp;
+
+ return EOF;
}
static void
@@ -161,9 +177,9 @@ fz_open_concat(fz_context *ctx, int len, int pad)
state->count = 0;
state->current = 0;
state->pad = pad;
- state->ws = 0; /* We never send padding byte at the start */
+ state->ws_buf = 32;
- return fz_new_stream(ctx, state, read_concat, close_concat, rebind_concat);
+ return fz_new_stream(ctx, state, next_concat, close_concat, rebind_concat);
}
void
@@ -185,6 +201,7 @@ struct fz_ahxd_s
{
fz_stream *chain;
int eod;
+ unsigned char buffer[256];
};
static inline int iswhite(int a)
@@ -213,23 +230,27 @@ static inline int unhex(int a)
}
static int
-read_ahxd(fz_stream *stm, unsigned char *buf, int len)
+next_ahxd(fz_stream *stm, int max)
{
fz_ahxd *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = state->buffer;
+ unsigned char *ep;
int a, b, c, odd;
+ if (max > sizeof(state->buffer))
+ max = sizeof(state->buffer);
+ ep = p + max;
+
odd = 0;
while (p < ep)
{
if (state->eod)
- return p - buf;
+ break;
c = fz_read_byte(state->chain);
if (c < 0)
- return p - buf;
+ break;
if (ishex(c))
{
@@ -250,14 +271,20 @@ read_ahxd(fz_stream *stm, unsigned char *buf, int len)
if (odd)
*p++ = (a << 4);
state->eod = 1;
+ break;
}
else if (!iswhite(c))
{
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in ahxd: '%c'", c);
}
}
+ stm->rp = state->buffer;
+ stm->wp = p;
+ stm->pos += p - state->buffer;
- return p - buf;
+ if (stm->rp != p)
+ return *stm->rp++;
+ return EOF;
}
static void
@@ -294,7 +321,7 @@ fz_open_ahxd(fz_stream *chain)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_ahxd, close_ahxd, rebind_ahxd);
+ return fz_new_stream(ctx, state, next_ahxd, close_ahxd, rebind_ahxd);
}
/* ASCII 85 Decode */
@@ -304,32 +331,32 @@ typedef struct fz_a85d_s fz_a85d;
struct fz_a85d_s
{
fz_stream *chain;
- unsigned char bp[4];
- unsigned char *rp, *wp;
+ unsigned char buffer[256];
int eod;
};
static int
-read_a85d(fz_stream *stm, unsigned char *buf, int len)
+next_a85d(fz_stream *stm, int max)
{
fz_a85d *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = state->buffer;
+ unsigned char *ep;
int count = 0;
int word = 0;
int c;
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
+ if (state->eod)
+ return EOF;
+
+ if (max > sizeof(state->buffer))
+ max = sizeof(state->buffer);
+ ep = p + max;
while (p < ep)
{
- if (state->eod)
- return p - buf;
-
c = fz_read_byte(state->chain);
if (c < 0)
- return p - buf;
+ break;
if (c >= '!' && c <= 'u')
{
@@ -337,12 +364,10 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len)
{
word = word * 85 + (c - '!');
- state->bp[0] = (word >> 24) & 0xff;
- state->bp[1] = (word >> 16) & 0xff;
- state->bp[2] = (word >> 8) & 0xff;
- state->bp[3] = (word) & 0xff;
- state->rp = state->bp;
- state->wp = state->bp + 4;
+ *p++ = (word >> 24) & 0xff;
+ *p++ = (word >> 16) & 0xff;
+ *p++ = (word >> 8) & 0xff;
+ *p++ = (word) & 0xff;
word = 0;
count = 0;
@@ -356,12 +381,10 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len)
else if (c == 'z' && count == 0)
{
- state->bp[0] = 0;
- state->bp[1] = 0;
- state->bp[2] = 0;
- state->bp[3] = 0;
- state->rp = state->bp;
- state->wp = state->bp + 4;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = 0;
}
else if (c == '~')
@@ -381,39 +404,38 @@ read_a85d(fz_stream *stm, unsigned char *buf, int len)
break;
case 2:
word = word * (85 * 85 * 85) + 0xffffff;
- state->bp[0] = word >> 24;
- state->rp = state->bp;
- state->wp = state->bp + 1;
+ *p++ = word >> 24;
break;
case 3:
word = word * (85 * 85) + 0xffff;
- state->bp[0] = word >> 24;
- state->bp[1] = word >> 16;
- state->rp = state->bp;
- state->wp = state->bp + 2;
+ *p++ = word >> 24;
+ *p++ = word >> 16;
break;
case 4:
word = word * 85 + 0xff;
- state->bp[0] = word >> 24;
- state->bp[1] = word >> 16;
- state->bp[2] = word >> 8;
- state->rp = state->bp;
- state->wp = state->bp + 3;
+ *p++ = word >> 24;
+ *p++ = word >> 16;
+ *p++ = word >> 8;
break;
}
state->eod = 1;
+ break;
}
else if (!iswhite(c))
{
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "bad data in a85d: '%c'", c);
}
-
- while (state->rp < state->wp && p < ep)
- *p++ = *state->rp++;
}
- return p - buf;
+ stm->rp = state->buffer;
+ stm->wp = p;
+ stm->pos += p - state->buffer;
+
+ if (p == stm->rp)
+ return EOF;
+
+ return *stm->rp++;
}
static void
@@ -443,8 +465,6 @@ fz_open_a85d(fz_stream *chain)
{
state = fz_malloc_struct(ctx, fz_a85d);
state->chain = chain;
- state->rp = state->bp;
- state->wp = state->bp;
state->eod = 0;
}
fz_catch(ctx)
@@ -453,7 +473,7 @@ fz_open_a85d(fz_stream *chain)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_a85d, close_a85d, rebind_a85d);
+ return fz_new_stream(ctx, state, next_a85d, close_a85d, rebind_a85d);
}
/* Run Length Decode */
@@ -464,25 +484,36 @@ struct fz_rld_s
{
fz_stream *chain;
int run, n, c;
+ unsigned char buffer[256];
};
static int
-read_rld(fz_stream *stm, unsigned char *buf, int len)
+next_rld(fz_stream *stm, int max)
{
fz_rld *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = state->buffer;
+ unsigned char *ep;
+
+ if (state->run == 128)
+ return EOF;
+
+ if (max > sizeof(state->buffer))
+ max = sizeof(state->buffer);
+ ep = p + max;
while (p < ep)
{
if (state->run == 128)
- return p - buf;
+ break;
if (state->n == 0)
{
state->run = fz_read_byte(state->chain);
if (state->run < 0)
+ {
state->run = 128;
+ break;
+ }
if (state->run < 128)
state->n = state->run + 1;
if (state->run > 128)
@@ -516,7 +547,14 @@ read_rld(fz_stream *stm, unsigned char *buf, int len)
}
}
- return p - buf;
+ stm->rp = state->buffer;
+ stm->wp = p;
+ stm->pos += p - state->buffer;
+
+ if (p == stm->rp)
+ return EOF;
+
+ return *stm->rp++;
}
static void
@@ -556,7 +594,7 @@ fz_open_rld(fz_stream *chain)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_rld, close_rld, rebind_rld);
+ return fz_new_stream(ctx, state, next_rld, close_rld, rebind_rld);
}
/* RC4 Filter */
@@ -567,15 +605,27 @@ struct fz_arc4c_s
{
fz_stream *chain;
fz_arc4 arc4;
+ unsigned char buffer[256];
};
static int
-read_arc4(fz_stream *stm, unsigned char *buf, int len)
+next_arc4(fz_stream *stm, int max)
{
fz_arc4c *state = stm->state;
- int n = fz_read(state->chain, buf, len);
- fz_arc4_encrypt(&state->arc4, buf, buf, n);
- return n;
+ int n = fz_available(state->chain, max);
+
+ if (n == 0)
+ return EOF;
+ if (n > sizeof(state->buffer))
+ n = sizeof(state->buffer);
+
+ stm->rp = state->buffer;
+ stm->wp = state->buffer + n;
+ fz_arc4_encrypt(&state->arc4, stm->rp, state->chain->rp, n);
+ state->chain->rp += n;
+ stm->pos += n;
+
+ return *stm->rp++;
}
static void
@@ -613,7 +663,7 @@ fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_arc4, close_arc4, rebind_arc4c);
+ return fz_new_stream(ctx, state, next_arc4, close_arc4, rebind_arc4c);
}
/* AES Filter */
@@ -628,14 +678,19 @@ struct fz_aesd_s
int ivcount;
unsigned char bp[16];
unsigned char *rp, *wp;
+ unsigned char buffer[256];
};
static int
-read_aesd(fz_stream *stm, unsigned char *buf, int len)
+next_aesd(fz_stream *stm, int max)
{
fz_aesd *state = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = state->buffer;
+ unsigned char *ep;
+
+ if (max > sizeof(state->buffer))
+ max = sizeof(state->buffer);
+ ep = p + max;
while (state->ivcount < 16)
{
@@ -652,7 +707,7 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len)
{
int n = fz_read(state->chain, state->bp, 16);
if (n == 0)
- return p - buf;
+ break;
else if (n < 16)
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "partial block in aes filter");
@@ -673,7 +728,14 @@ read_aesd(fz_stream *stm, unsigned char *buf, int len)
*p++ = *state->rp++;
}
- return p - buf;
+ stm->rp = state->buffer;
+ stm->wp = p;
+ stm->pos += p - state->buffer;
+
+ if (p == stm->rp)
+ return EOF;
+
+ return *stm->rp++;
}
static void
@@ -718,5 +780,5 @@ fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_aesd, close_aesd, rebind_aesd);
+ return fz_new_stream(ctx, state, next_aesd, close_aesd, rebind_aesd);
}
diff --git a/source/fitz/filter-dct.c b/source/fitz/filter-dct.c
index 23665909..86268032 100644
--- a/source/fitz/filter-dct.c
+++ b/source/fitz/filter-dct.c
@@ -22,6 +22,8 @@ struct fz_dctd_s
struct jpeg_error_mgr errmgr;
jmp_buf jb;
char msg[JMSG_LENGTH_MAX];
+
+ unsigned char buffer[4096];
};
static void error_exit(j_common_ptr cinfo)
@@ -48,10 +50,11 @@ static boolean fill_input_buffer(j_decompress_ptr cinfo)
fz_stream *curr_stm = state->curr_stm;
fz_context *ctx = curr_stm->ctx;
+
curr_stm->rp = curr_stm->wp;
fz_try(ctx)
{
- fz_fill_buffer(curr_stm);
+ src->bytes_in_buffer = fz_available(curr_stm, 1);
}
fz_catch(ctx)
{
@@ -59,7 +62,6 @@ static boolean fill_input_buffer(j_decompress_ptr cinfo)
return 0;
}
src->next_input_byte = curr_stm->rp;
- src->bytes_in_buffer = curr_stm->wp - curr_stm->rp;
if (src->bytes_in_buffer == 0)
{
@@ -88,12 +90,16 @@ static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
}
static int
-read_dctd(fz_stream *stm, unsigned char *buf, int len)
+next_dctd(fz_stream *stm, int max)
{
fz_dctd *state = stm->state;
j_decompress_ptr cinfo = &state->cinfo;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = state->buffer;
+ unsigned char *ep;
+
+ if (max > sizeof(state->buffer))
+ max = sizeof(state->buffer);
+ ep = state->buffer + max;
if (setjmp(state->jb))
{
@@ -202,8 +208,13 @@ read_dctd(fz_stream *stm, unsigned char *buf, int len)
while (state->rp < state->wp && p < ep)
*p++ = *state->rp++;
}
+ stm->rp = state->buffer;
+ stm->wp = p;
+ stm->pos += (p - state->buffer);
+ if (p == stm->rp)
+ return EOF;
- return p - buf;
+ return *stm->rp++;
}
static void
@@ -267,5 +278,5 @@ fz_open_dctd(fz_stream *chain, int color_transform, int l2factor, fz_stream *jpe
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_dctd, close_dctd, rebind_dctd);
+ return fz_new_stream(ctx, state, next_dctd, close_dctd, rebind_dctd);
}
diff --git a/source/fitz/filter-fax.c b/source/fitz/filter-fax.c
index 7b35c812..70692338 100644
--- a/source/fitz/filter-fax.c
+++ b/source/fitz/filter-fax.c
@@ -344,6 +344,8 @@ struct fz_faxd_s
unsigned char *ref;
unsigned char *dst;
unsigned char *rp, *wp;
+
+ unsigned char buffer[4096];
};
static inline void eat_bits(fz_faxd *fax, int nbits)
@@ -355,7 +357,10 @@ static inline void eat_bits(fz_faxd *fax, int nbits)
static int
fill_bits(fz_faxd *fax)
{
- while (fax->bidx >= 8)
+ /* The longest length of bits we'll ever need is 13. Never read more
+ * than we need to avoid unnecessary overreading of the end of the
+ * stream. */
+ while (fax->bidx > (32-13))
{
int c = fz_read_byte(fax->chain);
if (c == EOF)
@@ -551,14 +556,17 @@ dec2d(fz_context *ctx, fz_faxd *fax)
}
static int
-read_faxd(fz_stream *stm, unsigned char *buf, int len)
+next_faxd(fz_stream *stm, int max)
{
fz_context *ctx = stm->ctx;
fz_faxd *fax = stm->state;
- unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *p = fax->buffer;
+ unsigned char *ep;
unsigned char *tmp;
+ if (max > sizeof(fax->buffer))
+ max = sizeof(fax->buffer);
+ ep = p + max;
if (fax->stage == STATE_INIT && fax->end_of_line)
{
fill_bits(fax);
@@ -576,7 +584,7 @@ read_faxd(fz_stream *stm, unsigned char *buf, int len)
fax->stage = STATE_NORMAL;
if (fax->stage == STATE_DONE)
- return 0;
+ return EOF;
if (fax->stage == STATE_EOL)
goto eol;
@@ -679,7 +687,14 @@ eol:
}
if (fax->rp < fax->wp)
- return p - buf;
+ {
+ stm->rp = fax->buffer;
+ stm->wp = p;
+ stm->pos += (p - fax->buffer);
+ if (p == fax->buffer)
+ return EOF;
+ return *stm->rp++;
+ }
tmp = fax->ref;
fax->ref = fax->dst;
@@ -694,11 +709,8 @@ eol:
fax->a = -1;
fax->ridx ++;
- if (!fax->end_of_block && fax->rows)
- {
- if (fax->ridx >= fax->rows)
- goto rtc;
- }
+ if (!fax->end_of_block && fax->rows && fax->ridx >= fax->rows)
+ goto rtc;
/* we have not read dim from eol, make a guess */
if (fax->k > 0 && !fax->eolc && fax->a == -1)
@@ -719,8 +731,15 @@ eol:
}
/* no more space in output, don't decode the next row yet */
- if (p == buf + len)
- return p - buf;
+ if (p == fax->buffer + max)
+ {
+ stm->rp = fax->buffer;
+ stm->wp = p;
+ stm->pos += (p - fax->buffer);
+ if (p == fax->buffer)
+ return EOF;
+ return *stm->rp++;
+ }
goto loop;
@@ -740,7 +759,12 @@ error:
rtc:
fax->stage = STATE_DONE;
- return p - buf;
+ stm->rp = fax->buffer;
+ stm->wp = p;
+ stm->pos += (p - fax->buffer);
+ if (p == fax->buffer)
+ return EOF;
+ return *stm->rp++;
}
static void
@@ -828,5 +852,5 @@ fz_open_faxd(fz_stream *chain,
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, fax, read_faxd, close_faxd, rebind_faxd);
+ return fz_new_stream(ctx, fax, next_faxd, close_faxd, rebind_faxd);
}
diff --git a/source/fitz/filter-flate.c b/source/fitz/filter-flate.c
index 022cdb12..b306c9c3 100644
--- a/source/fitz/filter-flate.c
+++ b/source/fitz/filter-flate.c
@@ -8,6 +8,7 @@ struct fz_flate_s
{
fz_stream *chain;
z_stream z;
+ unsigned char buffer[4096];
};
static void *zalloc(void *opaque, unsigned int items, unsigned int size)
@@ -21,23 +22,27 @@ static void zfree(void *opaque, void *ptr)
}
static int
-read_flated(fz_stream *stm, unsigned char *outbuf, int outlen)
+next_flated(fz_stream *stm, int outlen)
{
fz_flate *state = stm->state;
fz_stream *chain = state->chain;
z_streamp zp = &state->z;
int code;
+ unsigned char *outbuf = state->buffer;
+
+ if (outlen > sizeof(state->buffer))
+ outlen = sizeof(state->buffer);
+
+ if (stm->eof)
+ return EOF;
zp->next_out = outbuf;
zp->avail_out = outlen;
while (zp->avail_out > 0)
{
- if (chain->rp == chain->wp)
- fz_fill_buffer(chain);
-
+ zp->avail_in = fz_available(chain, 1);
zp->next_in = chain->rp;
- zp->avail_in = chain->wp - chain->rp;
code = inflate(zp, Z_SYNC_FLUSH);
@@ -45,23 +50,23 @@ read_flated(fz_stream *stm, unsigned char *outbuf, int outlen)
if (code == Z_STREAM_END)
{
- return outlen - zp->avail_out;
+ break;
}
else if (code == Z_BUF_ERROR)
{
fz_warn(stm->ctx, "premature end of data in flate filter");
- return outlen - zp->avail_out;
+ break;
}
else if (code == Z_DATA_ERROR && zp->avail_in == 0)
{
fz_warn(stm->ctx, "ignoring zlib error: %s", zp->msg);
- return outlen - zp->avail_out;
+ break;
}
else if (code == Z_DATA_ERROR && !strcmp(zp->msg, "incorrect data check"))
{
fz_warn(stm->ctx, "ignoring zlib error: %s", zp->msg);
chain->rp = chain->wp;
- return outlen - zp->avail_out;
+ break;
}
else if (code != Z_OK)
{
@@ -69,7 +74,15 @@ read_flated(fz_stream *stm, unsigned char *outbuf, int outlen)
}
}
- return outlen - zp->avail_out;
+ stm->rp = state->buffer;
+ stm->wp = state->buffer + outlen - zp->avail_out;
+ stm->pos += outlen - zp->avail_out;
+ if (stm->rp == stm->wp)
+ {
+ stm->eof = 1;
+ return EOF;
+ }
+ return *stm->rp++;
}
static void
@@ -126,5 +139,5 @@ fz_open_flated(fz_stream *chain)
fz_close(chain);
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_flated, close_flated, rebind_flated);
+ return fz_new_stream(ctx, state, next_flated, close_flated, rebind_flated);
}
diff --git a/source/fitz/filter-jbig2.c b/source/fitz/filter-jbig2.c
index 592f7ab6..98919dcb 100644
--- a/source/fitz/filter-jbig2.c
+++ b/source/fitz/filter-jbig2.c
@@ -17,6 +17,7 @@ struct fz_jbig2d_s
fz_jbig2_globals *gctx;
Jbig2Image *page;
int idx;
+ unsigned char buffer[4096];
};
static void
@@ -39,15 +40,20 @@ close_jbig2d(fz_context *ctx, void *state_)
}
static int
-read_jbig2d(fz_stream *stm, unsigned char *buf, int len)
+next_jbig2d(fz_stream *stm, int len)
{
fz_jbig2d *state = stm->state;
unsigned char tmp[4096];
+ unsigned char *buf = state->buffer;
unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *ep;
unsigned char *s;
int x, w, n;
+ if (len > sizeof(state->buffer))
+ len = sizeof(state->buffer);
+ ep = buf + len;
+
if (!state->page)
{
while (1)
@@ -72,7 +78,12 @@ read_jbig2d(fz_stream *stm, unsigned char *buf, int len)
*p++ = s[x++] ^ 0xff;
state->idx = x;
- return p - buf;
+ stm->rp = buf;
+ stm->wp = p;
+ if (p == buf)
+ return EOF;
+ stm->pos += p - buf;
+ return *stm->rp++;
}
static fz_stream *
@@ -146,5 +157,5 @@ fz_open_jbig2d(fz_stream *chain, fz_jbig2_globals *globals)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_jbig2d, close_jbig2d, rebind_jbig2d);
+ return fz_new_stream(ctx, state, next_jbig2d, close_jbig2d, rebind_jbig2d);
}
diff --git a/source/fitz/filter-lzw.c b/source/fitz/filter-lzw.c
index c78c8c3f..e13b0ef0 100644
--- a/source/fitz/filter-lzw.c
+++ b/source/fitz/filter-lzw.c
@@ -41,15 +41,18 @@ struct fz_lzwd_s
unsigned char bp[MAX_LENGTH];
unsigned char *rp, *wp;
+
+ unsigned char buffer[4096];
};
static int
-read_lzwd(fz_stream *stm, unsigned char *buf, int len)
+next_lzwd(fz_stream *stm, int len)
{
fz_lzwd *lzw = stm->state;
lzw_code *table = lzw->table;
+ unsigned char *buf = lzw->buffer;
unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *ep;
unsigned char *s;
int codelen;
@@ -58,13 +61,17 @@ read_lzwd(fz_stream *stm, unsigned char *buf, int len)
int old_code = lzw->old_code;
int next_code = lzw->next_code;
+ if (len > sizeof(lzw->buffer))
+ len = sizeof(lzw->buffer);
+ ep = buf + len;
+
while (lzw->rp < lzw->wp && p < ep)
*p++ = *lzw->rp++;
while (p < ep)
{
if (lzw->eod)
- return 0;
+ return EOF;
code = fz_read_bits(lzw->chain, code_bits);
@@ -162,7 +169,13 @@ read_lzwd(fz_stream *stm, unsigned char *buf, int len)
lzw->old_code = old_code;
lzw->next_code = next_code;
- return p - buf;
+ stm->rp = buf;
+ stm->wp = p;
+ if (buf == p)
+ return EOF;
+ stm->pos += p - buf;
+
+ return *stm->rp++;
}
static void
@@ -228,5 +241,5 @@ fz_open_lzwd(fz_stream *chain, int early_change)
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, lzw, read_lzwd, close_lzwd, rebind_lzwd);
+ return fz_new_stream(ctx, lzw, next_lzwd, close_lzwd, rebind_lzwd);
}
diff --git a/source/fitz/filter-predict.c b/source/fitz/filter-predict.c
index 66101753..6862f8c9 100644
--- a/source/fitz/filter-predict.c
+++ b/source/fitz/filter-predict.c
@@ -19,6 +19,8 @@ struct fz_predict_s
unsigned char *out;
unsigned char *ref;
unsigned char *rp, *wp;
+
+ unsigned char buffer[4096];
};
static inline int getcomponent(unsigned char *line, int x, int bpc)
@@ -143,14 +145,19 @@ fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len
}
static int
-read_predict(fz_stream *stm, unsigned char *buf, int len)
+next_predict(fz_stream *stm, int len)
{
fz_predict *state = stm->state;
+ unsigned char *buf = state->buffer;
unsigned char *p = buf;
- unsigned char *ep = buf + len;
+ unsigned char *ep;
int ispng = state->predictor >= 10;
int n;
+ if (len >= sizeof(state->buffer))
+ len = sizeof(state->buffer);
+ ep = buf + len;
+
while (state->rp < state->wp && p < ep)
*p++ = *state->rp++;
@@ -158,7 +165,7 @@ read_predict(fz_stream *stm, unsigned char *buf, int len)
{
n = fz_read(state->chain, state->in, state->stride + ispng);
if (n == 0)
- return p - buf;
+ break;
if (state->predictor == 1)
memcpy(state->out, state->in, n);
@@ -177,7 +184,13 @@ read_predict(fz_stream *stm, unsigned char *buf, int len)
*p++ = *state->rp++;
}
- return p - buf;
+ stm->rp = buf;
+ stm->wp = p;
+ if (stm->rp == stm->wp)
+ return EOF;
+ stm->pos += p - buf;
+
+ return *stm->rp++;
}
static void
@@ -267,5 +280,5 @@ fz_open_predict(fz_stream *chain, int predictor, int columns, int colors, int bp
fz_rethrow(ctx);
}
- return fz_new_stream(ctx, state, read_predict, close_predict, rebind_predict);
+ return fz_new_stream(ctx, state, next_predict, close_predict, rebind_predict);
}
diff --git a/source/fitz/stream-open.c b/source/fitz/stream-open.c
index f336a4e4..3e51e733 100644
--- a/source/fitz/stream-open.c
+++ b/source/fitz/stream-open.c
@@ -12,7 +12,7 @@ void fz_rebind_stream(fz_stream *stm, fz_context *ctx)
fz_stream *
fz_new_stream(fz_context *ctx, void *state,
- fz_stream_read_fn *read,
+ fz_stream_next_fn *next,
fz_stream_close_fn *close,
fz_stream_rebind_fn *rebind)
{
@@ -36,13 +36,11 @@ fz_new_stream(fz_context *ctx, void *state,
stm->bits = 0;
stm->avail = 0;
- stm->bp = stm->buf;
- stm->rp = stm->bp;
- stm->wp = stm->bp;
- stm->ep = stm->buf + sizeof stm->buf;
+ stm->rp = NULL;
+ stm->wp = NULL;
stm->state = state;
- stm->read = read;
+ stm->next = next;
stm->close = close;
stm->seek = NULL;
stm->rebind = rebind;
@@ -75,27 +73,44 @@ fz_close(fz_stream *stm)
/* File stream */
-static int read_file(fz_stream *stm, unsigned char *buf, int len)
+typedef struct fz_file_stream_s
{
- int n = read(*(int*)stm->state, buf, len);
+ int file;
+ unsigned char buffer[4096];
+} fz_file_stream;
+
+static int next_file(fz_stream *stm, int n)
+{
+ fz_file_stream *state = stm->state;
+
+ /* n is only a hint, that we can safely ignore */
+ n = read(state->file, state->buffer, sizeof(state->buffer));
if (n < 0)
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "read error: %s", strerror(errno));
- return n;
+ stm->rp = state->buffer;
+ stm->wp = state->buffer + n;
+ stm->pos += n;
+
+ if (n == 0)
+ return EOF;
+ return *stm->rp++;
}
static void seek_file(fz_stream *stm, int offset, int whence)
{
- int n = lseek(*(int*)stm->state, offset, whence);
+ fz_file_stream *state = stm->state;
+ int n = lseek(state->file, offset, whence);
if (n < 0)
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "cannot lseek: %s", strerror(errno));
stm->pos = n;
- stm->rp = stm->bp;
- stm->wp = stm->bp;
+ stm->rp = state->buffer;
+ stm->wp = state->buffer;
}
-static void close_file(fz_context *ctx, void *state)
+static void close_file(fz_context *ctx, void *state_)
{
- int n = close(*(int*)state);
+ fz_file_stream *state = state_;
+ int n = close(state->file);
if (n < 0)
fz_warn(ctx, "close error: %s", strerror(errno));
fz_free(ctx, state);
@@ -105,14 +120,12 @@ fz_stream *
fz_open_fd(fz_context *ctx, int fd)
{
fz_stream *stm;
- int *state;
-
- state = fz_malloc_struct(ctx, int);
- *state = fd;
+ fz_file_stream *state = fz_malloc_struct(ctx, fz_file_stream);
+ state->file = fd;
fz_try(ctx)
{
- stm = fz_new_stream(ctx, state, read_file, close_file, NULL);
+ stm = fz_new_stream(ctx, state, next_file, close_file, NULL);
}
fz_catch(ctx)
{
@@ -160,21 +173,29 @@ fz_open_file_w(fz_context *ctx, const wchar_t *name)
/* Memory stream */
-static int read_buffer(fz_stream *stm, unsigned char *buf, int len)
+static int next_buffer(fz_stream *stm, int max)
{
- return 0;
+ return EOF;
}
static void seek_buffer(fz_stream *stm, int offset, int whence)
{
- if (whence == 0)
- stm->rp = stm->bp + offset;
+ int pos = stm->pos - (stm->wp - stm->rp);
+ /* Convert to absolute pos */
if (whence == 1)
- stm->rp += offset;
- if (whence == 2)
- stm->rp = stm->ep - offset;
- stm->rp = fz_clampp(stm->rp, stm->bp, stm->ep);
- stm->wp = stm->ep;
+ {
+ offset += pos; /* Was relative to current pos */
+ }
+ else if (whence == 2)
+ {
+ offset += stm->pos; /* Was relative to end */
+ }
+
+ if (offset < 0)
+ offset = 0;
+ if (offset > stm->pos)
+ offset = stm->pos;
+ stm->rp += offset - pos;
}
static void close_buffer(fz_context *ctx, void *state_)
@@ -190,13 +211,11 @@ fz_open_buffer(fz_context *ctx, fz_buffer *buf)
fz_stream *stm;
fz_keep_buffer(ctx, buf);
- stm = fz_new_stream(ctx, buf, read_buffer, close_buffer, NULL);
+ stm = fz_new_stream(ctx, buf, next_buffer, close_buffer, NULL);
stm->seek = seek_buffer;
- stm->bp = buf->data;
stm->rp = buf->data;
stm->wp = buf->data + buf->len;
- stm->ep = buf->data + buf->len;
stm->pos = buf->len;
@@ -208,13 +227,11 @@ fz_open_memory(fz_context *ctx, unsigned char *data, int len)
{
fz_stream *stm;
- stm = fz_new_stream(ctx, NULL, read_buffer, close_buffer, NULL);
+ stm = fz_new_stream(ctx, NULL, next_buffer, close_buffer, NULL);
stm->seek = seek_buffer;
- stm->bp = data;
stm->rp = data;
stm->wp = data + len;
- stm->ep = data + len;
stm->pos = len;
diff --git a/source/fitz/stream-prog.c b/source/fitz/stream-prog.c
index 5ec23823..01f3e5ef 100644
--- a/source/fitz/stream-prog.c
+++ b/source/fitz/stream-prog.c
@@ -24,12 +24,17 @@ typedef struct prog_state
int available;
int bps;
clock_t start_time;
+ unsigned char buffer[4096];
} prog_state;
-static int read_prog(fz_stream *stm, unsigned char *buf, int len)
+static int next_prog(fz_stream *stm, int len)
{
prog_state *ps = (prog_state *)stm->state;
int n;
+ unsigned char *buf = ps->buffer;
+
+ if (len > sizeof(ps->buffer))
+ len = sizeof(ps->buffer);
/* Simulate more data having arrived */
if (ps->available < ps->length)
@@ -53,7 +58,12 @@ static int read_prog(fz_stream *stm, unsigned char *buf, int len)
n = (len > 0 ? read(ps->fd, buf, len) : 0);
if (n < 0)
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "read error: %s", strerror(errno));
- return n;
+ stm->rp = ps->buffer + stm->pos;
+ stm->wp = ps->buffer + stm->pos + n;
+ stm->pos += n;
+ if (n == 0)
+ return EOF;
+ return *stm->rp++;
}
static void seek_prog(fz_stream *stm, int offset, int whence)
@@ -100,8 +110,7 @@ static void seek_prog(fz_stream *stm, int offset, int whence)
if (n < 0)
fz_throw(stm->ctx, FZ_ERROR_GENERIC, "cannot lseek: %s", strerror(errno));
stm->pos = n;
- stm->rp = stm->bp;
- stm->wp = stm->bp;
+ stm->wp = stm->rp;
}
static void close_prog(fz_context *ctx, void *state)
@@ -144,7 +153,7 @@ fz_open_fd_progressive(fz_context *ctx, int fd, int bps)
fz_try(ctx)
{
- stm = fz_new_stream(ctx, state, read_prog, close_prog, NULL);
+ stm = fz_new_stream(ctx, state, next_prog, close_prog, NULL);
}
fz_catch(ctx)
{
diff --git a/source/fitz/stream-read.c b/source/fitz/stream-read.c
index 71ae7666..02f186a0 100644
--- a/source/fitz/stream-read.c
+++ b/source/fitz/stream-read.c
@@ -7,89 +7,26 @@ fz_read(fz_stream *stm, unsigned char *buf, int len)
{
int count, n;
- count = fz_mini(len, stm->wp - stm->rp);
- if (count)
+ count = 0;
+ do
{
- memcpy(buf, stm->rp, count);
- stm->rp += count;
- }
-
- if (count == len || stm->error || stm->eof)
- return count;
-
- assert(stm->rp == stm->wp);
-
- if (len - count < stm->ep - stm->bp)
- {
- n = stm->read(stm, stm->bp, stm->ep - stm->bp);
+ n = fz_available(stm, len);
+ if (n > len)
+ n = len;
if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->rp = stm->bp;
- stm->wp = stm->bp + n;
- stm->pos += n;
- }
+ break;
- n = fz_mini(len - count, stm->wp - stm->rp);
- if (n)
- {
- memcpy(buf + count, stm->rp, n);
- stm->rp += n;
- count += n;
- }
- }
- else
- {
- n = stm->read(stm, buf + count, len - count);
- if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->pos += n;
- count += n;
- }
+ memcpy(buf, stm->rp, n);
+ stm->rp += n;
+ buf += n;
+ count += n;
+ len -= n;
}
+ while (len > 0);
return count;
}
-void
-fz_fill_buffer(fz_stream *stm)
-{
- int n;
-
- assert(stm->rp == stm->wp);
-
- if (stm->error || stm->eof)
- return;
-
- fz_try(stm->ctx)
- {
- n = stm->read(stm, stm->bp, stm->ep - stm->bp);
- if (n == 0)
- {
- stm->eof = 1;
- }
- else if (n > 0)
- {
- stm->rp = stm->bp;
- stm->wp = stm->bp + n;
- stm->pos += n;
- }
- }
- fz_catch(stm->ctx)
- {
- fz_rethrow_if(stm->ctx, FZ_ERROR_TRYLATER);
- fz_warn(stm->ctx, "read error; treating as end of file");
- stm->error = 1;
- }
-}
-
fz_buffer *
fz_read_all(fz_stream *stm, int initial)
{
@@ -196,16 +133,6 @@ fz_seek(fz_stream *stm, int offset, int whence)
offset = fz_tell(stm) + offset;
whence = 0;
}
- if (whence == 0)
- {
- int dist = stm->pos - offset;
- if (dist >= 0 && dist <= stm->wp - stm->bp)
- {
- stm->rp = stm->wp - dist;
- stm->eof = 0;
- return;
- }
- }
stm->seek(stm, offset, whence);
stm->eof = 0;
}
diff --git a/source/pdf/pdf-op-run.c b/source/pdf/pdf-op-run.c
index f6eda706..0f74667a 100644
--- a/source/pdf/pdf-op-run.c
+++ b/source/pdf/pdf-op-run.c
@@ -1741,6 +1741,7 @@ static void pdf_run_BI(pdf_csi *csi, void *state)
int ch;
fz_image *img;
pdf_obj *obj;
+ int found;
obj = pdf_parse_dict(csi->doc, file, &csi->doc->lexbuf.base);
@@ -1768,11 +1769,27 @@ static void pdf_run_BI(pdf_csi *csi, void *state)
fz_drop_image(ctx, img);
/* find EI */
+ found = 0;
ch = fz_read_byte(file);
- while (ch != 'E' && ch != EOF)
- ch = fz_read_byte(file);
- ch = fz_read_byte(file);
- if (ch != 'I')
+ do
+ {
+ while (ch != 'E' && ch != EOF)
+ ch = fz_read_byte(file);
+ if (ch == 'E')
+ {
+ ch = fz_read_byte(file);
+ if (ch == 'I')
+ {
+ ch = fz_peek_byte(file);
+ if (ch == ' ' || ch <= 32 || ch == EOF || ch == '<' || ch == '/')
+ {
+ found = 1;
+ break;
+ }
+ }
+ }
+ } while (ch != EOF);
+ if (!found)
fz_throw(ctx, FZ_ERROR_GENERIC, "syntax error after inline image");
}