Submitted By:            Randy McMurchy <randy_at_linuxfromscratch_dot_org>
Date:                    2010-11-26
Initial Package Version: 3.0.2
Upstream Status:         Originated upstream
Origin:                  Upstream
Description:             Fixes security holes. This patch is a consolidated patch
                         from the pl1 to pl5 patches from upstream.


diff -Naur xpdf-3.02-orig/fofi/FoFiType1.cc xpdf-3.02/fofi/FoFiType1.cc
--- xpdf-3.02-orig/fofi/FoFiType1.cc	2007-02-27 22:05:51.000000000 +0000
+++ xpdf-3.02/fofi/FoFiType1.cc	2010-11-26 17:22:00.000000000 +0000
@@ -224,7 +224,7 @@
 		code = code * 8 + (*p2 - '0');
 	      }
 	    }
-	    if (code < 256) {
+	    if (code >= 0 && code < 256) {
 	      for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
 	      if (*p == '/') {
 		++p;
diff -Naur xpdf-3.02-orig/goo/gmem.cc xpdf-3.02/goo/gmem.cc
--- xpdf-3.02-orig/goo/gmem.cc	2007-02-27 22:05:51.000000000 +0000
+++ xpdf-3.02/goo/gmem.cc	2010-11-26 17:21:26.000000000 +0000
@@ -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 -Naur xpdf-3.02-orig/splash/Splash.cc xpdf-3.02/splash/Splash.cc
--- xpdf-3.02-orig/splash/Splash.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/splash/Splash.cc	2010-11-26 17:21:44.000000000 +0000
@@ -12,6 +12,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include "gmem.h"
 #include "SplashErrorCodes.h"
 #include "SplashMath.h"
@@ -1912,7 +1913,10 @@
   xq = w % scaledWidth;
 
   // allocate pixel buffer
-  pixBuf = (SplashColorPtr)gmalloc((yp + 1) * w);
+  if (yp < 0 || yp > INT_MAX - 1) {
+    return splashErrBadArg;
+  }
+  pixBuf = (SplashColorPtr)gmallocn(yp + 1, w);
 
   // initialize the pixel pipe
   pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha,
@@ -2208,9 +2212,12 @@
   xq = w % scaledWidth;
 
   // allocate pixel buffers
-  colorBuf = (SplashColorPtr)gmalloc((yp + 1) * w * nComps);
+  if (yp < 0 || yp > INT_MAX - 1 || w > INT_MAX / nComps) {
+    return splashErrBadArg;
+  }
+  colorBuf = (SplashColorPtr)gmallocn(yp + 1, w * nComps);
   if (srcAlpha) {
-    alphaBuf = (Guchar *)gmalloc((yp + 1) * w);
+    alphaBuf = (Guchar *)gmallocn(yp + 1, w);
   } else {
     alphaBuf = NULL;
   }
diff -Naur xpdf-3.02-orig/splash/SplashBitmap.cc xpdf-3.02/splash/SplashBitmap.cc
--- xpdf-3.02-orig/splash/SplashBitmap.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/splash/SplashBitmap.cc	2010-11-26 17:21:44.000000000 +0000
@@ -11,6 +11,7 @@
 #endif
 
 #include <stdio.h>
+#include <limits.h>
 #include "gmem.h"
 #include "SplashErrorCodes.h"
 #include "SplashBitmap.h"
@@ -27,30 +28,48 @@
   mode = modeA;
   switch (mode) {
   case splashModeMono1:
-    rowSize = (width + 7) >> 3;
+    if (width > 0) {
+      rowSize = (width + 7) >> 3;
+    } else {
+      rowSize = -1;
+    }
     break;
   case splashModeMono8:
-    rowSize = width;
+    if (width > 0) {
+      rowSize = width;
+    } else {
+      rowSize = -1;
+    }
     break;
   case splashModeRGB8:
   case splashModeBGR8:
-    rowSize = width * 3;
+    if (width > 0 && width <= INT_MAX / 3) {
+      rowSize = width * 3;
+    } else {
+      rowSize = -1;
+    }
     break;
 #if SPLASH_CMYK
   case splashModeCMYK8:
-    rowSize = width * 4;
+    if (width > 0 && width <= INT_MAX / 4) {
+      rowSize = width * 4;
+    } else {
+      rowSize = -1;
+    }
     break;
 #endif
   }
-  rowSize += rowPad - 1;
-  rowSize -= rowSize % rowPad;
-  data = (SplashColorPtr)gmalloc(rowSize * height);
+  if (rowSize > 0) {
+    rowSize += rowPad - 1;
+    rowSize -= rowSize % rowPad;
+  }
+  data = (SplashColorPtr)gmallocn(height, rowSize);
   if (!topDown) {
     data += (height - 1) * rowSize;
     rowSize = -rowSize;
   }
   if (alphaA) {
-    alpha = (Guchar *)gmalloc(width * height);
+    alpha = (Guchar *)gmallocn(width, height);
   } else {
     alpha = NULL;
   }
diff -Naur xpdf-3.02-orig/splash/SplashErrorCodes.h xpdf-3.02/splash/SplashErrorCodes.h
--- xpdf-3.02-orig/splash/SplashErrorCodes.h	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/splash/SplashErrorCodes.h	2010-11-26 17:21:44.000000000 +0000
@@ -29,4 +29,6 @@
 
 #define splashErrSingularMatrix  8	// matrix is singular
 
+#define splashErrBadArg          9	// bad argument
+
 #endif
diff -Naur xpdf-3.02-orig/xpdf/Gfx.cc xpdf-3.02/xpdf/Gfx.cc
--- xpdf-3.02-orig/xpdf/Gfx.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/Gfx.cc	2010-11-26 17:22:00.000000000 +0000
@@ -461,6 +461,7 @@
     baseMatrix[i] = state->getCTM()[i];
   }
   formDepth = 0;
+  parser = NULL;
   abortCheckCbk = abortCheckCbkA;
   abortCheckCbkData = abortCheckCbkDataA;
 
@@ -500,6 +501,7 @@
     baseMatrix[i] = state->getCTM()[i];
   }
   formDepth = 0;
+  parser = NULL;
   abortCheckCbk = abortCheckCbkA;
   abortCheckCbkData = abortCheckCbkDataA;
 
diff -Naur xpdf-3.02-orig/xpdf/JBIG2Stream.cc xpdf-3.02/xpdf/JBIG2Stream.cc
--- xpdf-3.02-orig/xpdf/JBIG2Stream.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/JBIG2Stream.cc	2010-11-26 17:21:26.000000000 +0000
@@ -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 {
@@ -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 ||
+	(ex && 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) {
@@ -2505,6 +2612,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,
@@ -2517,7 +2661,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();
@@ -2527,9 +2671,18 @@
   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 *)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) {
 
@@ -2537,128 +2690,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;
       }
     }
@@ -2706,7 +2888,9 @@
 	  ltp = !ltp;
 	}
 	if (ltp) {
-	  bitmap->duplicateRow(y, y-1);
+	  if (y > 0) {
+	    bitmap->duplicateRow(y, y-1);
+	  }
 	  continue;
 	}
       }
@@ -2909,8 +3093,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 +3188,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 +3263,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 -Naur xpdf-3.02-orig/xpdf/JBIG2Stream.h xpdf-3.02/xpdf/JBIG2Stream.h
--- xpdf-3.02-orig/xpdf/JBIG2Stream.h	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/JBIG2Stream.h	2010-11-26 17:21:26.000000000 +0000
@@ -78,6 +78,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,
diff -Naur xpdf-3.02-orig/xpdf/PSOutputDev.cc xpdf-3.02/xpdf/PSOutputDev.cc
--- xpdf-3.02-orig/xpdf/PSOutputDev.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/PSOutputDev.cc	2010-11-26 17:21:44.000000000 +0000
@@ -4301,7 +4301,7 @@
 	     width, -height, height);
 
   // allocate a line buffer
-  lineBuf = (Guchar *)gmalloc(4 * width);
+  lineBuf = (Guchar *)gmallocn(width, 4);
 
   // set up to process the data stream
   imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
diff -Naur xpdf-3.02-orig/xpdf/Stream.cc xpdf-3.02/xpdf/Stream.cc
--- xpdf-3.02-orig/xpdf/Stream.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/Stream.cc	2010-11-26 17:21:44.000000000 +0000
@@ -323,6 +323,10 @@
   } else {
     imgLineSize = nVals;
   }
+  if (width > INT_MAX / nComps) {
+    // force a call to gmallocn(-1,...), which will throw an exception
+    imgLineSize = -1;
+  }
   imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar));
   imgIdx = nVals;
 }
@@ -410,15 +414,13 @@
   ok = gFalse;
 
   nVals = width * nComps;
-  if (width <= 0 || nComps <= 0 || nBits <= 0 ||
-      nComps >= INT_MAX / nBits ||
-      width >= INT_MAX / nComps / nBits ||
-      nVals * nBits + 7 < 0) {
-    return;
-  }
   pixBytes = (nComps * nBits + 7) >> 3;
   rowBytes = ((nVals * nBits + 7) >> 3) + pixBytes;
-  if (rowBytes <= 0) {
+  if (width <= 0 || nComps <= 0 || nBits <= 0 ||
+      nComps > gfxColorMaxComps ||
+      nBits > 16 ||
+      width >= INT_MAX / nComps ||      // check for overflow in nVals 
+      nVals >= (INT_MAX - 7) / nBits) { // check for overflow in rowBytes
     return;
   }
   predLine = (Guchar *)gmalloc(rowBytes);
@@ -1245,23 +1247,26 @@
   columns = columnsA;
   if (columns < 1) {
     columns = 1;
-  }
-  if (columns + 4 <= 0) {
-    columns = INT_MAX - 4;
+  } else if (columns > INT_MAX - 2) {
+    columns = INT_MAX - 2;
   }
   rows = rowsA;
   endOfBlock = endOfBlockA;
   black = blackA;
-  refLine = (short *)gmallocn(columns + 3, sizeof(short));
-  codingLine = (short *)gmallocn(columns + 2, sizeof(short));
+  // 0 <= codingLine[0] < codingLine[1] < ... < codingLine[n] = columns
+  // ---> max codingLine size = columns + 1
+  // refLine has one extra guard entry at the end
+  // ---> max refLine size = columns + 2
+  codingLine = (int *)gmallocn(columns + 1, sizeof(int));
+  refLine = (int *)gmallocn(columns + 2, sizeof(int));
 
   eof = gFalse;
   row = 0;
   nextLine2D = encoding < 0;
   inputBits = 0;
-  codingLine[0] = 0;
-  codingLine[1] = refLine[2] = columns;
-  a0 = 1;
+  codingLine[0] = columns;
+  a0i = 0;
+  outputBits = 0;
 
   buf = EOF;
 }
@@ -1280,9 +1285,9 @@
   row = 0;
   nextLine2D = encoding < 0;
   inputBits = 0;
-  codingLine[0] = 0;
-  codingLine[1] = columns;
-  a0 = 1;
+  codingLine[0] = columns;
+  a0i = 0;
+  outputBits = 0;
   buf = EOF;
 
   // skip any initial zero bits and end-of-line marker, and get the 2D
@@ -1299,211 +1304,230 @@
   }
 }
 
+inline void CCITTFaxStream::addPixels(int a1, int blackPixels) {
+  if (a1 > codingLine[a0i]) {
+    if (a1 > columns) {
+      error(getPos(), "CCITTFax row is wrong length (%d)", a1);
+      err = gTrue;
+      a1 = columns;
+    }
+    if ((a0i & 1) ^ blackPixels) {
+      ++a0i;
+    }
+    codingLine[a0i] = a1;
+  }
+}
+
+inline void CCITTFaxStream::addPixelsNeg(int a1, int blackPixels) {
+  if (a1 > codingLine[a0i]) {
+    if (a1 > columns) {
+      error(getPos(), "CCITTFax row is wrong length (%d)", a1);
+      err = gTrue;
+      a1 = columns;
+    }
+    if ((a0i & 1) ^ blackPixels) {
+      ++a0i;
+    }
+    codingLine[a0i] = a1;
+  } else if (a1 < codingLine[a0i]) {
+    if (a1 < 0) {
+      error(getPos(), "Invalid CCITTFax code");
+      err = gTrue;
+      a1 = 0;
+    }
+    while (a0i > 0 && a1 <= codingLine[a0i - 1]) {
+      --a0i;
+    }
+    codingLine[a0i] = a1;
+  }
+}
+
 int CCITTFaxStream::lookChar() {
   short code1, code2, code3;
-  int a0New;
-  GBool err, gotEOL;
-  int ret;
-  int bits, i;
+  int b1i, blackPixels, i, bits;
+  GBool gotEOL;
 
-  // if at eof just return EOF
-  if (eof && codingLine[a0] >= columns) {
-    return EOF;
+  if (buf != EOF) {
+    return buf;
   }
 
   // read the next row
-  err = gFalse;
-  if (codingLine[a0] >= columns) {
+  if (outputBits == 0) {
+
+    // if at eof just return EOF
+    if (eof) {
+      return EOF;
+    }
+
+    err = gFalse;
 
     // 2-D encoding
     if (nextLine2D) {
-      // state:
-      //   a0New = current position in coding line (0 <= a0New <= columns)
-      //   codingLine[a0] = last change in coding line
-      //                    (black-to-white if a0 is even,
-      //                     white-to-black if a0 is odd)
-      //   refLine[b1] = next change in reference line of opposite color
-      //                 to a0
-      // invariants:
-      //   0 <= codingLine[a0] <= a0New
-      //           <= refLine[b1] <= refLine[b1+1] <= columns
-      //   0 <= a0 <= columns+1
-      //   refLine[0] = 0
-      //   refLine[n] = refLine[n+1] = columns
-      //     -- for some 1 <= n <= columns+1
-      // end condition:
-      //   0 = codingLine[0] <= codingLine[1] < codingLine[2] < ...
-      //     < codingLine[n-1] < codingLine[n] = columns
-      //     -- where 1 <= n <= columns+1
       for (i = 0; codingLine[i] < columns; ++i) {
 	refLine[i] = codingLine[i];
       }
-      refLine[i] = refLine[i + 1] = columns;
-      b1 = 1;
-      a0New = codingLine[a0 = 0] = 0;
-      do {
+      refLine[i++] = columns;
+      refLine[i] = columns;
+      codingLine[0] = 0;
+      a0i = 0;
+      b1i = 0;
+      blackPixels = 0;
+      // invariant:
+      // refLine[b1i-1] <= codingLine[a0i] < refLine[b1i] < refLine[b1i+1]
+      //                                                             <= columns
+      // exception at left edge:
+      //   codingLine[a0i = 0] = refLine[b1i = 0] = 0 is possible
+      // exception at right edge:
+      //   refLine[b1i] = refLine[b1i+1] = columns is possible
+      while (codingLine[a0i] < columns) {
 	code1 = getTwoDimCode();
 	switch (code1) {
 	case twoDimPass:
-	  if (refLine[b1] < columns) {
-	    a0New = refLine[b1 + 1];
-	    b1 += 2;
+	  addPixels(refLine[b1i + 1], blackPixels);
+	  if (refLine[b1i + 1] < columns) {
+	    b1i += 2;
 	  }
 	  break;
 	case twoDimHoriz:
-	  if ((a0 & 1) == 0) {
-	    code1 = code2 = 0;
+	  code1 = code2 = 0;
+	  if (blackPixels) {
 	    do {
-	      code1 += code3 = getWhiteCode();
+	      code1 += code3 = getBlackCode();
 	    } while (code3 >= 64);
 	    do {
-	      code2 += code3 = getBlackCode();
+	      code2 += code3 = getWhiteCode();
 	    } while (code3 >= 64);
 	  } else {
-	    code1 = code2 = 0;
 	    do {
-	      code1 += code3 = getBlackCode();
+	      code1 += code3 = getWhiteCode();
 	    } while (code3 >= 64);
 	    do {
-	      code2 += code3 = getWhiteCode();
+	      code2 += code3 = getBlackCode();
 	    } while (code3 >= 64);
 	  }
-	  if (code1 > 0 || code2 > 0) {
-	    if (a0New + code1 <= columns) {
-	      codingLine[a0 + 1] = a0New + code1;
-	    } else {
-	      codingLine[a0 + 1] = columns;
-	    }
-	    ++a0;
-	    if (codingLine[a0] + code2 <= columns) {
-	      codingLine[a0 + 1] = codingLine[a0] + code2;
-	    } else {
-	      codingLine[a0 + 1] = columns;
-	    }
-	    ++a0;
-	    a0New = codingLine[a0];
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	  addPixels(codingLine[a0i] + code1, blackPixels);
+	  if (codingLine[a0i] < columns) {
+	    addPixels(codingLine[a0i] + code2, blackPixels ^ 1);
+	  }
+	  while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	    b1i += 2;
+	  }
+	  break;
+	case twoDimVertR3:
+	  addPixels(refLine[b1i] + 3, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    ++b1i;
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
 	  }
 	  break;
-	case twoDimVert0:
-	  if (refLine[b1] < columns) {
-	    a0New = codingLine[++a0] = refLine[b1];
-	    ++b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	case twoDimVertR2:
+	  addPixels(refLine[b1i] + 2, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    ++b1i;
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
-	  } else {
-	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertR1:
-	  if (refLine[b1] + 1 < columns) {
-	    a0New = codingLine[++a0] = refLine[b1] + 1;
-	    ++b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	  addPixels(refLine[b1i] + 1, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    ++b1i;
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
-	  } else {
-	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
-	case twoDimVertL1:
-	  if (refLine[b1] - 1 > a0New || (a0 == 0 && refLine[b1] == 1)) {
-	    a0New = codingLine[++a0] = refLine[b1] - 1;
-	    --b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	case twoDimVert0:
+	  addPixels(refLine[b1i], blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    ++b1i;
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
 	  }
 	  break;
-	case twoDimVertR2:
-	  if (refLine[b1] + 2 < columns) {
-	    a0New = codingLine[++a0] = refLine[b1] + 2;
-	    ++b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	case twoDimVertL3:
+	  addPixelsNeg(refLine[b1i] - 3, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    if (b1i > 0) {
+	      --b1i;
+	    } else {
+	      ++b1i;
+	    }
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
-	  } else {
-	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
 	case twoDimVertL2:
-	  if (refLine[b1] - 2 > a0New || (a0 == 0 && refLine[b1] == 2)) {
-	    a0New = codingLine[++a0] = refLine[b1] - 2;
-	    --b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	  addPixelsNeg(refLine[b1i] - 2, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    if (b1i > 0) {
+	      --b1i;
+	    } else {
+	      ++b1i;
 	    }
-	  }
-	  break;
-	case twoDimVertR3:
-	  if (refLine[b1] + 3 < columns) {
-	    a0New = codingLine[++a0] = refLine[b1] + 3;
-	    ++b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
-	  } else {
-	    a0New = codingLine[++a0] = columns;
 	  }
 	  break;
-	case twoDimVertL3:
-	  if (refLine[b1] - 3 > a0New || (a0 == 0 && refLine[b1] == 3)) {
-	    a0New = codingLine[++a0] = refLine[b1] - 3;
-	    --b1;
-	    while (refLine[b1] <= a0New && refLine[b1] < columns) {
-	      b1 += 2;
+	case twoDimVertL1:
+	  addPixelsNeg(refLine[b1i] - 1, blackPixels);
+	  blackPixels ^= 1;
+	  if (codingLine[a0i] < columns) {
+	    if (b1i > 0) {
+	      --b1i;
+	    } else {
+	      ++b1i;
+	    }
+	    while (refLine[b1i] <= codingLine[a0i] && refLine[b1i] < columns) {
+	      b1i += 2;
 	    }
 	  }
 	  break;
 	case EOF:
+	  addPixels(columns, 0);
 	  eof = gTrue;
-	  codingLine[a0 = 0] = columns;
-	  return EOF;
+	  break;
 	default:
 	  error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1);
+	  addPixels(columns, 0);
 	  err = gTrue;
 	  break;
 	}
-      } while (codingLine[a0] < columns);
+      }
 
     // 1-D encoding
     } else {
-      codingLine[a0 = 0] = 0;
-      while (1) {
+      codingLine[0] = 0;
+      a0i = 0;
+      blackPixels = 0;
+      while (codingLine[a0i] < columns) {
 	code1 = 0;
-	do {
-	  code1 += code3 = getWhiteCode();
-	} while (code3 >= 64);
-	codingLine[a0+1] = codingLine[a0] + code1;
-	++a0;
-	if (codingLine[a0] >= columns) {
-	  break;
-	}
-	code2 = 0;
-	do {
-	  code2 += code3 = getBlackCode();
-	} while (code3 >= 64);
-	codingLine[a0+1] = codingLine[a0] + code2;
-	++a0;
-	if (codingLine[a0] >= columns) {
-	  break;
+	if (blackPixels) {
+	  do {
+	    code1 += code3 = getBlackCode();
+	  } while (code3 >= 64);
+	} else {
+	  do {
+	    code1 += code3 = getWhiteCode();
+	  } while (code3 >= 64);
 	}
+	addPixels(codingLine[a0i] + code1, blackPixels);
+	blackPixels ^= 1;
       }
     }
 
-    if (codingLine[a0] != columns) {
-      error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]);
-      // force the row to be the correct length
-      while (codingLine[a0] > columns) {
-	--a0;
-      }
-      codingLine[++a0] = columns;
-      err = gTrue;
-    }
-
     // byte-align the row
     if (byteAlign) {
       inputBits &= ~7;
@@ -1562,14 +1586,17 @@
     // this if we know the stream contains end-of-line markers because
     // the "just plow on" technique tends to work better otherwise
     } else if (err && endOfLine) {
-      do {
+      while (1) {
+	code1 = lookBits(13);
 	if (code1 == EOF) {
 	  eof = gTrue;
 	  return EOF;
 	}
+	if ((code1 >> 1) == 0x001) {
+	  break;
+	}
 	eatBits(1);
-	code1 = lookBits(13);
-      } while ((code1 >> 1) != 0x001);
+      }
       eatBits(12); 
       if (encoding > 0) {
 	eatBits(1);
@@ -1577,11 +1604,11 @@
       }
     }
 
-    a0 = 0;
-    outputBits = codingLine[1] - codingLine[0];
-    if (outputBits == 0) {
-      a0 = 1;
-      outputBits = codingLine[2] - codingLine[1];
+    // set up for output
+    if (codingLine[0] > 0) {
+      outputBits = codingLine[a0i = 0];
+    } else {
+      outputBits = codingLine[a0i = 1];
     }
 
     ++row;
@@ -1589,39 +1616,43 @@
 
   // get a byte
   if (outputBits >= 8) {
-    ret = ((a0 & 1) == 0) ? 0xff : 0x00;
-    if ((outputBits -= 8) == 0) {
-      ++a0;
-      if (codingLine[a0] < columns) {
-	outputBits = codingLine[a0 + 1] - codingLine[a0];
-      }
+    buf = (a0i & 1) ? 0x00 : 0xff;
+    outputBits -= 8;
+    if (outputBits == 0 && codingLine[a0i] < columns) {
+      ++a0i;
+      outputBits = codingLine[a0i] - codingLine[a0i - 1];
     }
   } else {
     bits = 8;
-    ret = 0;
+    buf = 0;
     do {
       if (outputBits > bits) {
-	i = bits;
-	bits = 0;
-	if ((a0 & 1) == 0) {
-	  ret |= 0xff >> (8 - i);
+	buf <<= bits;
+	if (!(a0i & 1)) {
+	  buf |= 0xff >> (8 - bits);
 	}
-	outputBits -= i;
+	outputBits -= bits;
+	bits = 0;
       } else {
-	i = outputBits;
-	bits -= outputBits;
-	if ((a0 & 1) == 0) {
-	  ret |= (0xff >> (8 - i)) << bits;
+	buf <<= outputBits;
+	if (!(a0i & 1)) {
+	  buf |= 0xff >> (8 - outputBits);
 	}
+	bits -= outputBits;
 	outputBits = 0;
-	++a0;
-	if (codingLine[a0] < columns) {
-	  outputBits = codingLine[a0 + 1] - codingLine[a0];
+	if (codingLine[a0i] < columns) {
+	  ++a0i;
+	  outputBits = codingLine[a0i] - codingLine[a0i - 1];
+	} else if (bits > 0) {
+	  buf <<= bits;
+	  bits = 0;
 	}
       }
-    } while (bits > 0 && codingLine[a0] < columns);
+    } while (bits);
+  }
+  if (black) {
+    buf ^= 0xff;
   }
-  buf = black ? (ret ^ 0xff) : ret;
   return buf;
 }
 
@@ -1663,6 +1694,9 @@
   code = 0; // make gcc happy
   if (endOfBlock) {
     code = lookBits(12);
+    if (code == EOF) {
+      return 1;
+    }
     if ((code >> 5) == 0) {
       p = &whiteTab1[code];
     } else {
@@ -1675,6 +1709,9 @@
   } else {
     for (n = 1; n <= 9; ++n) {
       code = lookBits(n);
+      if (code == EOF) {
+	return 1;
+      }
       if (n < 9) {
 	code <<= 9 - n;
       }
@@ -1686,6 +1723,9 @@
     }
     for (n = 11; n <= 12; ++n) {
       code = lookBits(n);
+      if (code == EOF) {
+	return 1;
+      }
       if (n < 12) {
 	code <<= 12 - n;
       }
@@ -1711,9 +1751,12 @@
   code = 0; // make gcc happy
   if (endOfBlock) {
     code = lookBits(13);
+    if (code == EOF) {
+      return 1;
+    }
     if ((code >> 7) == 0) {
       p = &blackTab1[code];
-    } else if ((code >> 9) == 0) {
+    } else if ((code >> 9) == 0 && (code >> 7) != 0) {
       p = &blackTab2[(code >> 1) - 64];
     } else {
       p = &blackTab3[code >> 7];
@@ -1725,6 +1768,9 @@
   } else {
     for (n = 2; n <= 6; ++n) {
       code = lookBits(n);
+      if (code == EOF) {
+	return 1;
+      }
       if (n < 6) {
 	code <<= 6 - n;
       }
@@ -1736,6 +1782,9 @@
     }
     for (n = 7; n <= 12; ++n) {
       code = lookBits(n);
+      if (code == EOF) {
+	return 1;
+      }
       if (n < 12) {
 	code <<= 12 - n;
       }
@@ -1749,6 +1798,9 @@
     }
     for (n = 10; n <= 13; ++n) {
       code = lookBits(n);
+      if (code == EOF) {
+	return 1;
+      }
       if (n < 13) {
 	code <<= 13 - n;
       }
@@ -1963,6 +2015,12 @@
     // allocate a buffer for the whole image
     bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth;
     bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight;
+    if (bufWidth <= 0 || bufHeight <= 0 ||
+	bufWidth > INT_MAX / bufWidth / (int)sizeof(int)) {
+      error(getPos(), "Invalid image size in DCT stream");
+      y = height;
+      return;
+    }
     for (i = 0; i < numComps; ++i) {
       frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int));
       memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int));
@@ -3038,6 +3096,11 @@
   }
   scanInfo.firstCoeff = str->getChar();
   scanInfo.lastCoeff = str->getChar();
+  if (scanInfo.firstCoeff < 0 || scanInfo.lastCoeff > 63 ||
+      scanInfo.firstCoeff > scanInfo.lastCoeff) {
+    error(getPos(), "Bad DCT coefficient numbers in scan info block");
+    return gFalse;
+  }
   c = str->getChar();
   scanInfo.ah = (c >> 4) & 0x0f;
   scanInfo.al = c & 0x0f;
diff -Naur xpdf-3.02-orig/xpdf/Stream.h xpdf-3.02/xpdf/Stream.h
--- xpdf-3.02-orig/xpdf/Stream.h	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/Stream.h	2010-11-26 17:21:04.000000000 +0000
@@ -528,13 +528,15 @@
   int row;			// current row
   int inputBuf;			// input buffer
   int inputBits;		// number of bits in input buffer
-  short *refLine;		// reference line changing elements
-  int b1;			// index into refLine
-  short *codingLine;		// coding line changing elements
-  int a0;			// index into codingLine
+  int *codingLine;		// coding line changing elements
+  int *refLine;			// reference line changing elements
+  int a0i;			// index into codingLine
+  GBool err;			// error on current line
   int outputBits;		// remaining ouput bits
   int buf;			// character buffer
 
+  void addPixels(int a1, int black);
+  void addPixelsNeg(int a1, int black);
   short getTwoDimCode();
   short getWhiteCode();
   short getBlackCode();
diff -Naur xpdf-3.02-orig/xpdf/XRef.cc xpdf-3.02/xpdf/XRef.cc
--- xpdf-3.02-orig/xpdf/XRef.cc	2007-02-27 22:05:52.000000000 +0000
+++ xpdf-3.02/xpdf/XRef.cc	2010-11-26 17:21:44.000000000 +0000
@@ -52,6 +52,8 @@
   // generation 0.
   ObjectStream(XRef *xref, int objStrNumA);
 
+  GBool isOk() { return ok; }
+
   ~ObjectStream();
 
   // Return the object number of this object stream.
@@ -67,6 +69,7 @@
   int nObjects;			// number of objects in the stream
   Object *objs;			// the objects (length = nObjects)
   int *objNums;			// the object numbers (length = nObjects)
+  GBool ok;
 };
 
 ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
@@ -80,6 +83,7 @@
   nObjects = 0;
   objs = NULL;
   objNums = NULL;
+  ok = gFalse;
 
   if (!xref->fetch(objStrNum, 0, &objStr)->isStream()) {
     goto err1;
@@ -105,6 +109,13 @@
     goto err1;
   }
 
+  // this is an arbitrary limit to avoid integer overflow problems
+  // in the 'new Object[nObjects]' call (Acrobat apparently limits
+  // object streams to 100-200 objects)
+  if (nObjects > 1000000) {
+    error(-1, "Too many objects in an object stream");
+    goto err1;
+  }
   objs = new Object[nObjects];
   objNums = (int *)gmallocn(nObjects, sizeof(int));
   offsets = (int *)gmallocn(nObjects, sizeof(int));
@@ -161,10 +172,10 @@
   }
 
   gfree(offsets);
+  ok = gTrue;
 
  err1:
   objStr.free();
-  return;
 }
 
 ObjectStream::~ObjectStream() {
@@ -837,6 +848,11 @@
 	delete objStr;
       }
       objStr = new ObjectStream(this, e->offset);
+      if (!objStr->isOk()) {
+	delete objStr;
+	objStr = NULL;
+	goto err;
+      }
     }
     objStr->getObject(e->gen, num, obj);
     break;
