Index: xpdf-3.02/goo/gmem.cc
===================================================================
--- xpdf-3.02.orig/goo/gmem.cc
+++ xpdf-3.02/goo/gmem.cc
@@ -55,7 +55,15 @@ void *gmalloc(size_t size) GMEM_EXCEP {
   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 @@ void *gmalloc(size_t size) GMEM_EXCEP {
 #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 *grealloc(void *p, size_t size) GME
   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);
     }
@@ -131,7 +155,15 @@ void *grealloc(void *p, size_t size) GME
 #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);
     }
Index: xpdf-3.02/xpdf/JBIG2Stream.cc
===================================================================
--- xpdf-3.02.orig/xpdf/JBIG2Stream.cc
+++ xpdf-3.02/xpdf/JBIG2Stream.cc
@@ -422,12 +422,14 @@ void JBIG2HuffmanDecoder::buildTable(JBI
   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 @@ int JBIG2MMRDecoder::getWhiteCode() {
     ++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 @@ int JBIG2MMRDecoder::getBlackCode() {
     ++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 @@ JBIG2Bitmap::JBIG2Bitmap(Guint segNumA,
   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 @@ JBIG2Bitmap::JBIG2Bitmap(Guint segNumA,
   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 @@ void JBIG2Bitmap::clearToOne() {
 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 @@ void JBIG2Bitmap::combine(JBIG2Bitmap *b
   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 @@ private:
 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 @@ JBIG2SymbolDict::~JBIG2SymbolDict() {
   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 @@ void JBIG2Stream::readSegments() {
       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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
   Guint i, j, k;
   Guchar *p;
 
+  symWidths = NULL;
+
   // symbol dictionary flags
   if (!readUWord(&flags)) {
     goto eofError;
@@ -1466,20 +1493,32 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
   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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
   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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
     } 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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
     } 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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
   }
 
   // allocate symbol widths storage
-  symWidths = NULL;
   if (huff && !refAgg) {
     symWidths = (Guint *)gmallocn(numNewSyms, sizeof(Guint));
   }
@@ -1602,6 +1653,10 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
 	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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
 	    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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
     } 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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
     }
     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 @@ GBool JBIG2Stream::readSymbolDictSeg(Gui
 
   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 @@ void JBIG2Stream::readTextRegionSeg(Guin
       }
     } else {
       error(getPos(), "Invalid segment reference in JBIG2 text region");
+      delete codeTables;
+      return;
     }
   }
   symCodeLen = 0;
@@ -1871,6 +1947,9 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
     } 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 @@ void JBIG2Stream::readTextRegionSeg(Guin
 
   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 @@ void JBIG2Stream::readHalftoneRegionSeg(
     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 @@ void JBIG2Stream::readGenericRegionSeg(G
 
   // 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 @@ JBIG2Bitmap *JBIG2Stream::readGenericBit
   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 @@ JBIG2Bitmap *JBIG2Stream::readGenericBit
 	  ltp = !ltp;
 	}
 	if (ltp) {
-	  bitmap->duplicateRow(y, y-1);
+	  if (y > 0) {
+	    bitmap->duplicateRow(y, y-1);
+	  }
 	  continue;
 	}
       }
@@ -2909,8 +3023,8 @@ void JBIG2Stream::readGenericRefinementR
     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 @@ JBIG2Bitmap *JBIG2Stream::readGenericRef
 	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 @@ JBIG2Bitmap *JBIG2Stream::readGenericRef
 	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) {
