tag 524806 patch
thanks

derived from ubuntu's 0.5.1 patch, here is a patch set for etch's
0.4.5.  i am fairly certain all of these CVEs are addressed in this one.

note vulnerable code not present in etch for CVE-2009-0755/1188.

please test; i've done some basic testing with existing pdfs on my
system, but have by no means done extensive or robust testing.
hopefully nothings been broken.

this may be useful for the etch r9 point release (if not for a DSA)?

good night,
mike
diff -ur poppler-0.4.5/poppler/CairoOutputDev.cc poppler-0.4.5-new/poppler/CairoOutputDev.cc
--- poppler-0.4.5/poppler/CairoOutputDev.cc	2005-12-12 17:24:01.000000000 -0500
+++ poppler-0.4.5-new/poppler/CairoOutputDev.cc	2009-08-04 01:27:24.000000000 -0400
@@ -509,7 +509,7 @@
   cairo_matrix_t matrix;
   int is_identity_transform;
   
-  buffer = (unsigned char *)gmalloc (width * height * 4);
+  buffer = (unsigned char *)gmallocn (width, height * 4);
 
   /* TODO: Do we want to cache these? */
   imgStr = new ImageStream(str, width,
Only in poppler-0.4.5-new/poppler: CairoOutputDev.cc.orig
diff -ur poppler-0.4.5/poppler/JBIG2Stream.cc poppler-0.4.5-new/poppler/JBIG2Stream.cc
--- poppler-0.4.5/poppler/JBIG2Stream.cc	2006-01-10 13:53:54.000000000 -0500
+++ poppler-0.4.5-new/poppler/JBIG2Stream.cc	2009-08-04 01:26:46.000000000 -0400
@@ -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++;
+    }
   }
 }
 
@@ -491,7 +493,7 @@
   }
   if (p->bits < 0) {
     error(str->getPos(), "Bad two dim code in JBIG2 MMR stream");
-    return 0;
+    return EOF;
   }
   bufLen -= p->bits;
   return p->n;
@@ -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 {
@@ -667,6 +670,7 @@
   void combine(JBIG2Bitmap *bitmap, int x, int y, Guint combOp);
   Guchar *getDataPtr() { return data; }
   int getDataSize() { return h * line; }
+  GBool isOk() { return data != NULL; }
 
 private:
 
@@ -762,6 +766,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;
@@ -806,6 +812,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 {
@@ -1226,6 +1236,7 @@
   Guint segNum, segFlags, segType, page, segLength;
   Guint refFlags, nRefSegs;
   Guint *refSegs;
+  int segDataPos;
   int c1, c2, c3;
   Guint i;
 
@@ -1293,6 +1304,16 @@
       goto eofError2;
     }
 
+    // keep track of the start of the segment data 
+    segDataPos = getPos();
+
+    // 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");
+      return;
+    }
+
     // read the segment data
     switch (segType) {
     case 0:
@@ -1368,6 +1389,45 @@
       break;
     }
 
+    // Make sure the segment handler read all of the bytes in the 
+    // segment data, unless this segment is marked as having an
+    // unknown length (section 7.2.7 of the JBIG2 Final Committee Draft)
+
+    if (segLength != 0xffffffff) {
+
+      int segExtraBytes = segDataPos + segLength - getPos();
+      if (segExtraBytes > 0) {
+
+	// If we didn't read all of the bytes in the segment data,
+	// indicate an error, and throw away the rest of the data.
+	
+	// v.3.1.01.13 of the LuraTech PDF Compressor Server will
+	// sometimes generate an extraneous NULL byte at the end of
+	// arithmetic-coded symbol dictionary segments when numNewSyms
+	// == 0.  Segments like this often occur for blank pages.
+	
+	error(getPos(), "%d extraneous byte%s after segment",
+	      segExtraBytes, (segExtraBytes > 1) ? "s" : "");
+	
+	// Burn through the remaining bytes -- inefficient, but
+	// hopefully we're not doing this much
+	
+	int trash;
+	for (int i = segExtraBytes; i > 0; i--) {
+	  readByte(&trash);
+	}
+	
+      } else if (segExtraBytes < 0) {
+	
+	// If we read more bytes than we should have, according to the 
+	// segment length field, note an error.
+	
+	error(getPos(), "Previous segment handler read too many bytes");
+	
+      }
+
+    }
+    
     gfree(refSegs);
   }
 
@@ -1402,6 +1462,8 @@
   Guint i, j, k;
   Guchar *p;
 
+  symWidths = NULL;
+
   // symbol dictionary flags
   if (!readUWord(&flags)) {
     goto eofError;
@@ -1457,20 +1519,38 @@
   codeTables = new GooList();
   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);
+    // This is need by bug 12014, returning gFalse makes it not crash
+    // but we end up with a empty page while acroread is able to render
+    // part of it
+    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);
+      }
+    } else {
+      delete codeTables;
+      return;
     }
   }
+  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
@@ -1480,7 +1560,7 @@
   inputSymbolDict = NULL;
   for (i = 0; i < nRefSegs; ++i) {
     seg = findSegment(refSegs[i]);
-    if (seg->getType() == jbig2SegSymbolDict) {
+    if (seg != NULL && seg->getType() == jbig2SegSymbolDict) {
       inputSymbolDict = (JBIG2SymbolDict *)seg;
       for (j = 0; j < inputSymbolDict->getSize(); ++j) {
 	bitmaps[k++] = inputSymbolDict->getBitmap(j);
@@ -1498,6 +1578,9 @@
     } else if (huffDH == 1) {
       huffDHTable = huffTableE;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffDW == 0) {
@@ -1505,17 +1588,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();
     }
@@ -1548,7 +1640,6 @@
   }
 
   // allocate symbol widths storage
-  symWidths = NULL;
   if (huff && !refAgg) {
     symWidths = (Guint *)gmalloc(numNewSyms * sizeof(Guint));
   }
@@ -1582,6 +1673,10 @@
 	}
       }
       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) {
@@ -1606,6 +1701,7 @@
 #else
 	if (refAggNum == 1) {
 #endif
+
 	  if (huff) {
 	    symID = huffDecoder->readBits(symCodeLen);
 	    huffDecoder->decodeInt(&refDX, huffTableO);
@@ -1684,6 +1780,13 @@
     } else {
       arithDecoder->decodeInt(&run, iaexStats);
     }
+    if (i + run > numInputSyms + numNewSyms ||
+	(ex && j + run > numExSyms)) {
+      error(getPos(), "Too many exported symbols in JBIG2 symbol dictionary");
+      for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL);
+      delete symbolDict;
+      goto syntaxError;
+    }
     if (ex) {
       for (cnt = 0; cnt < run; ++cnt) {
 	symbolDict->setBitmap(j++, bitmaps[i++]->copy());
@@ -1693,6 +1796,12 @@
     }
     ex = !ex;
   }
+  if (j != numExSyms) {
+    error(getPos(), "Too few symbols in JBIG2 symbol dictionary");
+    for ( ; j < numExSyms; ++j) symbolDict->setBitmap(j, NULL);
+    delete symbolDict;
+    goto syntaxError;
+  }
 
   for (i = 0; i < numNewSyms; ++i) {
     delete bitmaps[numInputSyms + i];
@@ -1715,6 +1824,22 @@
 
   return;
 
+ codeTableError:
+  error(getPos(), "Missing code table in JBIG2 dictionary");
+  delete codeTables;
+
+ syntaxError:
+  for (i = 0; i < numNewSyms; ++i) {
+    if (bitmaps[numInputSyms + 1]) {
+      delete bitmaps[numInputSyms +i];
+    }
+  }
+  gfree(bitmaps);
+  if (symWidths) {
+    gfree(symWidths);
+  }
+  return;
+
  eofError:
   error(getPos(), "Unexpected EOF in JBIG2 stream");
 }
@@ -1834,6 +1959,9 @@
     } else if (huffFS == 1) {
       huffFSTable = huffTableG;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffDS == 0) {
@@ -1843,6 +1971,9 @@
     } else if (huffDS == 2) {
       huffDSTable = huffTableJ;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffDT == 0) {
@@ -1852,6 +1983,9 @@
     } else if (huffDT == 2) {
       huffDTTable = huffTableM;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffRDW == 0) {
@@ -1859,6 +1993,9 @@
     } else if (huffRDW == 1) {
       huffRDWTable = huffTableO;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffRDH == 0) {
@@ -1866,6 +2003,9 @@
     } else if (huffRDH == 1) {
       huffRDHTable = huffTableO;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffRDX == 0) {
@@ -1873,6 +2013,9 @@
     } else if (huffRDX == 1) {
       huffRDXTable = huffTableO;
     } else {
+      if (i >= (Guint)codeTables->getLength()) {
+	goto codeTableError;
+      }
       huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable();
     }
     if (huffRDY == 0) {
@@ -1880,11 +2023,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();
     }
@@ -1958,18 +2107,20 @@
 
   gfree(syms);
 
-  // combine the region bitmap into the page bitmap
-  if (imm) {
-    if (pageH == 0xffffffff && y + h > curPageH) {
-      pageBitmap->expand(y + h, pageDefPixel);
-    }
-    pageBitmap->combine(bitmap, x, y, extCombOp);
-    delete bitmap;
+  if (bitmap) {
+    // combine the region bitmap into the page bitmap
+    if (imm) {
+      if (pageH == 0xffffffff && y + h > curPageH) {
+        pageBitmap->expand(y + h, pageDefPixel);
+      }
+      pageBitmap->combine(bitmap, x, y, extCombOp);
+      delete bitmap;
 
-  // store the region bitmap
-  } else {
-    bitmap->setSegNum(segNum);
-    segments->append(bitmap);
+    // store the region bitmap
+    } else {
+      bitmap->setSegNum(segNum);
+      segments->append(bitmap);
+    }
   }
 
   // clean up the Huffman decoder
@@ -1979,8 +2130,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,
@@ -2015,6 +2173,10 @@
 
   // allocate the bitmap
   bitmap = new JBIG2Bitmap(0, w, h);
+  if (!bitmap->isOk()) {
+    delete bitmap;
+    return NULL;
+  }
   if (defPixel) {
     bitmap->clearToOne();
   } else {
@@ -2087,73 +2249,85 @@
 	ri = 0;
       }
       if (ri) {
-	if (huff) {
-	  huffDecoder->decodeInt(&rdw, huffRDWTable);
-	  huffDecoder->decodeInt(&rdh, huffRDHTable);
-	  huffDecoder->decodeInt(&rdx, huffRDXTable);
-	  huffDecoder->decodeInt(&rdy, huffRDYTable);
-	  huffDecoder->decodeInt(&bmSize, huffRSizeTable);
-	  huffDecoder->reset();
+
+        GBool decodeSuccess;
+        if (huff) {
+          decodeSuccess = huffDecoder->decodeInt(&rdw, huffRDWTable);
+          decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdh, huffRDHTable);
+          decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdx, huffRDXTable);
+          decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&rdy, huffRDYTable);
+          decodeSuccess = decodeSuccess && huffDecoder->decodeInt(&bmSize, huffRSizeTable);
+          huffDecoder->reset();
 	  arithDecoder->start();
+        } else {
+          decodeSuccess = arithDecoder->decodeInt(&rdw, iardwStats);
+          decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdh, iardhStats);
+          decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdx, iardxStats);
+          decodeSuccess = decodeSuccess && arithDecoder->decodeInt(&rdy, iardyStats);
+        }
+ 	  
+        if (decodeSuccess && syms[symID])
+        {
+          refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
+          refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
+ 
+          symbolBitmap =
+            readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
+                                        rdh + syms[symID]->getHeight(),
+ 					templ, gFalse, syms[symID],
+ 					refDX, refDY, atx, aty);
+	  //~ do we need to use the bmSize value here (in Huffman mode)?
 	} else {
-	  arithDecoder->decodeInt(&rdw, iardwStats);
-	  arithDecoder->decodeInt(&rdh, iardhStats);
-	  arithDecoder->decodeInt(&rdx, iardxStats);
-	  arithDecoder->decodeInt(&rdy, iardyStats);
-	}
-	refDX = ((rdw >= 0) ? rdw : rdw - 1) / 2 + rdx;
-	refDY = ((rdh >= 0) ? rdh : rdh - 1) / 2 + rdy;
-
-	symbolBitmap =
-	  readGenericRefinementRegion(rdw + syms[symID]->getWidth(),
-				      rdh + syms[symID]->getHeight(),
-				      templ, gFalse, syms[symID],
-				      refDX, refDY, atx, aty);
-	//~ do we need to use the bmSize value here (in Huffman mode)?
-      } else {
-	symbolBitmap = syms[symID];
-      }
-
-      // combine the symbol bitmap into the region bitmap
-      //~ something is wrong here - refCorner shouldn't degenerate into
-      //~   two cases
-      bw = symbolBitmap->getWidth() - 1;
-      bh = symbolBitmap->getHeight() - 1;
-      if (transposed) {
-	switch (refCorner) {
-	case 0: // bottom left
-	  bitmap->combine(symbolBitmap, tt, s, combOp);
-	  break;
-	case 1: // top left
-	  bitmap->combine(symbolBitmap, tt, s, combOp);
-	  break;
-	case 2: // bottom right
-	  bitmap->combine(symbolBitmap, tt - bw, s, combOp);
-	  break;
-	case 3: // top right
-	  bitmap->combine(symbolBitmap, tt - bw, s, combOp);
-	  break;
-	}
-	s += bh;
-      } else {
-	switch (refCorner) {
-	case 0: // bottom left
-	  bitmap->combine(symbolBitmap, s, tt - bh, combOp);
-	  break;
-	case 1: // top left
-	  bitmap->combine(symbolBitmap, s, tt, combOp);
-	  break;
-	case 2: // bottom right
-	  bitmap->combine(symbolBitmap, s, tt - bh, combOp);
-	  break;
-	case 3: // top right
-	  bitmap->combine(symbolBitmap, s, tt, combOp);
-	  break;
+	  symbolBitmap = syms[symID];
 	}
-	s += bw;
-      }
-      if (ri) {
-	delete symbolBitmap;
+
+ 	if (symbolBitmap) {
+ 	  // combine the symbol bitmap into the region bitmap
+ 	  //~ something is wrong here - refCorner shouldn't degenerate into
+ 	  //~   two cases
+ 	  bw = symbolBitmap->getWidth() - 1;
+ 	  bh = symbolBitmap->getHeight() - 1;
+ 	  if (transposed) {
+ 	    switch (refCorner) {
+ 	    case 0: // bottom left
+ 	      bitmap->combine(symbolBitmap, tt, s, combOp);
+ 	      break;
+ 	    case 1: // top left
+ 	      bitmap->combine(symbolBitmap, tt, s, combOp);
+ 	      break;
+ 	    case 2: // bottom right
+ 	      bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ 	      break;
+ 	    case 3: // top right
+	      bitmap->combine(symbolBitmap, tt - bw, s, combOp);
+ 	      break;
+ 	    }
+ 	    s += bh;
+ 	  } else {
+ 	    switch (refCorner) {
+ 	    case 0: // bottom left
+ 	      bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ 	      break;
+ 	    case 1: // top left
+ 	      bitmap->combine(symbolBitmap, s, tt, combOp);
+ 	      break;
+ 	    case 2: // bottom right
+ 	      bitmap->combine(symbolBitmap, s, tt - bh, combOp);
+ 	      break;
+ 	    case 3: // top right
+ 	      bitmap->combine(symbolBitmap, s, tt, combOp);
+ 	      break;
+ 	    }
+ 	    s += bw;
+          }
+          if (ri) {
+            delete symbolBitmap;
+          }
+        } else {
+          // NULL symbolBitmap only happens on error
+          delete bitmap;
+          return NULL;
+        }
       }
 
       // next instance
@@ -2275,7 +2449,7 @@
     return;
   }
   seg = findSegment(refSegs[0]);
-  if (seg->getType() != jbig2SegPatternDict) {
+  if (seg == NULL || seg->getType() != jbig2SegPatternDict) {
     error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment");
     return;
   }
@@ -2318,9 +2492,9 @@
     skipBitmap = new JBIG2Bitmap(0, gridW, gridH);
     skipBitmap->clearToZero();
     for (m = 0; m < gridH; ++m) {
-      xx = gridX + m * stepY;
-      yy = gridY + m * stepX;
       for (n = 0; n < gridW; ++n) {
+	xx = gridX + m * stepY + n * stepX;
+	yy = gridY + m * stepX - n * stepY;
 	if (((xx + (int)patW) >> 8) <= 0 || (xx >> 8) >= (int)w ||
 	    ((yy + (int)patH) >> 8) <= 0 || (yy >> 8) >= (int)h) {
 	  skipBitmap->setPixel(n, m);
@@ -2367,6 +2541,9 @@
   }
 
   gfree(grayImg);
+  if (skipBitmap) {
+    delete skipBitmap;
+  }
 
   // combine the region bitmap into the page bitmap
   if (imm) {
@@ -2439,7 +2616,9 @@
 
   // 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);
+  if (!bitmap)
+    return;
 
   // combine the region bitmap into the page bitmap
   if (imm) {
@@ -2461,6 +2640,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,
@@ -2469,13 +2685,17 @@
   JBIG2Bitmap *bitmap;
   GBool ltp;
   Guint ltpCX, cx, cx0, cx1, cx2;
-  JBIG2BitmapPtr cxPtr0, cxPtr1;
-  JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3;
+  JBIG2BitmapPtr cxPtr0 = {0}, cxPtr1 = {0};
+  JBIG2BitmapPtr atPtr0 = {0}, atPtr1 = {0}, atPtr2 = {0}, atPtr3 = {0};
   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);
+  if (!bitmap->isOk()) {
+    delete bitmap;
+    return NULL;
+  }
   bitmap->clearToZero();
 
   //----- MMR decode
@@ -2483,9 +2703,19 @@
   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;
+    }
+    // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = w
+    // ---> max codingLine size = w + 1
+    // refLine has one extra guard entry at the end
+    // ---> max refLine size = w + 2
+    codingLine = (int *)gmallocn(w + 1, sizeof(int));
     refLine = (int *)gmalloc((w + 2) * sizeof(int));
     codingLine = (int *)gmalloc((w + 2) * sizeof(int));
-    codingLine[0] = codingLine[1] = w;
+    codingLine[0] = w;
 
     for (y = 0; y < h; ++y) {
 
@@ -2493,128 +2723,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;
       }
     }
@@ -2662,7 +2921,9 @@
 	  ltp = !ltp;
 	}
 	if (ltp) {
-	  bitmap->duplicateRow(y, y-1);
+	  if (y > 0) {
+	    bitmap->duplicateRow(y, y-1);
+	  }
 	  continue;
 	}
       }
@@ -2866,7 +3127,7 @@
   }
   if (nRefSegs == 1) {
     seg = findSegment(refSegs[0]);
-    if (seg->getType() != jbig2SegBitmap) {
+    if (seg == NULL || seg->getType() != jbig2SegBitmap) {
       error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment");
       return;
     }
@@ -2915,8 +3176,16 @@
   JBIG2Bitmap *bitmap;
   GBool ltp;
   Guint ltpCX, cx, cx0, cx2, cx3, cx4, tpgrCX0, tpgrCX1, tpgrCX2;
-  JBIG2BitmapPtr cxPtr0, cxPtr1, cxPtr2, cxPtr3, cxPtr4, cxPtr5, cxPtr6;
-  JBIG2BitmapPtr tpgrCXPtr0, tpgrCXPtr1, tpgrCXPtr2;
+  JBIG2BitmapPtr cxPtr0 = {0};
+  JBIG2BitmapPtr cxPtr1 = {0};
+  JBIG2BitmapPtr cxPtr2 = {0};
+  JBIG2BitmapPtr cxPtr3 = {0};
+  JBIG2BitmapPtr cxPtr4 = {0};
+  JBIG2BitmapPtr cxPtr5 = {0};
+  JBIG2BitmapPtr cxPtr6 = {0};
+  JBIG2BitmapPtr tpgrCXPtr0 = {0};
+  JBIG2BitmapPtr tpgrCXPtr1 = {0};
+  JBIG2BitmapPtr tpgrCXPtr2 = {0};
   int x, y, pix;
 
   if (w < 0 || h <= 0 || w >= INT_MAX / h) {
@@ -2925,6 +3194,11 @@
   }
 
   bitmap = new JBIG2Bitmap(0, w, h);
+   if (!bitmap->isOk())
+   {
+     delete bitmap;
+     return NULL;
+   }
   bitmap->clearToZero();
 
   // set up the typical row context
@@ -2965,6 +3239,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) {
@@ -3036,6 +3314,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) {
@@ -3101,6 +3383,12 @@
   }
   pageBitmap = new JBIG2Bitmap(0, pageW, curPageH);
 
+  if (!pageBitmap->isOk()) {
+    delete pageBitmap;
+    pageBitmap = NULL;
+    return;
+  }
+  
   // default pixel value
   if (pageDefPixel) {
     pageBitmap->clearToOne();
@@ -3302,7 +3590,7 @@
   iardwStats->reset();
   iardhStats->reset();
   iariStats->reset();
-  if (iaidStats->getContextSize() == symCodeLen + 1) {
+  if (iaidStats->getContextSize() == 1 << (symCodeLen + 1)) {
     iaidStats->reset();
   } else {
     delete iaidStats;
diff -ur poppler-0.4.5/poppler/JBIG2Stream.h poppler-0.4.5-new/poppler/JBIG2Stream.h
--- poppler-0.4.5/poppler/JBIG2Stream.h	2005-03-03 14:46:00.000000000 -0500
+++ poppler-0.4.5-new/poppler/JBIG2Stream.h	2009-08-04 01:26:46.000000000 -0400
@@ -75,6 +75,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,

Reply via email to