Stream.cc (xpdf-4.03) | : | Stream.cc (xpdf-4.04) | ||
---|---|---|---|---|
skipping to change at line 55 | skipping to change at line 55 | |||
#ifdef VMS | #ifdef VMS | |||
#ifdef __GNUC__ | #ifdef __GNUC__ | |||
#define SEEK_SET 0 | #define SEEK_SET 0 | |||
#define SEEK_CUR 1 | #define SEEK_CUR 1 | |||
#define SEEK_END 2 | #define SEEK_END 2 | |||
#endif | #endif | |||
#endif | #endif | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
// An LZW/Flate decompression bomb is detected if the output size | ||||
// exceeds decompressionBombSizeThreshold and the decompression ratio | ||||
// exceeds decompressionBombRatioThreshold. | ||||
#define decompressionBombSizeThreshold 50000000 | ||||
#define decompressionBombRatioThreshold 200 | ||||
//------------------------------------------------------------------------ | ||||
// Stream (base class) | // Stream (base class) | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
Stream::Stream() { | Stream::Stream() { | |||
} | } | |||
Stream::~Stream() { | Stream::~Stream() { | |||
} | } | |||
void Stream::close() { | void Stream::close() { | |||
skipping to change at line 151 | skipping to change at line 159 | |||
dict->dictLookup("DecodeParms", ¶ms, recursion); | dict->dictLookup("DecodeParms", ¶ms, recursion); | |||
if (params.isNull()) { | if (params.isNull()) { | |||
params.free(); | params.free(); | |||
dict->dictLookup("DP", ¶ms, recursion); | dict->dictLookup("DP", ¶ms, recursion); | |||
} | } | |||
if (obj.isName()) { | if (obj.isName()) { | |||
str = makeFilter(obj.getName(), str, ¶ms, recursion); | str = makeFilter(obj.getName(), str, ¶ms, recursion); | |||
} else if (obj.isArray()) { | } else if (obj.isArray()) { | |||
for (i = 0; i < obj.arrayGetLength(); ++i) { | for (i = 0; i < obj.arrayGetLength(); ++i) { | |||
obj.arrayGet(i, &obj2, recursion); | obj.arrayGet(i, &obj2, recursion); | |||
if (params.isArray()) | if (params.isArray() && i < params.arrayGetLength()) | |||
params.arrayGet(i, ¶ms2, recursion); | params.arrayGet(i, ¶ms2, recursion); | |||
else | else | |||
params2.initNull(); | params2.initNull(); | |||
if (obj2.isName()) { | if (obj2.isName()) { | |||
str = makeFilter(obj2.getName(), str, ¶ms2, recursion); | str = makeFilter(obj2.getName(), str, ¶ms2, recursion); | |||
} else { | } else { | |||
error(errSyntaxError, getPos(), "Bad filter name"); | error(errSyntaxError, getPos(), "Bad filter name"); | |||
str = new EOFStream(str); | str = new EOFStream(str); | |||
} | } | |||
obj2.free(); | obj2.free(); | |||
skipping to change at line 308 | skipping to change at line 316 | |||
} | } | |||
str = new FlateStream(str, pred, columns, colors, bits); | str = new FlateStream(str, pred, columns, colors, bits); | |||
} else if (!strcmp(name, "JBIG2Decode")) { | } else if (!strcmp(name, "JBIG2Decode")) { | |||
if (params->isDict()) { | if (params->isDict()) { | |||
params->dictLookup("JBIG2Globals", &globals, recursion); | params->dictLookup("JBIG2Globals", &globals, recursion); | |||
} | } | |||
str = new JBIG2Stream(str, &globals); | str = new JBIG2Stream(str, &globals); | |||
globals.free(); | globals.free(); | |||
} else if (!strcmp(name, "JPXDecode")) { | } else if (!strcmp(name, "JPXDecode")) { | |||
str = new JPXStream(str); | str = new JPXStream(str); | |||
} else if (!strcmp(name, "Crypt")) { | ||||
// this is handled in Parser::makeStream() | ||||
} else { | } else { | |||
error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name); | error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name); | |||
str = new EOFStream(str); | str = new EOFStream(str); | |||
} | } | |||
return str; | return str; | |||
} | } | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
// BaseStream | // BaseStream | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
skipping to change at line 387 | skipping to change at line 397 | |||
} | } | |||
ImageStream::~ImageStream() { | ImageStream::~ImageStream() { | |||
if (imgLine != (Guchar *)inputLine) { | if (imgLine != (Guchar *)inputLine) { | |||
gfree(imgLine); | gfree(imgLine); | |||
} | } | |||
gfree(inputLine); | gfree(inputLine); | |||
} | } | |||
void ImageStream::reset() { | void ImageStream::reset() { | |||
str->disableDecompressionBombChecking(); | ||||
str->reset(); | str->reset(); | |||
} | } | |||
void ImageStream::close() { | void ImageStream::close() { | |||
str->close(); | str->close(); | |||
} | } | |||
GBool ImageStream::getPixel(Guchar *pix) { | GBool ImageStream::getPixel(Guchar *pix) { | |||
int i; | int i; | |||
skipping to change at line 937 | skipping to change at line 948 | |||
bufPtr += n; | bufPtr += n; | |||
return n; | return n; | |||
} | } | |||
void MemStream::setPos(GFileOffset pos, int dir) { | void MemStream::setPos(GFileOffset pos, int dir) { | |||
Guint i; | Guint i; | |||
if (dir >= 0) { | if (dir >= 0) { | |||
i = (Guint)pos; | i = (Guint)pos; | |||
} else { | } else { | |||
i = (Guint)(start + length - pos); | if (pos > start + length) { | |||
i = 0; | ||||
} else { | ||||
i = (Guint)(start + length - pos); | ||||
} | ||||
} | } | |||
if (i < start) { | if (i < start) { | |||
i = start; | i = start; | |||
} else if (i > start + length) { | } else if (i > start + length) { | |||
i = start + length; | i = start + length; | |||
} | } | |||
bufPtr = buf + i; | bufPtr = buf + i; | |||
} | } | |||
void MemStream::moveStart(int delta) { | void MemStream::moveStart(int delta) { | |||
skipping to change at line 1223 | skipping to change at line 1238 | |||
delete pred; | delete pred; | |||
pred = NULL; | pred = NULL; | |||
} | } | |||
} else { | } else { | |||
pred = NULL; | pred = NULL; | |||
} | } | |||
early = earlyA; | early = earlyA; | |||
eof = gFalse; | eof = gFalse; | |||
inputBits = 0; | inputBits = 0; | |||
clearTable(); | clearTable(); | |||
checkForDecompressionBombs = gTrue; | ||||
} | } | |||
LZWStream::~LZWStream() { | LZWStream::~LZWStream() { | |||
if (pred) { | if (pred) { | |||
delete pred; | delete pred; | |||
} | } | |||
delete str; | delete str; | |||
} | } | |||
Stream *LZWStream::copy() { | Stream *LZWStream::copy() { | |||
if (pred) { | if (pred) { | |||
return new LZWStream(str->copy(), pred->getPredictor(), | return new LZWStream(str->copy(), pred->getPredictor(), | |||
pred->getWidth(), pred->getNComps(), | pred->getWidth(), pred->getNComps(), | |||
pred->getNBits(), early); | pred->getNBits(), early); | |||
} else { | } else { | |||
return new LZWStream(str->copy(), 1, 0, 0, 0, early); | return new LZWStream(str->copy(), 1, 0, 0, 0, early); | |||
} | } | |||
} | } | |||
void LZWStream::disableDecompressionBombChecking() { | ||||
checkForDecompressionBombs = gFalse; | ||||
FilterStream::disableDecompressionBombChecking(); | ||||
} | ||||
int LZWStream::getChar() { | int LZWStream::getChar() { | |||
if (pred) { | if (pred) { | |||
return pred->getChar(); | return pred->getChar(); | |||
} | } | |||
if (eof) { | if (eof) { | |||
return EOF; | return EOF; | |||
} | } | |||
if (seqIndex >= seqLength) { | if (seqIndex >= seqLength) { | |||
if (!processNextCode()) { | if (!processNextCode()) { | |||
return EOF; | return EOF; | |||
skipping to change at line 1388 | skipping to change at line 1409 | |||
nextBits = 10; | nextBits = 10; | |||
else if (nextCode + early == 1024) | else if (nextCode + early == 1024) | |||
nextBits = 11; | nextBits = 11; | |||
else if (nextCode + early == 2048) | else if (nextCode + early == 2048) | |||
nextBits = 12; | nextBits = 12; | |||
} | } | |||
prevCode = code; | prevCode = code; | |||
totalOut += seqLength; | totalOut += seqLength; | |||
// check for a 'decompression bomb' | // check for a 'decompression bomb' | |||
if (totalOut > 50000000 && totalIn < totalOut / 250) { | if (checkForDecompressionBombs && | |||
error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); | totalOut > decompressionBombSizeThreshold && | |||
totalIn < totalOut / decompressionBombRatioThreshold) { | ||||
error(errSyntaxError, getPos(), "Decompression bomb in LZW stream"); | ||||
eof = gTrue; | eof = gTrue; | |||
return gFalse; | return gFalse; | |||
} | } | |||
// reset buffer | // reset buffer | |||
seqIndex = 0; | seqIndex = 0; | |||
return gTrue; | return gTrue; | |||
} | } | |||
skipping to change at line 2640 | skipping to change at line 2663 | |||
39, 46, 53, 60, | 39, 46, 53, 60, | |||
61, 54, 47, | 61, 54, 47, | |||
55, 62, | 55, 62, | |||
63 | 63 | |||
}; | }; | |||
DCTStream::DCTStream(Stream *strA, GBool colorXformA): | DCTStream::DCTStream(Stream *strA, GBool colorXformA): | |||
FilterStream(strA) { | FilterStream(strA) { | |||
int i; | int i; | |||
prepared = gFalse; | ||||
colorXform = colorXformA; | colorXform = colorXformA; | |||
progressive = interleaved = gFalse; | progressive = interleaved = gFalse; | |||
width = height = 0; | width = height = 0; | |||
mcuWidth = mcuHeight = 0; | mcuWidth = mcuHeight = 0; | |||
numComps = 0; | numComps = 0; | |||
comp = 0; | comp = 0; | |||
x = y = 0; | x = y = 0; | |||
for (i = 0; i < 4; ++i) { | for (i = 0; i < 4; ++i) { | |||
frameBuf[i] = NULL; | frameBuf[i] = NULL; | |||
} | } | |||
skipping to change at line 2685 | skipping to change at line 2709 | |||
numDCHuffTables = 0; | numDCHuffTables = 0; | |||
numACHuffTables = 0; | numACHuffTables = 0; | |||
gotJFIFMarker = gFalse; | gotJFIFMarker = gFalse; | |||
gotAdobeMarker = gFalse; | gotAdobeMarker = gFalse; | |||
restartInterval = 0; | restartInterval = 0; | |||
if (!readHeader(gTrue)) { | if (!readHeader(gTrue)) { | |||
// force an EOF condition | // force an EOF condition | |||
progressive = gTrue; | progressive = gTrue; | |||
y = height; | y = height; | |||
prepared = gTrue; | ||||
return; | return; | |||
} | } | |||
// compute MCU size | // compute MCU size | |||
if (numComps == 1) { | if (numComps == 1) { | |||
compInfo[0].hSample = compInfo[0].vSample = 1; | compInfo[0].hSample = compInfo[0].vSample = 1; | |||
} | } | |||
mcuWidth = compInfo[0].hSample; | mcuWidth = compInfo[0].hSample; | |||
mcuHeight = compInfo[0].vSample; | mcuHeight = compInfo[0].vSample; | |||
for (i = 1; i < numComps; ++i) { | for (i = 1; i < numComps; ++i) { | |||
skipping to change at line 2721 | skipping to change at line 2746 | |||
compInfo[2].id == 66) { // ASCII "RGB" | compInfo[2].id == 66) { // ASCII "RGB" | |||
colorXform = 0; | colorXform = 0; | |||
} else { | } else { | |||
colorXform = 1; | colorXform = 1; | |||
} | } | |||
} else { | } else { | |||
colorXform = 0; | colorXform = 0; | |||
} | } | |||
} | } | |||
if (progressive || !interleaved) { | prepared = gFalse; | |||
// allocate a buffer for the whole image | ||||
bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; | ||||
bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; | ||||
if (bufWidth <= 0 || bufHeight <= 0 || | ||||
bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { | ||||
error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); | ||||
y = height; | ||||
return; | ||||
} | ||||
for (i = 0; i < numComps; ++i) { | ||||
frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); | ||||
memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); | ||||
} | ||||
// read the image data | ||||
do { | ||||
restartMarker = 0xd0; | ||||
restart(); | ||||
readScan(); | ||||
} while (readHeader(gFalse)); | ||||
// decode | ||||
decodeImage(); | ||||
// initialize counters | ||||
comp = 0; | ||||
x = 0; | ||||
y = 0; | ||||
} else { | ||||
if (scanInfo.numComps != numComps) { | ||||
error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream"); | ||||
y = height; | ||||
return; | ||||
} | ||||
// allocate a buffer for one row of MCUs | ||||
bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; | ||||
rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); | ||||
rowBufPtr = rowBufEnd = rowBuf; | ||||
// initialize counters | ||||
y = -mcuHeight; | ||||
restartMarker = 0xd0; | ||||
restart(); | ||||
} | ||||
} | } | |||
GBool DCTStream::checkSequentialInterleaved() { | GBool DCTStream::checkSequentialInterleaved() { | |||
GBool headerOk; | GBool headerOk; | |||
str->reset(); | str->reset(); | |||
progressive = interleaved = gFalse; | progressive = interleaved = gFalse; | |||
width = height = 0; | width = height = 0; | |||
numComps = 0; | numComps = 0; | |||
skipping to change at line 2810 | skipping to change at line 2786 | |||
frameBuf[i] = NULL; | frameBuf[i] = NULL; | |||
} | } | |||
gfree(rowBuf); | gfree(rowBuf); | |||
rowBuf = NULL; | rowBuf = NULL; | |||
FilterStream::close(); | FilterStream::close(); | |||
} | } | |||
int DCTStream::getChar() { | int DCTStream::getChar() { | |||
int c; | int c; | |||
if (!prepared) { | ||||
prepare(); | ||||
} | ||||
if (progressive || !interleaved) { | if (progressive || !interleaved) { | |||
if (y >= height) { | if (y >= height) { | |||
return EOF; | return EOF; | |||
} | } | |||
c = frameBuf[comp][y * bufWidth + x]; | c = frameBuf[comp][y * bufWidth + x]; | |||
if (++comp == numComps) { | if (++comp == numComps) { | |||
comp = 0; | comp = 0; | |||
if (++x == width) { | if (++x == width) { | |||
x = 0; | x = 0; | |||
++y; | ++y; | |||
skipping to change at line 2839 | skipping to change at line 2818 | |||
y = height; | y = height; | |||
return EOF; | return EOF; | |||
} | } | |||
} | } | |||
c = *rowBufPtr++; | c = *rowBufPtr++; | |||
} | } | |||
return c; | return c; | |||
} | } | |||
int DCTStream::lookChar() { | int DCTStream::lookChar() { | |||
if (!prepared) { | ||||
prepare(); | ||||
} | ||||
if (progressive || !interleaved) { | if (progressive || !interleaved) { | |||
if (y >= height) { | if (y >= height) { | |||
return EOF; | return EOF; | |||
} | } | |||
return frameBuf[comp][y * bufWidth + x]; | return frameBuf[comp][y * bufWidth + x]; | |||
} else { | } else { | |||
if (rowBufPtr == rowBufEnd) { | if (rowBufPtr == rowBufEnd) { | |||
if (y + mcuHeight >= height) { | if (y + mcuHeight >= height) { | |||
return EOF; | return EOF; | |||
} | } | |||
skipping to change at line 2861 | skipping to change at line 2843 | |||
return EOF; | return EOF; | |||
} | } | |||
} | } | |||
return *rowBufPtr; | return *rowBufPtr; | |||
} | } | |||
} | } | |||
int DCTStream::getBlock(char *blk, int size) { | int DCTStream::getBlock(char *blk, int size) { | |||
int nRead, nAvail, n; | int nRead, nAvail, n; | |||
if (!prepared) { | ||||
prepare(); | ||||
} | ||||
if (progressive || !interleaved) { | if (progressive || !interleaved) { | |||
if (y >= height) { | if (y >= height) { | |||
return 0; | return 0; | |||
} | } | |||
for (nRead = 0; nRead < size; ++nRead) { | for (nRead = 0; nRead < size; ++nRead) { | |||
blk[nRead] = (char)frameBuf[comp][y * bufWidth + x]; | blk[nRead] = (char)frameBuf[comp][y * bufWidth + x]; | |||
if (++comp == numComps) { | if (++comp == numComps) { | |||
comp = 0; | comp = 0; | |||
if (++x == width) { | if (++x == width) { | |||
x = 0; | x = 0; | |||
skipping to change at line 2902 | skipping to change at line 2887 | |||
nAvail = (int)(rowBufEnd - rowBufPtr); | nAvail = (int)(rowBufEnd - rowBufPtr); | |||
n = (nAvail < size - nRead) ? nAvail : size - nRead; | n = (nAvail < size - nRead) ? nAvail : size - nRead; | |||
memcpy(blk + nRead, rowBufPtr, n); | memcpy(blk + nRead, rowBufPtr, n); | |||
rowBufPtr += n; | rowBufPtr += n; | |||
nRead += n; | nRead += n; | |||
} | } | |||
} | } | |||
return nRead; | return nRead; | |||
} | } | |||
void DCTStream::prepare() { | ||||
int i; | ||||
if (progressive || !interleaved) { | ||||
// allocate a buffer for the whole image | ||||
bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; | ||||
bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; | ||||
if (bufWidth <= 0 || bufHeight <= 0 || | ||||
bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) { | ||||
error(errSyntaxError, getPos(), "Invalid image size in DCT stream"); | ||||
y = height; | ||||
prepared = gTrue; | ||||
return; | ||||
} | ||||
#if USE_EXCEPTIONS | ||||
try { | ||||
#endif | ||||
for (i = 0; i < numComps; ++i) { | ||||
frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); | ||||
memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); | ||||
} | ||||
#if USE_EXCEPTIONS | ||||
} catch (GMemException) { | ||||
error(errSyntaxError, getPos(), "Out of memory in DCT stream"); | ||||
y = height; | ||||
prepared = gTrue; | ||||
return; | ||||
} | ||||
#endif | ||||
// read the image data | ||||
do { | ||||
restartMarker = 0xd0; | ||||
restart(); | ||||
readScan(); | ||||
} while (readHeader(gFalse)); | ||||
// decode | ||||
decodeImage(); | ||||
// initialize counters | ||||
comp = 0; | ||||
x = 0; | ||||
y = 0; | ||||
} else { | ||||
if (scanInfo.numComps != numComps) { | ||||
error(errSyntaxError, getPos(), "Invalid scan in sequential DCT stream"); | ||||
y = height; | ||||
prepared = gTrue; | ||||
return; | ||||
} | ||||
// allocate a buffer for one row of MCUs | ||||
bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; | ||||
rowBuf = (Guchar *)gmallocn(numComps * mcuHeight, bufWidth); | ||||
rowBufPtr = rowBufEnd = rowBuf; | ||||
// initialize counters | ||||
y = -mcuHeight; | ||||
restartMarker = 0xd0; | ||||
restart(); | ||||
} | ||||
prepared = gTrue; | ||||
} | ||||
void DCTStream::restart() { | void DCTStream::restart() { | |||
int i; | int i; | |||
inputBits = 0; | inputBits = 0; | |||
restartCtr = restartInterval; | restartCtr = restartInterval; | |||
for (i = 0; i < numComps; ++i) { | for (i = 0; i < numComps; ++i) { | |||
compInfo[i].prevDC = 0; | compInfo[i].prevDC = 0; | |||
} | } | |||
eobRun = 0; | eobRun = 0; | |||
} | } | |||
skipping to change at line 3843 | skipping to change at line 3898 | |||
"Invalid DCT marker in scan <{0:02x}>", c); | "Invalid DCT marker in scan <{0:02x}>", c); | |||
return gFalse; | return gFalse; | |||
} | } | |||
break; | break; | |||
case 0xd9: // EOI | case 0xd9: // EOI | |||
return gFalse; | return gFalse; | |||
case 0xda: // SOS | case 0xda: // SOS | |||
if (!readScanInfo()) { | if (!readScanInfo()) { | |||
return gFalse; | return gFalse; | |||
} | } | |||
if (frame) { | ||||
interleaved = scanInfo.numComps == numComps; | ||||
} | ||||
doScan = gTrue; | doScan = gTrue; | |||
break; | break; | |||
case 0xdb: // DQT | case 0xdb: // DQT | |||
if (!readQuantTables()) { | if (!readQuantTables()) { | |||
return gFalse; | return gFalse; | |||
} | } | |||
break; | break; | |||
case 0xdd: // DRI | case 0xdd: // DRI | |||
if (!readRestartInterval()) { | if (!readRestartInterval()) { | |||
return gFalse; | return gFalse; | |||
skipping to change at line 4008 | skipping to change at line 4066 | |||
if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) { | if (scanInfo.numComps <= 0 || scanInfo.numComps > 4) { | |||
error(errSyntaxError, getPos(), "Bad number of components in DCT stream"); | error(errSyntaxError, getPos(), "Bad number of components in DCT stream"); | |||
scanInfo.numComps = 0; | scanInfo.numComps = 0; | |||
return gFalse; | return gFalse; | |||
} | } | |||
--length; | --length; | |||
if (length != 2 * scanInfo.numComps + 3) { | if (length != 2 * scanInfo.numComps + 3) { | |||
error(errSyntaxError, getPos(), "Bad DCT scan info block"); | error(errSyntaxError, getPos(), "Bad DCT scan info block"); | |||
return gFalse; | return gFalse; | |||
} | } | |||
interleaved = scanInfo.numComps == numComps; | ||||
for (j = 0; j < numComps; ++j) { | for (j = 0; j < numComps; ++j) { | |||
scanInfo.comp[j] = gFalse; | scanInfo.comp[j] = gFalse; | |||
} | } | |||
for (i = 0; i < scanInfo.numComps; ++i) { | for (i = 0; i < scanInfo.numComps; ++i) { | |||
id = str->getChar(); | id = str->getChar(); | |||
// some (broken) DCT streams reuse ID numbers, but at least they | // some (broken) DCT streams reuse ID numbers, but at least they | |||
// keep the components in order, so we check compInfo[i] first to | // keep the components in order, so we check compInfo[i] first to | |||
// work around the problem | // work around the problem | |||
if (id == compInfo[i].id) { | if (id == compInfo[i].id) { | |||
j = i; | j = i; | |||
skipping to change at line 4913 | skipping to change at line 4970 | |||
if (!pred->isOk()) { | if (!pred->isOk()) { | |||
delete pred; | delete pred; | |||
pred = NULL; | pred = NULL; | |||
} | } | |||
} else { | } else { | |||
pred = NULL; | pred = NULL; | |||
} | } | |||
litCodeTab.codes = NULL; | litCodeTab.codes = NULL; | |||
distCodeTab.codes = NULL; | distCodeTab.codes = NULL; | |||
memset(buf, 0, flateWindow); | memset(buf, 0, flateWindow); | |||
checkForDecompressionBombs = gTrue; | ||||
} | } | |||
FlateStream::~FlateStream() { | FlateStream::~FlateStream() { | |||
if (litCodeTab.codes != fixedLitCodeTab.codes) { | if (litCodeTab.codes != fixedLitCodeTab.codes) { | |||
gfree(litCodeTab.codes); | gfree(litCodeTab.codes); | |||
} | } | |||
if (distCodeTab.codes != fixedDistCodeTab.codes) { | if (distCodeTab.codes != fixedDistCodeTab.codes) { | |||
gfree(distCodeTab.codes); | gfree(distCodeTab.codes); | |||
} | } | |||
if (pred) { | if (pred) { | |||
skipping to change at line 4938 | skipping to change at line 4996 | |||
Stream *FlateStream::copy() { | Stream *FlateStream::copy() { | |||
if (pred) { | if (pred) { | |||
return new FlateStream(str->copy(), pred->getPredictor(), | return new FlateStream(str->copy(), pred->getPredictor(), | |||
pred->getWidth(), pred->getNComps(), | pred->getWidth(), pred->getNComps(), | |||
pred->getNBits()); | pred->getNBits()); | |||
} else { | } else { | |||
return new FlateStream(str->copy(), 1, 0, 0, 0); | return new FlateStream(str->copy(), 1, 0, 0, 0); | |||
} | } | |||
} | } | |||
void FlateStream::disableDecompressionBombChecking() { | ||||
checkForDecompressionBombs = gFalse; | ||||
FilterStream::disableDecompressionBombChecking(); | ||||
} | ||||
void FlateStream::reset() { | void FlateStream::reset() { | |||
int cmf, flg; | int cmf, flg; | |||
index = 0; | index = 0; | |||
remain = 0; | remain = 0; | |||
codeBuf = 0; | codeBuf = 0; | |||
codeSize = 0; | codeSize = 0; | |||
compressedBlock = gFalse; | compressedBlock = gFalse; | |||
endOfBlock = gTrue; | endOfBlock = gTrue; | |||
eof = gTrue; | eof = gTrue; | |||
skipping to change at line 5200 | skipping to change at line 5263 | |||
} | } | |||
remain = i; | remain = i; | |||
blockLen -= len; | blockLen -= len; | |||
if (blockLen == 0) | if (blockLen == 0) | |||
endOfBlock = gTrue; | endOfBlock = gTrue; | |||
totalIn += remain; | totalIn += remain; | |||
} | } | |||
totalOut += remain; | totalOut += remain; | |||
// check for a 'decompression bomb' | // check for a 'decompression bomb' | |||
if (totalOut > 50000000 && totalIn < totalOut / 250) { | if (checkForDecompressionBombs && | |||
totalOut > decompressionBombSizeThreshold && | ||||
totalIn < totalOut / decompressionBombRatioThreshold) { | ||||
error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); | error(errSyntaxError, getPos(), "Decompression bomb in flate stream"); | |||
endOfBlock = eof = gTrue; | endOfBlock = eof = gTrue; | |||
remain = 0; | remain = 0; | |||
} | } | |||
return; | return; | |||
err: | err: | |||
error(errSyntaxError, getPos(), "Unexpected end of file in flate stream"); | error(errSyntaxError, getPos(), "Unexpected end of file in flate stream"); | |||
endOfBlock = eof = gTrue; | endOfBlock = eof = gTrue; | |||
skipping to change at line 5251 | skipping to change at line 5316 | |||
if ((c = str->getChar()) == EOF) | if ((c = str->getChar()) == EOF) | |||
goto err; | goto err; | |||
blockLen |= (c & 0xff) << 8; | blockLen |= (c & 0xff) << 8; | |||
if ((c = str->getChar()) == EOF) | if ((c = str->getChar()) == EOF) | |||
goto err; | goto err; | |||
check = c & 0xff; | check = c & 0xff; | |||
if ((c = str->getChar()) == EOF) | if ((c = str->getChar()) == EOF) | |||
goto err; | goto err; | |||
check |= (c & 0xff) << 8; | check |= (c & 0xff) << 8; | |||
if (check != (~blockLen & 0xffff)) | if (check != (~blockLen & 0xffff)) | |||
error(errSyntaxError, getPos(), | goto err; | |||
"Bad uncompressed block length in flate stream"); | ||||
codeBuf = 0; | codeBuf = 0; | |||
codeSize = 0; | codeSize = 0; | |||
totalIn += 4; | totalIn += 4; | |||
// compressed block with fixed codes | // compressed block with fixed codes | |||
} else if (blockHdr == 1) { | } else if (blockHdr == 1) { | |||
compressedBlock = gTrue; | compressedBlock = gTrue; | |||
loadFixedCodes(); | loadFixedCodes(); | |||
// compressed block with dynamic codes | // compressed block with dynamic codes | |||
End of changes. 21 change blocks. | ||||
58 lines changed or deleted | 122 lines changed or added |