]> www.fi.muni.cz Git - evince.git/commitdiff
Fix for a number of integer overflow bugs discovered by Chris Evans. GNOME_2_8_ANCHOR GPDF_2_8_1
authorDan Williams <dcbw@redhat.com>
Fri, 5 Nov 2004 18:43:19 +0000 (18:43 +0000)
committerMartin Kretzschmar <martink@src.gnome.org>
Fri, 5 Nov 2004 18:43:19 +0000 (18:43 +0000)
2004-11-05  Dan Williams  <dcbw@redhat.com>

* xpdf/Catalog.cc, xpdf/XRef.cc: Fix for a number of integer
overflow bugs discovered by Chris Evans. CAN-2004-0888,
Bug #156729, Red Hat Bug #137420.

pdf/xpdf/Catalog.cc
pdf/xpdf/XRef.cc

index c645fd001be0719f67cd52f722a49ecdf91308ec..8762cd4cb4d1a908436382fbadfc4d26b5805620 100644 (file)
@@ -64,6 +64,15 @@ Catalog::Catalog(XRef *xrefA) {
   }
   pagesSize = numPages0 = (int)obj.getNum();
   obj.free();
+  // The gcc doesnt optimize this away, so this check is ok,
+  // even if it looks like a pagesSize != pagesSize check
+  if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize ||
+      pagesSize*sizeof(Ref)/sizeof(Ref) != pagesSize) {
+    error(-1, "Invalid 'pagesSize'");
+    ok = gFalse;
+    return;
+  }
+
   pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
   pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
   for (i = 0; i < pagesSize; ++i) {
@@ -191,6 +200,11 @@ int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
       }
       if (start >= pagesSize) {
        pagesSize += 32;
+        if (pagesSize*sizeof(Page *)/sizeof(Page *) != pagesSize ||
+            pagesSize*sizeof(Ref)/sizeof(Ref) != pagesSize) {
+          error(-1, "Invalid 'pagesSize' parameter.");
+          goto err3;
+        }
        pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *));
        pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref));
        for (j = pagesSize - 32; j < pagesSize; ++j) {
index e0d82d23c62ef46ddff1a8c771ceeb576c436758..afb787d43c8e10dccdb83f3ad84a3c905c63aa2d 100644 (file)
@@ -96,7 +96,7 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
   }
   nObjects = obj1.getInt();
   obj1.free();
-  if (nObjects == 0) {
+  if (nObjects <= 0) {
     goto err1;
   }
 
@@ -106,7 +106,15 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
   }
   first = obj1.getInt();
   obj1.free();
+  if (first < 0) {
+    goto err1;
+  }
 
+  if (nObjects*sizeof(int)/sizeof(int) != nObjects) {
+    error(-1, "Invalid 'nObjects'");
+    goto err1;
+  }
   objs = new Object[nObjects];
   objNums = (int *)gmalloc(nObjects * sizeof(int));
   offsets = (int *)gmalloc(nObjects * sizeof(int));
@@ -130,6 +138,12 @@ ObjectStream::ObjectStream(XRef *xref, int objStrNumA) {
     offsets[i] = obj2.getInt();
     obj1.free();
     obj2.free();
+    if (objNums[i] < 0 || offsets[i] < 0 ||
+       (i > 0 && offsets[i] < offsets[i-1])) {
+      delete parser;
+      gfree(offsets);
+      goto err1;
+    }
   }
   while (str->getChar() != EOF) ;
   delete parser;
@@ -369,10 +383,21 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
     }
     n = obj.getInt();
     obj.free();
+    if (first < 0 || n < 0 || first + n < 0) {
+      goto err1;
+    }
     if (first + n > size) {
       for (newSize = size ? 2 * size : 1024;
-          first + n > newSize;
+          first + n > newSize && newSize > 0;
           newSize <<= 1) ;
+      if (newSize < 0) {
+       goto err1;
+      }
+      if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+        error(-1, "Invalid 'obj' parameters'");
+        goto err1;
+      }
       entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
       for (i = size; i < newSize; ++i) {
        entries[i].offset = 0xffffffff;
@@ -443,7 +468,7 @@ GBool XRef::readXRefTable(Parser *parser, Guint *pos) {
 
   // check for an 'XRefStm' key
   if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) {
-    pos2 = obj2.getInt();
+    pos2 = (Guint)obj2.getInt();
     readXRef(&pos2);
     if (!ok) {
       goto err1;
@@ -474,7 +499,14 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
   }
   newSize = obj.getInt();
   obj.free();
+  if (newSize < 0) {
+    goto err1;
+  }
   if (newSize > size) {
+    if (newSize * sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+      error(-1, "Invalid 'size' parameter.");
+      return gFalse;
+    }
     entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
     for (i = size; i < newSize; ++i) {
       entries[i].offset = 0xffffffff;
@@ -494,6 +526,9 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
     }
     w[i] = obj2.getInt();
     obj2.free();
+    if (w[i] < 0 || w[i] > 4) {
+      goto err1;
+    }
   }
   obj.free();
 
@@ -513,13 +548,14 @@ GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) {
       }
       n = obj.getInt();
       obj.free();
-      if (!readXRefStreamSection(xrefStr, w, first, n)) {
+      if (first < 0 || n < 0 ||
+         !readXRefStreamSection(xrefStr, w, first, n)) {
        idx.free();
        goto err0;
       }
     }
   } else {
-    if (!readXRefStreamSection(xrefStr, w, 0, size)) {
+    if (!readXRefStreamSection(xrefStr, w, 0, newSize)) {
       idx.free();
       goto err0;
     }
@@ -551,10 +587,20 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
   Guint offset;
   int type, gen, c, newSize, i, j;
 
+  if (first + n < 0) {
+    return gFalse;
+  }
   if (first + n > size) {
     for (newSize = size ? 2 * size : 1024;
-        first + n > newSize;
+        first + n > newSize && newSize > 0;
         newSize <<= 1) ;
+    if (newSize < 0) {
+      return gFalse;
+    }
+    if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+      error(-1, "Invalid 'size' inside xref table.");
+      return gFalse;
+    }
     entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
     for (i = size; i < newSize; ++i) {
       entries[i].offset = 0xffffffff;
@@ -585,24 +631,26 @@ GBool XRef::readXRefStreamSection(Stream *xrefStr, int *w, int first, int n) {
       }
       gen = (gen << 8) + c;
     }
-    switch (type) {
-    case 0:
-      entries[i].offset = offset;
-      entries[i].gen = gen;
-      entries[i].type = xrefEntryFree;
-      break;
-    case 1:
-      entries[i].offset = offset;
-      entries[i].gen = gen;
-      entries[i].type = xrefEntryUncompressed;
-      break;
-    case 2:
-      entries[i].offset = offset;
-      entries[i].gen = gen;
-      entries[i].type = xrefEntryCompressed;
-      break;
-    default:
-      return gFalse;
+    if (entries[i].offset == 0xffffffff) {
+      switch (type) {
+      case 0:
+       entries[i].offset = offset;
+       entries[i].gen = gen;
+       entries[i].type = xrefEntryFree;
+       break;
+      case 1:
+       entries[i].offset = offset;
+       entries[i].gen = gen;
+       entries[i].type = xrefEntryUncompressed;
+       break;
+      case 2:
+       entries[i].offset = offset;
+       entries[i].gen = gen;
+       entries[i].type = xrefEntryCompressed;
+       break;
+      default:
+       return gFalse;
+      }
     }
   }
 
@@ -664,38 +712,48 @@ GBool XRef::constructXRef() {
     // look for object
     } else if (isdigit(*p)) {
       num = atoi(p);
-      do {
-       ++p;
-      } while (*p && isdigit(*p));
-      if (isspace(*p)) {
+      if (num > 0) {
        do {
          ++p;
-       } while (*p && isspace(*p));
-       if (isdigit(*p)) {
-         gen = atoi(p);
+       } while (*p && isdigit(*p));
+       if (isspace(*p)) {
          do {
            ++p;
-         } while (*p && isdigit(*p));
-         if (isspace(*p)) {
+         } while (*p && isspace(*p));
+         if (isdigit(*p)) {
+           gen = atoi(p);
            do {
              ++p;
-           } while (*p && isspace(*p));
-           if (!strncmp(p, "obj", 3)) {
-             if (num >= size) {
-               newSize = (num + 1 + 255) & ~255;
-               entries = (XRefEntry *)
-                           grealloc(entries, newSize * sizeof(XRefEntry));
-               for (i = size; i < newSize; ++i) {
-                 entries[i].offset = 0xffffffff;
-                 entries[i].type = xrefEntryFree;
+           } while (*p && isdigit(*p));
+           if (isspace(*p)) {
+             do {
+               ++p;
+             } while (*p && isspace(*p));
+             if (!strncmp(p, "obj", 3)) {
+               if (num >= size) {
+                 newSize = (num + 1 + 255) & ~255;
+                 if (newSize < 0) {
+                   error(-1, "Bad object number");
+                   return gFalse;
+                 }
+                  if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+                    error(-1, "Invalid 'obj' parameters.");
+                    return gFalse;
+                  }
+                 entries = (XRefEntry *)
+                     grealloc(entries, newSize * sizeof(XRefEntry));
+                 for (i = size; i < newSize; ++i) {
+                   entries[i].offset = 0xffffffff;
+                   entries[i].type = xrefEntryFree;
+                 }
+                 size = newSize;
+               }
+               if (entries[num].type == xrefEntryFree ||
+                   gen >= entries[num].gen) {
+                 entries[num].offset = pos - start;
+                 entries[num].gen = gen;
+                 entries[num].type = xrefEntryUncompressed;
                }
-               size = newSize;
-             }
-             if (entries[num].type == xrefEntryFree ||
-                 gen >= entries[num].gen) {
-               entries[num].offset = pos - start;
-               entries[num].gen = gen;
-               entries[num].type = xrefEntryUncompressed;
              }
            }
          }
@@ -705,6 +763,10 @@ GBool XRef::constructXRef() {
     } else if (!strncmp(p, "endstream", 9)) {
       if (streamEndsLen == streamEndsSize) {
        streamEndsSize += 64;
+        if (streamEndsSize*sizeof(int)/sizeof(int) != streamEndsSize) {
+          error(-1, "Invalid 'endstream' parameter.");
+          return gFalse;
+        }
        streamEnds = (Guint *)grealloc(streamEnds,
                                       streamEndsSize * sizeof(int));
       }