summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc232
1 files changed, 151 insertions, 81 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
index d9c295bb12c..a1f7395dd57 100644
--- a/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
+++ b/Build/source/libs/xpdf/xpdf-src/xpdf/JPXStream.cc
@@ -230,6 +230,7 @@ JPXStream::JPXStream(Stream *strA):
{
bufStr = new BufStream(str, 3);
+ decoded = gFalse;
nComps = 0;
bpc = NULL;
width = height = 0;
@@ -270,15 +271,7 @@ Stream *JPXStream::copy() {
void JPXStream::reset() {
img.ySize = 0;
bufStr->reset();
- if (readBoxes() == jpxDecodeFatalError) {
- // readBoxes reported an error, so we go immediately to EOF
- curY = img.ySize >> reduction;
- } else {
- curY = img.yOffsetR;
- }
- curX = img.xOffsetR;
- curComp = 0;
- readBufLen = 0;
+ decoded = gFalse;
}
void JPXStream::close() {
@@ -363,9 +356,25 @@ void JPXStream::close() {
bufStr->close();
}
+void JPXStream::decodeImage() {
+ if (readBoxes() == jpxDecodeFatalError) {
+ // readBoxes reported an error, so we go immediately to EOF
+ curY = img.ySize >> reduction;
+ } else {
+ curY = img.yOffsetR;
+ }
+ curX = img.xOffsetR;
+ curComp = 0;
+ readBufLen = 0;
+ decoded = gTrue;
+}
+
int JPXStream::getChar() {
int c;
+ if (!decoded) {
+ decodeImage();
+ }
if (readBufLen < 8) {
fillReadBuf();
}
@@ -387,6 +396,9 @@ int JPXStream::getChar() {
int JPXStream::lookChar() {
int c;
+ if (!decoded) {
+ decodeImage();
+ }
if (readBufLen < 8) {
fillReadBuf();
}
@@ -420,10 +432,18 @@ void JPXStream::fillReadBuf() {
#else
tileComp = &img.tiles[tileIdx].tileComps[havePalette ? 0 : curComp];
#endif
- tx = jpxFloorDiv(curX - jpxCeilDivPow2(img.tiles[tileIdx].x0, reduction),
- tileComp->hSep);
- ty = jpxFloorDiv(curY - jpxCeilDivPow2(img.tiles[tileIdx].y0, reduction),
- tileComp->vSep);
+ tx = jpxFloorDiv(curX, tileComp->hSep);
+ if (tx < tileComp->x0r) {
+ tx = 0;
+ } else {
+ tx -= tileComp->x0r;
+ }
+ ty = jpxFloorDiv(curY, tileComp->vSep);
+ if (ty < tileComp->y0r) {
+ ty = 0;
+ } else {
+ ty -= tileComp->y0r;
+ }
pix = (int)tileComp->data[ty * tileComp->w + tx];
pixBits = tileComp->prec;
eol = gFalse;
@@ -1061,6 +1081,12 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) {
error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return jpxDecodeFatalError;
}
+ if (r > 0 && ((precinctSize & 0x0f) == 0 ||
+ (precinctSize & 0xf0) == 0)) {
+ error(errSyntaxError, getPos(),
+ "Invalid precinct size in JPX COD marker segment");
+ return jpxDecodeFatalError;
+ }
img.tiles[0].tileComps[0].resLevels[r].precinctWidth =
precinctSize & 0x0f;
img.tiles[0].tileComps[0].resLevels[r].precinctHeight =
@@ -1135,6 +1161,12 @@ JPXDecodeResult JPXStream::readCodestream(Guint len) {
error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return jpxDecodeFatalError;
}
+ if (r > 0 && ((precinctSize & 0x0f) == 0 ||
+ (precinctSize & 0xf0) == 0)) {
+ error(errSyntaxError, getPos(),
+ "Invalid precinct size in JPX COD marker segment");
+ return jpxDecodeFatalError;
+ }
img.tiles[0].tileComps[comp].resLevels[r].precinctWidth =
precinctSize & 0x0f;
img.tiles[0].tileComps[comp].resLevels[r].precinctHeight =
@@ -1579,6 +1611,12 @@ GBool JPXStream::readTilePart() {
error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
+ if (r > 0 && ((precinctSize & 0x0f) == 0 ||
+ (precinctSize & 0xf0) == 0)) {
+ error(errSyntaxError, getPos(),
+ "Invalid precinct size in JPX COD marker segment");
+ return gFalse;
+ }
img.tiles[tileIdx].tileComps[0].resLevels[r].precinctWidth =
precinctSize & 0x0f;
img.tiles[tileIdx].tileComps[0].resLevels[r].precinctHeight =
@@ -1643,6 +1681,12 @@ GBool JPXStream::readTilePart() {
error(errSyntaxError, getPos(), "Error in JPX COD marker segment");
return gFalse;
}
+ if (r > 0 && ((precinctSize & 0x0f) == 0 ||
+ (precinctSize & 0xf0) == 0)) {
+ error(errSyntaxError, getPos(),
+ "Invalid precinct size in JPX COD marker segment");
+ return gFalse;
+ }
img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctWidth =
precinctSize & 0x0f;
img.tiles[tileIdx].tileComps[comp].resLevels[r].precinctHeight =
@@ -1886,9 +1930,9 @@ GBool JPXStream::readTilePart() {
for (comp = 0; comp < img.nComps; ++comp) {
tileComp = &img.tiles[tileIdx].tileComps[comp];
qStyle = tileComp->quantStyle & 0x1f;
- if ((qStyle == 0 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels) ||
+ if ((qStyle == 0 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1) ||
(qStyle == 1 && tileComp->nQuantSteps < 1) ||
- (qStyle == 2 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels)) {
+ (qStyle == 2 && tileComp->nQuantSteps < 3 * tileComp->nDecompLevels + 1)) {
error(errSyntaxError, getPos(), "Too few quant steps in JPX tile part");
return gFalse;
}
@@ -1917,6 +1961,7 @@ GBool JPXStream::readTilePart() {
tile->layer = 0;
tile->done = gFalse;
tile->maxNDecompLevels = 0;
+ tile->maxNPrecincts = 0;
for (comp = 0; comp < img.nComps; ++comp) {
tileComp = &tile->tileComps[comp];
if (tileComp->nDecompLevels > tile->maxNDecompLevels) {
@@ -1926,11 +1971,12 @@ GBool JPXStream::readTilePart() {
tileComp->y0 = jpxCeilDiv(tile->y0, tileComp->vSep);
tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep);
tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->vSep);
- tileComp->w = jpxCeilDivPow2(tileComp->x1, reduction)
- - jpxCeilDivPow2(tileComp->x0, reduction);
- tileComp->h = jpxCeilDivPow2(tileComp->y1, reduction)
- - jpxCeilDivPow2(tileComp->y0, reduction);
- if (tileComp->w == 0 || tileComp->h == 0) {
+ tileComp->x0r = jpxCeilDivPow2(tileComp->x0, reduction);
+ tileComp->w = jpxCeilDivPow2(tileComp->x1, reduction) - tileComp->x0r;
+ tileComp->y0r = jpxCeilDivPow2(tileComp->y0, reduction);
+ tileComp->h = jpxCeilDivPow2(tileComp->y1, reduction) - tileComp->y0r;
+ if (tileComp->w == 0 || tileComp->h == 0 ||
+ tileComp->w > INT_MAX / tileComp->h) {
error(errSyntaxError, getPos(),
"Invalid tile size or sample separation in JPX stream");
return gFalse;
@@ -2008,6 +2054,9 @@ GBool JPXStream::readTilePart() {
resLevel->nPrecincts = (preCol1 - preCol0) * (preRow1 - preRow0);
resLevel->precincts = (JPXPrecinct *)gmallocn(resLevel->nPrecincts,
sizeof(JPXPrecinct));
+ if (resLevel->nPrecincts > tile->maxNPrecincts) {
+ tile->maxNPrecincts = resLevel->nPrecincts;
+ }
for (pre = 0; pre < resLevel->nPrecincts; ++pre) {
resLevel->precincts[pre].subbands = NULL;
}
@@ -2169,14 +2218,15 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
tile = &img.tiles[tileIdx];
- // if the tile is finished, just skip this tile part
- if (tile->done) {
- bufStr->discardChars(tilePartLen);
- return gTrue;
- }
-
// read all packets from this tile-part
while (1) {
+
+ // if the tile is finished, skip any remaining data
+ if (tile->done) {
+ bufStr->discardChars(tilePartLen);
+ return gTrue;
+ }
+
if (tilePartToEOC) {
//~ peek for an EOC marker
cover(93);
@@ -2425,90 +2475,110 @@ GBool JPXStream::readTilePartData(Guint tileIdx,
switch (tile->progOrder) {
case 0: // layer, resolution level, component, precinct
cover(58);
- resLevel = &tile->tileComps[tile->comp].resLevels[tile->res];
- if (++tile->precinct == resLevel->nPrecincts) {
- tile->precinct = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- tile->done = gTrue;
+ do {
+ if (++tile->precinct == tile->maxNPrecincts) {
+ tile->precinct = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ tile->done = gTrue;
+ }
}
}
}
- }
+ } while (!tile->done &&
+ (tile->res > tile->tileComps[tile->comp].nDecompLevels ||
+ tile->precinct >= tile->tileComps[tile->comp]
+ .resLevels[tile->res].nPrecincts));
break;
case 1: // resolution level, layer, component, precinct
cover(59);
- resLevel = &tile->tileComps[tile->comp].resLevels[tile->res];
- if (++tile->precinct == resLevel->nPrecincts) {
- tile->precinct = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- tile->done = gTrue;
+ do {
+ if (++tile->precinct == tile->maxNPrecincts) {
+ tile->precinct = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ tile->done = gTrue;
+ }
}
}
}
- }
+ } while (!tile->done &&
+ (tile->res > tile->tileComps[tile->comp].nDecompLevels ||
+ tile->precinct >= tile->tileComps[tile->comp]
+ .resLevels[tile->res].nPrecincts));
break;
case 2: // resolution level, precinct, component, layer
cover(60);
//~ this is incorrect if there are subsampled components (?)
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- resLevel = &tile->tileComps[tile->comp].resLevels[tile->res];
- if (++tile->precinct == resLevel->nPrecincts) {
- tile->precinct = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- tile->done = gTrue;
+ do {
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->precinct == tile->maxNPrecincts) {
+ tile->precinct = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ tile->done = gTrue;
+ }
}
}
}
- }
+ } while (!tile->done &&
+ (tile->res > tile->tileComps[tile->comp].nDecompLevels ||
+ tile->precinct >= tile->tileComps[tile->comp]
+ .resLevels[tile->res].nPrecincts));
break;
case 3: // precinct, component, resolution level, layer
cover(61);
//~ this is incorrect if there are subsampled components (?)
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- resLevel = &tile->tileComps[tile->comp].resLevels[tile->res];
- if (++tile->precinct == resLevel->nPrecincts) {
- tile->precinct = 0;
- tile->done = gTrue;
+ do {
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ if (++tile->precinct == tile->maxNPrecincts) {
+ tile->precinct = 0;
+ tile->done = gTrue;
+ }
}
}
}
- }
+ } while (!tile->done &&
+ (tile->res > tile->tileComps[tile->comp].nDecompLevels ||
+ tile->precinct >= tile->tileComps[tile->comp]
+ .resLevels[tile->res].nPrecincts));
break;
case 4: // component, precinct, resolution level, layer
cover(62);
- if (++tile->layer == tile->nLayers) {
- tile->layer = 0;
- if (++tile->res == tile->maxNDecompLevels + 1) {
- tile->res = 0;
- resLevel = &tile->tileComps[tile->comp].resLevels[tile->res];
- if (++tile->precinct == resLevel->nPrecincts) {
- tile->precinct = 0;
- if (++tile->comp == img.nComps) {
- tile->comp = 0;
- tile->done = gTrue;
+ do {
+ if (++tile->layer == tile->nLayers) {
+ tile->layer = 0;
+ if (++tile->res == tile->maxNDecompLevels + 1) {
+ tile->res = 0;
+ if (++tile->precinct == tile->maxNPrecincts) {
+ tile->precinct = 0;
+ if (++tile->comp == img.nComps) {
+ tile->comp = 0;
+ tile->done = gTrue;
+ }
}
}
}
- }
+ } while (!tile->done &&
+ (tile->res > tile->tileComps[tile->comp].nDecompLevels ||
+ tile->precinct >= tile->tileComps[tile->comp]
+ .resLevels[tile->res].nPrecincts));
break;
}
}