Hi, I've prepared a NMU to fix CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183 in stable and oldstable.
Proposed debdiffs in attachment. Cheers, Giuseppe.
diffstat for xpdf_3.01-9.1+etch5 xpdf_3.01-9.1+etch6 debian/patches/CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch | 995 ++++++++++ xpdf-3.01/debian/changelog | 51 xpdf-3.01/debian/patches/00list | 1 3 files changed, 1047 insertions(+) diff -u xpdf-3.01/debian/changelog xpdf-3.01/debian/changelog --- xpdf-3.01/debian/changelog +++ xpdf-3.01/debian/changelog @@ -1,3 +1,54 @@ +xpdf (3.01-9.1+etch6) oldstable-security; urgency=high + + * Non-maintainer upload. + * This update fixes various security issues (Closes: #524809): + - CVE-2009-0146: Multiple buffer overflows in the JBIG2 decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, and other products allow + remote attackers to cause a denial of service (crash) via a crafted PDF + file, related to (1) JBIG2SymbolDict::setBitmap and (2) + JBIG2Stream::readSymbolDictSeg. + - CVE-2009-0147: Multiple integer overflows in the JBIG2 decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, and other products allow + remote attackers to cause a denial of service (crash) via a crafted PDF + file, related to (1) JBIG2Stream::readSymbolDictSeg, (2) + JBIG2Stream::readSymbolDictSeg, and (3) JBIG2Stream::readGenericBitmap. + - CVE-2009-0165: Integer overflow in the JBIG2 decoder in Xpdf 3.02pl2 and + earlier, as used in Poppler and other products, when running on Mac OS X, + has unspecified impact, related to "g*allocn." + - CVE-2009-0166: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, and other products allows remote attackers to cause a denial + of service (crash) via a crafted PDF file that triggers a free of + uninitialized memory. + - CVE-2009-0799: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (crash) via a crafted PDF file + that triggers an out-of-bounds read. + - CVE-2009-0800: Multiple "input validation flaws" in the JBIG2 decoder in + Xpdf 3.02pl2 and earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, + and other products allow remote attackers to execute arbitrary code via + a crafted PDF file. + - CVE-2009-1179: Integer overflow in the JBIG2 decoder in Xpdf 3.02pl2 and + earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, and other products + allows remote attackers to execute arbitrary code via a crafted PDF file. + - CVE-2009-1180: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to execute arbitrary code via a crafted PDF file that triggers + a free of invalid data. + - CVE-2009-1181: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (crash) via a crafted PDF file that + triggers a NULL pointer dereference. + - CVE-2009-1182: Multiple buffer overflows in the JBIG2 MMR decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, and + other products allow remote attackers to execute arbitrary code via a + crafted PDF file. + - CVE-2009-1183: The JBIG2 MMR decoder in Xpdf 3.02pl2 and earlier, CUPS + 1.3.9 and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (infinite loop and hang) via a + crafted PDF file. + + -- Giuseppe Iuculano <giuse...@iuculano.it> Sat, 02 May 2009 14:12:12 +0200 + xpdf (3.01-9.1+etch5) stable; urgency=low * Remove the strictly versionned dependency on xpdf-utils. Without diff -u xpdf-3.01/debian/patches/00list xpdf-3.01/debian/patches/00list --- xpdf-3.01/debian/patches/00list +++ xpdf-3.01/debian/patches/00list @@ -18,2 +18,3 @@ 41_lesstif_cpp.dpatch +CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch 99_autoconf.dpatch only in patch2: unchanged: --- xpdf-3.01.orig/debian/patches/CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch +++ xpdf-3.01/debian/patches/CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch @@ -0,0 +1,995 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch by Giuseppe Iuculano <giuse...@iuculano.it> +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: No description. + +...@dpatch@ +diff -urNad xpdf-3.01~/goo/gmem.c xpdf-3.01/goo/gmem.c +--- xpdf-3.01~/goo/gmem.c 2009-05-02 14:11:06.000000000 +0200 ++++ xpdf-3.01/goo/gmem.c 2009-05-02 14:11:07.000000000 +0200 +@@ -55,7 +55,7 @@ + + #endif /* DEBUG_MEM */ + +-void *gmalloc(size_t size) { ++void *gmalloc(int size) GMEM_EXCEP { + #ifdef DEBUG_MEM + size_t size1; + char *mem; +@@ -64,7 +64,16 @@ + int lst; + unsigned long *trl, *p; + +- if (size <= 0) ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ ++ if (size == 0) + return NULL; + size1 = gMemDataSize(size); + if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) { +@@ -87,7 +96,16 @@ + #else + void *p; + +- if (size <= 0) ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ ++ if (size == 0) + return NULL; + if (!(p = malloc(size))) { + fprintf(stderr, "Out of memory\n"); +@@ -97,13 +115,22 @@ + #endif + } + +-void *grealloc(void *p, size_t size) { ++void *grealloc(void *p, int size) GMEM_EXCEP { + #ifdef DEBUG_MEM + GMemHdr *hdr; + void *q; + size_t oldSize; + +- if (size <= 0) { ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ ++ if (size == 0) { + if (p) + gfree(p); + return NULL; +@@ -138,7 +165,7 @@ + #endif + } + +-void *gmallocn(int nObjs, size_t objSize) { ++void *gmallocn(int nObjs, int objSize) GMEM_EXCEP { + size_t n; + + if (nObjs == 0) { +@@ -152,7 +179,7 @@ + return gmalloc(n); + } + +-void *greallocn(void *p, int nObjs, size_t objSize) { ++void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP { + size_t n; + + if (nObjs == 0) { +diff -urNad xpdf-3.01~/goo/gmem.h xpdf-3.01/goo/gmem.h +--- xpdf-3.01~/goo/gmem.h 2009-05-02 14:11:06.000000000 +0200 ++++ xpdf-3.01/goo/gmem.h 2009-05-02 14:11:07.000000000 +0200 +@@ -10,6 +10,23 @@ + #define GMEM_H + + #include <stdio.h> ++#include <aconf.h> ++ ++#if USE_EXCEPTIONS ++ ++class GMemException { ++public: ++ GMemException() {} ++ ~GMemException() {} ++}; ++ ++#define GMEM_EXCEP throw(GMemException) ++ ++#else // USE_EXCEPTIONS ++ ++#define GMEM_EXCEP ++ ++#endif // USE_EXCEPTIONS + + #ifdef __cplusplus + extern "C" { +@@ -19,13 +36,13 @@ + * Same as malloc, but prints error message and exits if malloc() + * returns NULL. + */ +-extern void *gmalloc(size_t size); ++extern void *gmalloc(int size) GMEM_EXCEP; + + /* + * Same as realloc, but prints error message and exits if realloc() + * returns NULL. If <p> is NULL, calls malloc instead of realloc(). + */ +-extern void *grealloc(void *p, size_t size); ++extern void *grealloc(void *p, int size) GMEM_EXCEP; + + /* + * These are similar to gmalloc and grealloc, but take an object count +@@ -33,8 +50,8 @@ + * bytes, but there is an additional error check that the total size + * doesn't overflow an int. + */ +-extern void *gmallocn(int nObjs, size_t objSize); +-extern void *greallocn(void *p, int nObjs, size_t objSize); ++extern void *gmallocn(int nObjs, int objSize) GMEM_EXCEP; ++extern void *greallocn(void *p, int nObjs, int objSize) GMEM_EXCEP; + + /* + * Same as free, but checks for and ignores NULL pointers. +diff -urNad xpdf-3.01~/xpdf/JBIG2Stream.cc xpdf-3.01/xpdf/JBIG2Stream.cc +--- xpdf-3.01~/xpdf/JBIG2Stream.cc 2009-05-02 14:11:06.000000000 +0200 ++++ xpdf-3.01/xpdf/JBIG2Stream.cc 2009-05-02 14:11:07.000000000 +0200 +@@ -422,12 +422,14 @@ + table[i] = table[len]; + + // assign prefixes +- i = 0; +- prefix = 0; +- table[i++].prefix = prefix++; +- for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { +- prefix <<= table[i].prefixLen - table[i-1].prefixLen; +- table[i].prefix = prefix++; ++ if (table[0].rangeLen != jbig2HuffmanEOT) { ++ i = 0; ++ prefix = 0; ++ table[i++].prefix = prefix++; ++ for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { ++ prefix <<= table[i].prefixLen - table[i-1].prefixLen; ++ table[i].prefix = prefix++; ++ } + } + } + +@@ -507,7 +509,7 @@ + ++nBytesRead; + } + while (1) { +- if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { ++ if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { +@@ -550,14 +552,15 @@ + ++nBytesRead; + } + while (1) { +- if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { ++ if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { + if (bufLen <= 13) { + code = buf << (13 - bufLen); + } else { + code = buf >> (bufLen - 13); + } + p = &blackTab1[code & 0x7f]; +- } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { ++ } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 && ++ ((buf >> (bufLen - 6)) & 0x03) != 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { +@@ -682,10 +685,12 @@ + w = wA; + h = hA; + line = (wA + 7) >> 3; +- if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- data = NULL; +- return; ++ if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX -1) / line) { ++ // force a call to gmalloc(-1), which will throw an exception ++ h = -1; ++ line = 2; + } ++ + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); + data[h * line] = 0; +@@ -698,8 +703,9 @@ + h = bitmap->h; + line = bitmap->line; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- data = NULL; +- return; ++ // force a call to gmalloc(-1), which will throw an exception ++ h = -1; ++ line = 2; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -754,6 +760,8 @@ + inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) { + if (y < 0 || y >= h || x >= w) { + ptr->p = NULL; ++ ptr->shift = 0; // make gcc happy ++ ptr->x = 0; // make gcc happy + } else if (x < 0) { + ptr->p = &data[y * line]; + ptr->shift = 7; +@@ -798,6 +806,10 @@ + Guint src0, src1, src, dest, s1, s2, m1, m2, m3; + GBool oneByte; + ++ // check for the pathological case where y = -2^31 ++ if (y < -0x7fffffff) { ++ return; ++ } + if (y < 0) { + y0 = -y; + } else { +@@ -1011,8 +1023,13 @@ + JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) + { ++ Guint i; ++ + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); ++ for (i = 0; i < size; ++i) { ++ bitmaps[i] = NULL; ++ } + genericRegionStats = NULL; + refinementRegionStats = NULL; + } +@@ -1021,7 +1038,9 @@ + Guint i; + + for (i = 0; i < size; ++i) { +- delete bitmaps[i]; ++ if (bitmaps[i]) { ++ delete bitmaps[i]; ++ } + } + gfree(bitmaps); + if (genericRegionStats) { +@@ -1289,6 +1308,13 @@ + goto eofError2; + } + ++ // check for missing page information segment ++ if (!pageBitmap && ((segType >= 4 && segType <= 7) || ++ (segType >= 20 && segType <= 43))) { ++ error(getPos(), "First JBIG2 segment associated with a page must be a page information segment"); ++ goto syntaxError; ++ } ++ + // read the segment data + switch (segType) { + case 0: +@@ -1404,6 +1430,8 @@ + Guint i, j, k; + Guchar *p; + ++ symWidths = NULL; ++ + // symbol dictionary flags + if (!readUWord(&flags)) { + goto eofError; +@@ -1459,20 +1487,32 @@ + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { +- seg = findSegment(refSegs[i]); +- if (seg->getType() == jbig2SegSymbolDict) { +- numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); +- } else if (seg->getType() == jbig2SegCodeTable) { +- codeTables->append(seg); ++ if ((seg = findSegment(refSegs[i]))) { ++ if (seg->getType() == jbig2SegSymbolDict) { ++ j = ((JBIG2SymbolDict *)seg)->getSize(); ++ if (numInputSyms > UINT_MAX - j) { ++ error(getPos(), "Too many input symbols in JBIG2 symbol dictionary"); ++ delete codeTables; ++ goto eofError; ++ } ++ numInputSyms += j; ++ } else if (seg->getType() == jbig2SegCodeTable) { ++ codeTables->append(seg); ++ } + } + } ++ if (numInputSyms > UINT_MAX - numNewSyms) { ++ error(getPos(), "Too many input symbols in JBIG2 symbol dictionary"); ++ delete codeTables; ++ goto eofError; ++ } + + // compute symbol code length +- symCodeLen = 0; +- i = 1; +- while (i < numInputSyms + numNewSyms) { ++ symCodeLen = 1; ++ i = (numInputSyms + numNewSyms) >> 1; ++ while (i) { + ++symCodeLen; +- i <<= 1; ++ i >>= 1; + } + + // get the input symbol bitmaps +@@ -1484,13 +1524,14 @@ + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { +- seg = findSegment(refSegs[i]); +- if (seg->getType() == jbig2SegSymbolDict) { +- inputSymbolDict = (JBIG2SymbolDict *)seg; +- for (j = 0; j < inputSymbolDict->getSize(); ++j) { +- bitmaps[k++] = inputSymbolDict->getBitmap(j); +- } +- } ++ if ((seg = findSegment(refSegs[i]))) { ++ if (seg->getType() == jbig2SegSymbolDict) { ++ inputSymbolDict = (JBIG2SymbolDict *)seg; ++ for (j = 0; j < inputSymbolDict->getSize(); ++j) { ++ bitmaps[k++] = inputSymbolDict->getBitmap(j); ++ } ++ } ++ } + } + + // get the Huffman tables +@@ -1503,6 +1544,9 @@ + } else if (huffDH == 1) { + huffDHTable = huffTableE; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDW == 0) { +@@ -1510,17 +1554,26 @@ + } else if (huffDW == 1) { + huffDWTable = huffTableC; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffBMSize == 0) { + huffBMSizeTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffBMSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffAggInst == 0) { + huffAggInstTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffAggInstTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } +@@ -1553,7 +1606,6 @@ + } + + // allocate symbol widths storage +- symWidths = NULL; + if (huff && !refAgg) { + symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); + } +@@ -1595,6 +1647,10 @@ + goto syntaxError; + } + symWidth += dw; ++ if (i >= numNewSyms) { ++ error(getPos(), "Too many symbols in JBIG2 symbol dictionary"); ++ goto syntaxError; ++ } + + // using a collective bitmap, so don't read a bitmap here + if (huff && !refAgg) { +@@ -1631,6 +1687,10 @@ + arithDecoder->decodeInt(&refDX, iardxStats); + arithDecoder->decodeInt(&refDY, iardyStats); + } ++ if (symID >= numInputSyms + i) { ++ error(getPos(), "Invalid symbol ID in JBIG2 symbol dictionary"); ++ goto syntaxError; ++ } + refBitmap = bitmaps[symID]; + bitmaps[numInputSyms + i] = + readGenericRefinementRegion(symWidth, symHeight, +@@ -1697,6 +1757,12 @@ + } else { + arithDecoder->decodeInt(&run, iaexStats); + } ++ if (i + run > numInputSyms + numNewSyms || ++ j + run > numExSyms) { ++ error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary"); ++ delete symbolDict; ++ goto syntaxError; ++ } + if (ex) { + for (cnt = 0; cnt < run; ++cnt) { + symbolDict->setBitmap(j++, bitmaps[i++]->copy()); +@@ -1706,6 +1772,11 @@ + } + ex = !ex; + } ++ if (j != numExSyms) { ++ error(getPos(), "Too few symbols in JBIG2 symbol dictionary"); ++ delete symbolDict; ++ goto syntaxError; ++ } + + for (i = 0; i < numNewSyms; ++i) { + delete bitmaps[numInputSyms + i]; +@@ -1728,6 +1799,10 @@ + + return gTrue; + ++ codeTableError: ++ error(getPos(), "Missing code table in JBIG2 symbol dictionary"); ++ delete codeTables; ++ + syntaxError: + for (i = 0; i < numNewSyms; ++i) { + if (bitmaps[numInputSyms + i]) { +@@ -1830,6 +1905,8 @@ + } + } else { + error(getPos(), "Invalid segment reference in JBIG2 text region"); ++ delete codeTables; ++ return; + } + } + symCodeLen = 0; +@@ -1864,6 +1941,9 @@ + } else if (huffFS == 1) { + huffFSTable = huffTableG; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDS == 0) { +@@ -1873,6 +1953,9 @@ + } else if (huffDS == 2) { + huffDSTable = huffTableJ; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDT == 0) { +@@ -1882,6 +1965,9 @@ + } else if (huffDT == 2) { + huffDTTable = huffTableM; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDW == 0) { +@@ -1889,6 +1975,9 @@ + } else if (huffRDW == 1) { + huffRDWTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDH == 0) { +@@ -1896,6 +1985,9 @@ + } else if (huffRDH == 1) { + huffRDHTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDX == 0) { +@@ -1903,6 +1995,9 @@ + } else if (huffRDX == 1) { + huffRDXTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDY == 0) { +@@ -1910,11 +2005,17 @@ + } else if (huffRDY == 1) { + huffRDYTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRSize == 0) { + huffRSizeTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } +@@ -1941,7 +2042,7 @@ + runLengthTab[35].prefixLen = 0; + runLengthTab[35].rangeLen = jbig2HuffmanEOT; + huffDecoder->buildTable(runLengthTab, 35); +- symCodeTab = (JBIG2HuffmanTable *)gmallocn(numSyms + 1, ++ symCodeTab = (JBIG2HuffmanTable *)gmallocn((numSyms + 1), + sizeof(JBIG2HuffmanTable)); + for (i = 0; i < numSyms; ++i) { + symCodeTab[i].val = i; +@@ -2009,8 +2110,15 @@ + + return; + ++ codeTableError: ++ error(getPos(), "Missing code table in JBIG2 text region"); ++ gfree(codeTables); ++ delete syms; ++ return; ++ + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); ++ return; + } + + JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, +@@ -2263,6 +2371,7 @@ + + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); ++ return; + } + + void JBIG2Stream::readHalftoneRegionSeg(Guint segNum, GBool imm, +@@ -2401,6 +2510,9 @@ + } + + gfree(grayImg); ++ if (skipBitmap) { ++ delete skipBitmap; ++ } + + // combine the region bitmap into the page bitmap + if (imm) { +@@ -2473,7 +2585,7 @@ + + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, +- NULL, atx, aty, mmr ? 0 : length - 18); ++ NULL, atx, aty, mmr ? length - 18 : 0); + + // combine the region bitmap into the page bitmap + if (imm) { +@@ -2495,6 +2607,43 @@ + error(getPos(), "Unexpected EOF in JBIG2 stream"); + } + ++inline void JBIG2Stream::mmrAddPixels(int a1, int blackPixels, ++ int *codingLine, int *a0i, int w) { ++ if (a1 > codingLine[*a0i]) { ++ if (a1 > w) { ++ error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ a1 = w; ++ } ++ if ((*a0i & 1) ^ blackPixels) { ++ ++*a0i; ++ } ++ codingLine[*a0i] = a1; ++ } ++} ++ ++inline void JBIG2Stream::mmrAddPixelsNeg(int a1, int blackPixels, ++ int *codingLine, int *a0i, int w) { ++ if (a1 > codingLine[*a0i]) { ++ if (a1 > w) { ++ error(getPos(), "JBIG2 MMR row is wrong length ({0:d})", a1); ++ a1 = w; ++ } ++ if ((*a0i & 1) ^ blackPixels) { ++ ++*a0i; ++ } ++ codingLine[*a0i] = a1; ++ } else if (a1 < codingLine[*a0i]) { ++ if (a1 < 0) { ++ error(getPos(), "Invalid JBIG2 MMR code"); ++ a1 = 0; ++ } ++ while (*a0i > 0 && a1 <= codingLine[*a0i - 1]) { ++ --*a0i; ++ } ++ codingLine[*a0i] = a1; ++ } ++} ++ + JBIG2Bitmap *JBIG2Stream::readGenericBitmap(GBool mmr, int w, int h, + int templ, GBool tpgdOn, + GBool useSkip, JBIG2Bitmap *skip, +@@ -2507,7 +2656,7 @@ + JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; + int *refLine, *codingLine; + int code1, code2, code3; +- int x, y, a0, pix, i, refI, codingI; ++ int x, y, a0i, b1i, blackPixels, pix, i; + + bitmap = new JBIG2Bitmap(0, w, h); + bitmap->clearToZero(); +@@ -2517,9 +2666,14 @@ + if (mmr) { + + mmrDecoder->reset(); ++ if (w > INT_MAX - 2) { ++ error(getPos(), "Bad width in JBIG2 generic bitmap"); ++ // force a call to gmalloc(-1), which will throw an exception ++ w = -3; ++ } ++ codingLine = (int *)gmallocn(w + 1, sizeof(int)); + refLine = (int *)gmallocn(w + 2, sizeof(int)); +- codingLine = (int *)gmallocn(w + 2, sizeof(int)); +- codingLine[0] = codingLine[1] = w; ++ codingLine[0] = w; + + for (y = 0; y < h; ++y) { + +@@ -2527,128 +2681,157 @@ + for (i = 0; codingLine[i] < w; ++i) { + refLine[i] = codingLine[i]; + } +- refLine[i] = refLine[i + 1] = w; ++ refLine[i++] = w; ++ refLine[i] = w; + + // decode a line +- refI = 0; // b1 = refLine[refI] +- codingI = 0; // a1 = codingLine[codingI] +- a0 = 0; +- do { ++ codingLine[0] = 0; ++ a0i = 0; ++ b1i = 0; ++ blackPixels = 0; ++ // invariant: ++ // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1] <= w ++ // exception at left edge: ++ // codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible ++ // exception at right edge: ++ // refLine[b1i] = refLine[b1i+1] = w is possible ++ while (codingLine[a0i] < w) { + code1 = mmrDecoder->get2DCode(); + switch (code1) { + case twoDimPass: +- if (refLine[refI] < w) { +- a0 = refLine[refI + 1]; +- refI += 2; +- } +- break; ++ mmrAddPixels(refLine[b1i + 1], blackPixels, codingLine, &a0i, w); ++ if (refLine[b1i + 1] < w) { ++ b1i += 2; ++ } ++ break; + case twoDimHoriz: +- if (codingI & 1) { +- code1 = 0; +- do { +- code1 += code3 = mmrDecoder->getBlackCode(); +- } while (code3 >= 64); +- code2 = 0; +- do { +- code2 += code3 = mmrDecoder->getWhiteCode(); +- } while (code3 >= 64); +- } else { +- code1 = 0; +- do { +- code1 += code3 = mmrDecoder->getWhiteCode(); +- } while (code3 >= 64); +- code2 = 0; +- do { +- code2 += code3 = mmrDecoder->getBlackCode(); +- } while (code3 >= 64); +- } +- if (code1 > 0 || code2 > 0) { +- a0 = codingLine[codingI++] = a0 + code1; +- a0 = codingLine[codingI++] = a0 + code2; +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- } +- break; +- case twoDimVert0: +- a0 = codingLine[codingI++] = refLine[refI]; +- if (refLine[refI] < w) { +- ++refI; +- } +- break; +- case twoDimVertR1: +- a0 = codingLine[codingI++] = refLine[refI] + 1; +- if (refLine[refI] < w) { +- ++refI; +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- } +- break; +- case twoDimVertR2: +- a0 = codingLine[codingI++] = refLine[refI] + 2; +- if (refLine[refI] < w) { +- ++refI; +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- } +- break; ++ code1 = code2 = 0; ++ if (blackPixels) { ++ do { ++ code1 += code3 = mmrDecoder->getBlackCode(); ++ } while (code3 >= 64); ++ do { ++ code2 += code3 = mmrDecoder->getWhiteCode(); ++ } while (code3 >= 64); ++ } else { ++ do { ++ code1 += code3 = mmrDecoder->getWhiteCode(); ++ } while (code3 >= 64); ++ do { ++ code2 += code3 = mmrDecoder->getBlackCode(); ++ } while (code3 >= 64); ++ } ++ mmrAddPixels(codingLine[a0i] + code1, blackPixels, ++ codingLine, &a0i, w); ++ if (codingLine[a0i] < w) { ++ mmrAddPixels(codingLine[a0i] + code2, blackPixels ^ 1, ++ codingLine, &a0i, w); ++ } ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ break; + case twoDimVertR3: +- a0 = codingLine[codingI++] = refLine[refI] + 3; +- if (refLine[refI] < w) { +- ++refI; +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- } +- break; +- case twoDimVertL1: +- a0 = codingLine[codingI++] = refLine[refI] - 1; +- if (refI > 0) { +- --refI; +- } else { +- ++refI; +- } +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- break; +- case twoDimVertL2: +- a0 = codingLine[codingI++] = refLine[refI] - 2; +- if (refI > 0) { +- --refI; +- } else { +- ++refI; +- } +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- break; ++ mmrAddPixels(refLine[b1i] + 3, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ ++b1i; ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case twoDimVertR2: ++ mmrAddPixels(refLine[b1i] + 2, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ ++b1i; ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case twoDimVertR1: ++ mmrAddPixels(refLine[b1i] + 1, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ ++b1i; ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case twoDimVert0: ++ mmrAddPixels(refLine[b1i], blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ ++b1i; ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; + case twoDimVertL3: +- a0 = codingLine[codingI++] = refLine[refI] - 3; +- if (refI > 0) { +- --refI; +- } else { +- ++refI; +- } +- while (refLine[refI] <= a0 && refLine[refI] < w) { +- refI += 2; +- } +- break; ++ mmrAddPixelsNeg(refLine[b1i] - 3, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ if (b1i > 0) { ++ --b1i; ++ } else { ++ ++b1i; ++ } ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case twoDimVertL2: ++ mmrAddPixelsNeg(refLine[b1i] - 2, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ if (b1i > 0) { ++ --b1i; ++ } else { ++ ++b1i; ++ } ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case twoDimVertL1: ++ mmrAddPixelsNeg(refLine[b1i] - 1, blackPixels, codingLine, &a0i, w); ++ blackPixels ^= 1; ++ if (codingLine[a0i] < w) { ++ if (b1i > 0) { ++ --b1i; ++ } else { ++ ++b1i; ++ } ++ while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < w) { ++ b1i += 2; ++ } ++ } ++ break; ++ case EOF: ++ mmrAddPixels(w, 0, codingLine, &a0i, w); ++ break; + default: + error(getPos(), "Illegal code in JBIG2 MMR bitmap data"); ++ mmrAddPixels(w, 0, codingLine, &a0i, w); + break; + } +- } while (a0 < w); +- codingLine[codingI++] = w; ++ } + + // convert the run lengths to a bitmap line + i = 0; +- while (codingLine[i] < w) { ++ while (1) { + for (x = codingLine[i]; x < codingLine[i+1]; ++x) { + bitmap->setPixel(x, y); + } ++ if (codingLine[i+1] >= w || codingLine[i+2] >= w) { ++ break; ++ } + i += 2; + } + } +@@ -2696,7 +2879,9 @@ + ltp = !ltp; + } + if (ltp) { +- bitmap->duplicateRow(y, y-1); ++ if (y > 0) { ++ bitmap->duplicateRow(y, y-1); ++ } + continue; + } + } +@@ -2899,8 +3084,8 @@ + return; + } + if (nRefSegs == 1) { +- seg = findSegment(refSegs[0]); +- if (seg->getType() != jbig2SegBitmap) { ++ if (!(seg = findSegment(refSegs[0])) || ++ seg->getType() != jbig2SegBitmap) { + error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } +@@ -2994,6 +3179,10 @@ + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); ++ } else { ++ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy ++ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0; ++ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0; + } + + for (x = 0; x < w; ++x) { +@@ -3065,6 +3254,10 @@ + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); ++ } else { ++ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy ++ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0; ++ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0; + } + + for (x = 0; x < w; ++x) { +diff -urNad xpdf-3.01~/xpdf/JBIG2Stream.h xpdf-3.01/xpdf/JBIG2Stream.h +--- xpdf-3.01~/xpdf/JBIG2Stream.h 2005-08-17 07:34:31.000000000 +0200 ++++ xpdf-3.01/xpdf/JBIG2Stream.h 2009-05-02 14:11:07.000000000 +0200 +@@ -77,6 +77,10 @@ + Guint *refSegs, Guint nRefSegs); + void readGenericRegionSeg(Guint segNum, GBool imm, + GBool lossless, Guint length); ++ void mmrAddPixels(int a1, int blackPixels, ++ int *codingLine, int *a0i, int w); ++ void mmrAddPixelsNeg(int a1, int blackPixels, ++ int *codingLine, int *a0i, int w); + JBIG2Bitmap *readGenericBitmap(GBool mmr, int w, int h, + int templ, GBool tpgdOn, + GBool useSkip, JBIG2Bitmap *skip,
diffstat for xpdf_3.02-1.4 xpdf_3.02-1.4+lenny1 debian/patches/fix-CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch | 563 ++++++++++ xpdf-3.02/debian/changelog | 51 xpdf-3.02/debian/patches/00list | 3 3 files changed, 617 insertions(+) diff -u xpdf-3.02/debian/changelog xpdf-3.02/debian/changelog --- xpdf-3.02/debian/changelog +++ xpdf-3.02/debian/changelog @@ -1,3 +1,54 @@ +xpdf (3.02-1.4+lenny1) stable-security; urgency=high + + * Non-maintainer upload. + * This update fixes various security issues (Closes: #524809): + - CVE-2009-0146: Multiple buffer overflows in the JBIG2 decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, and other products allow + remote attackers to cause a denial of service (crash) via a crafted PDF + file, related to (1) JBIG2SymbolDict::setBitmap and (2) + JBIG2Stream::readSymbolDictSeg. + - CVE-2009-0147: Multiple integer overflows in the JBIG2 decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, and other products allow + remote attackers to cause a denial of service (crash) via a crafted PDF + file, related to (1) JBIG2Stream::readSymbolDictSeg, (2) + JBIG2Stream::readSymbolDictSeg, and (3) JBIG2Stream::readGenericBitmap. + - CVE-2009-0165: Integer overflow in the JBIG2 decoder in Xpdf 3.02pl2 and + earlier, as used in Poppler and other products, when running on Mac OS X, + has unspecified impact, related to "g*allocn." + - CVE-2009-0166: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, and other products allows remote attackers to cause a denial + of service (crash) via a crafted PDF file that triggers a free of + uninitialized memory. + - CVE-2009-0799: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (crash) via a crafted PDF file + that triggers an out-of-bounds read. + - CVE-2009-0800: Multiple "input validation flaws" in the JBIG2 decoder in + Xpdf 3.02pl2 and earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, + and other products allow remote attackers to execute arbitrary code via + a crafted PDF file. + - CVE-2009-1179: Integer overflow in the JBIG2 decoder in Xpdf 3.02pl2 and + earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, and other products + allows remote attackers to execute arbitrary code via a crafted PDF file. + - CVE-2009-1180: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to execute arbitrary code via a crafted PDF file that triggers + a free of invalid data. + - CVE-2009-1181: The JBIG2 decoder in Xpdf 3.02pl2 and earlier, CUPS 1.3.9 + and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (crash) via a crafted PDF file that + triggers a NULL pointer dereference. + - CVE-2009-1182: Multiple buffer overflows in the JBIG2 MMR decoder in Xpdf + 3.02pl2 and earlier, CUPS 1.3.9 and earlier, Poppler before 0.10.6, and + other products allow remote attackers to execute arbitrary code via a + crafted PDF file. + - CVE-2009-1183: The JBIG2 MMR decoder in Xpdf 3.02pl2 and earlier, CUPS + 1.3.9 and earlier, Poppler before 0.10.6, and other products allows remote + attackers to cause a denial of service (infinite loop and hang) via a + crafted PDF file. + + -- Giuseppe Iuculano <giuse...@iuculano.it> Sat, 02 May 2009 10:05:02 +0200 + xpdf (3.02-1.4) unstable; urgency=low * Non-maintainer upload. diff -u xpdf-3.02/debian/patches/00list xpdf-3.02/debian/patches/00list --- xpdf-3.02/debian/patches/00list +++ xpdf-3.02/debian/patches/00list @@ -40,0 +41,3 @@ + +#Fix CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183 +fix-CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch only in patch2: unchanged: --- xpdf-3.02.orig/debian/patches/fix-CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch +++ xpdf-3.02/debian/patches/fix-CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch @@ -0,0 +1,563 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## fix-CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183.dpatch by Giuseppe Iuculano <giuse...@iuculano.it> +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: fix for CVE-2009-0146,0147,0165,0166,0799,0800,1179-1183 + +...@dpatch@ +diff -urNad xpdf-3.02~/goo/gmem.cc xpdf-3.02/goo/gmem.cc +--- xpdf-3.02~/goo/gmem.cc 2007-02-27 23:05:51.000000000 +0100 ++++ xpdf-3.02/goo/gmem.cc 2009-05-01 20:37:19.000000000 +0200 +@@ -55,7 +55,15 @@ + void *data; + unsigned long *trl, *p; + +- if (size <= 0) { ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ if (size == 0) { + return NULL; + } + size1 = gMemDataSize(size); +@@ -91,7 +99,15 @@ + #else + void *p; + +- if (size <= 0) { ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ if (size == 0) { + return NULL; + } + if (!(p = malloc(size))) { +@@ -112,7 +128,15 @@ + void *q; + int oldSize; + +- if (size <= 0) { ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ if (size == 0) { + if (p) { + gfree(p); + } +@@ -131,7 +155,15 @@ + #else + void *q; + +- if (size <= 0) { ++ if (size < 0) { ++#if USE_EXCEPTIONS ++ throw GMemException(); ++#else ++ fprintf(stderr, "Invalid memory allocation size\n"); ++ exit(1); ++#endif ++ } ++ if (size == 0) { + if (p) { + free(p); + } +diff -urNad xpdf-3.02~/xpdf/JBIG2Stream.cc xpdf-3.02/xpdf/JBIG2Stream.cc +--- xpdf-3.02~/xpdf/JBIG2Stream.cc 2007-02-27 23:05:52.000000000 +0100 ++++ xpdf-3.02/xpdf/JBIG2Stream.cc 2009-05-01 20:37:19.000000000 +0200 +@@ -422,12 +422,14 @@ + table[i] = table[len]; + + // assign prefixes +- i = 0; +- prefix = 0; +- table[i++].prefix = prefix++; +- for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { +- prefix <<= table[i].prefixLen - table[i-1].prefixLen; +- table[i].prefix = prefix++; ++ if (table[0].rangeLen != jbig2HuffmanEOT) { ++ i = 0; ++ prefix = 0; ++ table[i++].prefix = prefix++; ++ for (; table[i].rangeLen != jbig2HuffmanEOT; ++i) { ++ prefix <<= table[i].prefixLen - table[i-1].prefixLen; ++ table[i].prefix = prefix++; ++ } + } + } + +@@ -507,7 +509,7 @@ + ++nBytesRead; + } + while (1) { +- if (bufLen >= 7 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { ++ if (bufLen >= 11 && ((buf >> (bufLen - 7)) & 0x7f) == 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { +@@ -550,14 +552,15 @@ + ++nBytesRead; + } + while (1) { +- if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { ++ if (bufLen >= 10 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { + if (bufLen <= 13) { + code = buf << (13 - bufLen); + } else { + code = buf >> (bufLen - 13); + } + p = &blackTab1[code & 0x7f]; +- } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { ++ } else if (bufLen >= 7 && ((buf >> (bufLen - 4)) & 0x0f) == 0 && ++ ((buf >> (bufLen - 6)) & 0x03) != 0) { + if (bufLen <= 12) { + code = buf << (12 - bufLen); + } else { +@@ -683,8 +686,9 @@ + h = hA; + line = (wA + 7) >> 3; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- data = NULL; +- return; ++ // force a call to gmalloc(-1), which will throw an exception ++ h = -1; ++ line = 2; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -698,8 +702,9 @@ + h = bitmap->h; + line = bitmap->line; + if (w <= 0 || h <= 0 || line <= 0 || h >= (INT_MAX - 1) / line) { +- data = NULL; +- return; ++ // force a call to gmalloc(-1), which will throw an exception ++ h = -1; ++ line = 2; + } + // need to allocate one extra guard byte for use in combine() + data = (Guchar *)gmalloc(h * line + 1); +@@ -754,6 +759,8 @@ + inline void JBIG2Bitmap::getPixelPtr(int x, int y, JBIG2BitmapPtr *ptr) { + if (y < 0 || y >= h || x >= w) { + ptr->p = NULL; ++ ptr->shift = 0; // make gcc happy ++ ptr->x = 0; // make gcc happy + } else if (x < 0) { + ptr->p = &data[y * line]; + ptr->shift = 7; +@@ -798,6 +805,10 @@ + Guint src0, src1, src, dest, s1, s2, m1, m2, m3; + GBool oneByte; + ++ // check for the pathological case where y = -2^31 ++ if (y < -0x7fffffff) { ++ return; ++ } + if (y < 0) { + y0 = -y; + } else { +@@ -1011,8 +1022,13 @@ + JBIG2SymbolDict::JBIG2SymbolDict(Guint segNumA, Guint sizeA): + JBIG2Segment(segNumA) + { ++ Guint i; ++ + size = sizeA; + bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); ++ for (i = 0; i < size; ++i) { ++ bitmaps[i] = NULL; ++ } + genericRegionStats = NULL; + refinementRegionStats = NULL; + } +@@ -1021,7 +1037,9 @@ + Guint i; + + for (i = 0; i < size; ++i) { +- delete bitmaps[i]; ++ if (bitmaps[i]) { ++ delete bitmaps[i]; ++ } + } + gfree(bitmaps); + if (genericRegionStats) { +@@ -1296,6 +1314,13 @@ + goto eofError2; + } + ++ // check for missing page information segment ++ if (!pageBitmap && ((segType >= 4 && segType <= 7) || ++ (segType >= 20 && segType <= 43))) { ++ error(getPos(), "First JBIG2 segment associated with a page must be a page information segment"); ++ goto syntaxError; ++ } ++ + // read the segment data + switch (segType) { + case 0: +@@ -1411,6 +1436,8 @@ + Guint i, j, k; + Guchar *p; + ++ symWidths = NULL; ++ + // symbol dictionary flags + if (!readUWord(&flags)) { + goto eofError; +@@ -1466,20 +1493,32 @@ + codeTables = new GList(); + numInputSyms = 0; + for (i = 0; i < nRefSegs; ++i) { +- seg = findSegment(refSegs[i]); +- if (seg->getType() == jbig2SegSymbolDict) { +- numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); +- } else if (seg->getType() == jbig2SegCodeTable) { +- codeTables->append(seg); ++ if ((seg = findSegment(refSegs[i]))) { ++ if (seg->getType() == jbig2SegSymbolDict) { ++ j = ((JBIG2SymbolDict *)seg)->getSize(); ++ if (numInputSyms > UINT_MAX - j) { ++ error(getPos(), "Too many input symbols in JBIG2 symbol dictionary"); ++ delete codeTables; ++ goto eofError; ++ } ++ numInputSyms += j; ++ } else if (seg->getType() == jbig2SegCodeTable) { ++ codeTables->append(seg); ++ } + } + } ++ if (numInputSyms > UINT_MAX - numNewSyms) { ++ error(getPos(), "Too many input symbols in JBIG2 symbol dictionary"); ++ delete codeTables; ++ goto eofError; ++ } + + // compute symbol code length +- symCodeLen = 0; +- i = 1; +- while (i < numInputSyms + numNewSyms) { ++ symCodeLen = 1; ++ i = (numInputSyms + numNewSyms) >> 1; ++ while (i) { + ++symCodeLen; +- i <<= 1; ++ i >>= 1; + } + + // get the input symbol bitmaps +@@ -1491,11 +1530,12 @@ + k = 0; + inputSymbolDict = NULL; + for (i = 0; i < nRefSegs; ++i) { +- seg = findSegment(refSegs[i]); +- if (seg->getType() == jbig2SegSymbolDict) { +- inputSymbolDict = (JBIG2SymbolDict *)seg; +- for (j = 0; j < inputSymbolDict->getSize(); ++j) { +- bitmaps[k++] = inputSymbolDict->getBitmap(j); ++ if ((seg = findSegment(refSegs[i]))) { ++ if (seg->getType() == jbig2SegSymbolDict) { ++ inputSymbolDict = (JBIG2SymbolDict *)seg; ++ for (j = 0; j < inputSymbolDict->getSize(); ++j) { ++ bitmaps[k++] = inputSymbolDict->getBitmap(j); ++ } + } + } + } +@@ -1510,6 +1550,9 @@ + } else if (huffDH == 1) { + huffDHTable = huffTableE; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDW == 0) { +@@ -1517,17 +1560,26 @@ + } else if (huffDW == 1) { + huffDWTable = huffTableC; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffBMSize == 0) { + huffBMSizeTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffBMSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffAggInst == 0) { + huffAggInstTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffAggInstTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } +@@ -1560,7 +1612,6 @@ + } + + // allocate symbol widths storage +- symWidths = NULL; + if (huff && !refAgg) { + symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint)); + } +@@ -1602,6 +1653,10 @@ + goto syntaxError; + } + symWidth += dw; ++ if (i >= numNewSyms) { ++ error(getPos(), "Too many symbols in JBIG2 symbol dictionary"); ++ goto syntaxError; ++ } + + // using a collective bitmap, so don't read a bitmap here + if (huff && !refAgg) { +@@ -1638,6 +1693,10 @@ + arithDecoder->decodeInt(&refDX, iardxStats); + arithDecoder->decodeInt(&refDY, iardyStats); + } ++ if (symID >= numInputSyms + i) { ++ error(getPos(), "Invalid symbol ID in JBIG2 symbol dictionary"); ++ goto syntaxError; ++ } + refBitmap = bitmaps[symID]; + bitmaps[numInputSyms + i] = + readGenericRefinementRegion(symWidth, symHeight, +@@ -1704,6 +1763,12 @@ + } else { + arithDecoder->decodeInt(&run, iaexStats); + } ++ if (i + run > numInputSyms + numNewSyms || ++ j + run > numExSyms) { ++ error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary"); ++ delete symbolDict; ++ goto syntaxError; ++ } + if (ex) { + for (cnt = 0; cnt < run; ++cnt) { + symbolDict->setBitmap(j++, bitmaps[i++]->copy()); +@@ -1713,6 +1778,11 @@ + } + ex = !ex; + } ++ if (j != numExSyms) { ++ error(getPos(), "Too few symbols in JBIG2 symbol dictionary"); ++ delete symbolDict; ++ goto syntaxError; ++ } + + for (i = 0; i < numNewSyms; ++i) { + delete bitmaps[numInputSyms + i]; +@@ -1735,6 +1805,10 @@ + + return gTrue; + ++ codeTableError: ++ error(getPos(), "Missing code table in JBIG2 symbol dictionary"); ++ delete codeTables; ++ + syntaxError: + for (i = 0; i < numNewSyms; ++i) { + if (bitmaps[numInputSyms + i]) { +@@ -1837,6 +1911,8 @@ + } + } else { + error(getPos(), "Invalid segment reference in JBIG2 text region"); ++ delete codeTables; ++ return; + } + } + symCodeLen = 0; +@@ -1871,6 +1947,9 @@ + } else if (huffFS == 1) { + huffFSTable = huffTableG; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDS == 0) { +@@ -1880,6 +1959,9 @@ + } else if (huffDS == 2) { + huffDSTable = huffTableJ; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffDT == 0) { +@@ -1889,6 +1971,9 @@ + } else if (huffDT == 2) { + huffDTTable = huffTableM; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDW == 0) { +@@ -1896,6 +1981,9 @@ + } else if (huffRDW == 1) { + huffRDWTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDH == 0) { +@@ -1903,6 +1991,9 @@ + } else if (huffRDH == 1) { + huffRDHTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDX == 0) { +@@ -1910,6 +2001,9 @@ + } else if (huffRDX == 1) { + huffRDXTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRDY == 0) { +@@ -1917,11 +2011,17 @@ + } else if (huffRDY == 1) { + huffRDYTable = huffTableO; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } + if (huffRSize == 0) { + huffRSizeTable = huffTableA; + } else { ++ if (i >= (Guint)codeTables->getLength()) { ++ goto codeTableError; ++ } + huffRSizeTable = + ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); + } +@@ -2016,8 +2116,15 @@ + + return; + ++ codeTableError: ++ error(getPos(), "Missing code table in JBIG2 text region"); ++ gfree(codeTables); ++ delete syms; ++ return; ++ + eofError: + error(getPos(), "Unexpected EOF in JBIG2 stream"); ++ return; + } + + JBIG2Bitmap *JBIG2Stream::readTextRegion(GBool huff, GBool refine, +@@ -2324,8 +2431,8 @@ + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } +- seg = findSegment(refSegs[0]); +- if (seg->getType() != jbig2SegPatternDict) { ++ if (!(seg = findSegment(refSegs[0])) || ++ seg->getType() != jbig2SegPatternDict) { + error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); + return; + } +@@ -2483,7 +2590,7 @@ + + // read the bitmap + bitmap = readGenericBitmap(mmr, w, h, templ, tpgdOn, gFalse, +- NULL, atx, aty, mmr ? 0 : length - 18); ++ NULL, atx, aty, mmr ? length - 18 : 0); + + // combine the region bitmap into the page bitmap + if (imm) { +@@ -2527,6 +2634,11 @@ + if (mmr) { + + mmrDecoder->reset(); ++ if (w > INT_MAX - 2) { ++ error(getPos(), "Bad width in JBIG2 generic bitmap"); ++ // force a call to gmalloc(-1), which will throw an exception ++ w = -3; ++ } + refLine = (int *)gmallocn(w + 2, sizeof(int)); + codingLine = (int *)gmallocn(w + 2, sizeof(int)); + codingLine[0] = codingLine[1] = w; +@@ -2706,7 +2818,9 @@ + ltp = !ltp; + } + if (ltp) { +- bitmap->duplicateRow(y, y-1); ++ if (y > 0) { ++ bitmap->duplicateRow(y, y-1); ++ } + continue; + } + } +@@ -2909,8 +3023,8 @@ + return; + } + if (nRefSegs == 1) { +- seg = findSegment(refSegs[0]); +- if (seg->getType() != jbig2SegBitmap) { ++ if (!(seg = findSegment(refSegs[0])) || ++ seg->getType() != jbig2SegBitmap) { + error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); + return; + } +@@ -3004,6 +3118,10 @@ + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); ++ } else { ++ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy ++ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0; ++ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0; + } + + for (x = 0; x < w; ++x) { +@@ -3075,6 +3193,10 @@ + tpgrCX2 = refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); + tpgrCX2 = (tpgrCX2 << 1) | refBitmap->nextPixel(&tpgrCXPtr2); ++ } else { ++ tpgrCXPtr0.p = tpgrCXPtr1.p = tpgrCXPtr2.p = NULL; // make gcc happy ++ tpgrCXPtr0.shift = tpgrCXPtr1.shift = tpgrCXPtr2.shift = 0; ++ tpgrCXPtr0.x = tpgrCXPtr1.x = tpgrCXPtr2.x = 0; + } + + for (x = 0; x < w; ++x) {
signature.asc
Description: OpenPGP digital signature