summaryrefslogtreecommitdiff
path: root/fitz/filt_lzwd.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2009-11-05 23:36:53 +0100
committerTor Andersson <tor@ghostscript.com>2009-11-05 23:36:53 +0100
commit836800bf5a7d9c99738cfd5bab4699af68d2fb6a (patch)
treeec5489fdec4de2f5f268ddd49bd373b1a341c374 /fitz/filt_lzwd.c
parentc5a20664155a6b37c2c325ac465c1d16d4da6c71 (diff)
downloadmupdf-836800bf5a7d9c99738cfd5bab4699af68d2fb6a.tar.xz
Fix clear and bit count change-over bugs in lzw decoder.
Diffstat (limited to 'fitz/filt_lzwd.c')
-rw-r--r--fitz/filt_lzwd.c42
1 files changed, 10 insertions, 32 deletions
diff --git a/fitz/filt_lzwd.c b/fitz/filt_lzwd.c
index 9edffa71..35ae59c2 100644
--- a/fitz/filt_lzwd.c
+++ b/fitz/filt_lzwd.c
@@ -17,7 +17,7 @@ typedef struct lzw_code_s lzw_code;
struct lzw_code_s
{
- int prev; /* prev code (in string) */
+ int prev; /* prev code (in string) */
unsigned short length; /* string len, including this token */
unsigned char value; /* data value */
unsigned char firstchar; /* first token of string */
@@ -34,9 +34,9 @@ struct fz_lzwd_s
unsigned int word; /* bits loaded from data */
int bidx;
- int resume; /* resume output of code from needout */
+ int resume; /* resume output of code from needout */
int codebits; /* num bits/code */
- int code; /* current code */
+ int code; /* current code */
int oldcode; /* previously recognized code */
int nextcode; /* next free entry */
lzw_code table[NUMCODES];
@@ -149,47 +149,23 @@ fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out)
}
lzw->code = lzw->word >> (32 - lzw->codebits);
+ lzw->code &= (1 << lzw->codebits) - 1;
+ eatbits(lzw, lzw->codebits);
if (lzw->code == LZW_EOD)
{
- eatbits(lzw, lzw->codebits);
unstuff(lzw, in);
return fz_iodone;
}
if (lzw->code == LZW_CLEAR)
{
- int oldcodebits = lzw->codebits;
-
lzw->codebits = MINBITS;
lzw->nextcode = LZW_FIRST;
-
- lzw->code = lzw->word >> (32 - oldcodebits - MINBITS) & ((1 << MINBITS) - 1);
-
- if (lzw->code == LZW_EOD)
- {
- eatbits(lzw, oldcodebits + MINBITS);
- unstuff(lzw, in);
- return fz_iodone;
- }
-
- eatbits(lzw, oldcodebits + MINBITS);
-
- lzw->oldcode = lzw->code;
-
- if (out->wp + 1 > out->ep)
- {
- lzw->resume = 1;
- return fz_ioneedout;
- }
-
- *out->wp++ = lzw->code;
-
+ lzw->oldcode = -1;
continue;
}
- eatbits(lzw, lzw->codebits);
-
/* if stream starts without a clear code, oldcode is undefined... */
if (lzw->oldcode == -1)
{
@@ -203,12 +179,14 @@ fz_processlzwd(fz_filter *filter, fz_buffer *in, fz_buffer *out)
lzw->table[lzw->nextcode].length = lzw->table[lzw->oldcode].length + 1;
if (lzw->code < lzw->nextcode)
lzw->table[lzw->nextcode].value = lzw->table[lzw->code].firstchar;
- else
+ else if (lzw->code == lzw->nextcode)
lzw->table[lzw->nextcode].value = lzw->table[lzw->nextcode].firstchar;
+ else
+ fz_warn("out of range code encountered in lzw decode");
lzw->nextcode ++;
- if (lzw->nextcode >= (1 << lzw->codebits) - lzw->earlychange - 1)
+ if (lzw->nextcode > (1 << lzw->codebits) - lzw->earlychange - 1)
{
lzw->codebits ++;
if (lzw->codebits > MAXBITS)