[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

New xpdf vulnerabilities related to CAN-2004-0888



Hi xpdf/cupsys/tetex-bin maintainers, hi Debian security team!

Markus Meissner discovered even more instances of integer overflows
(see CAN-2004-0888), see forwarded message below.

Several packages follow the bad habit to include xpdf source code;
among them are tetex-bin and cupsys, other ones are not supported by
Ubuntu.

I prepared updated Ubuntu packages for xpdf, cupsys and tetex-bin,
which are based on Markus's patches. However, Debian/Ubuntu use
slightly different solutions for the former bugs, so my patches look a
bit different.

Find attached the package interdiffs aganst tetex-bin_2.0.2-23,
xpdf_3.00-9, and cupsys_1.1.20final+rc1-10. Our version numbers do not
directly follow fhese Debian versions, but should apply cleanly to
them.

Thanks for considering and have a nice day!

Martin

----- Forwarded message from Matt Zimmerman <mdz@canonical.com> -----
From: Marcus Meissner <meissner@suse.de>
To: vendor-sec@lst.de
Cc: derekn@foolabs.com
Subject: [vendor-sec] xpdf .... 64bit fun
Date: Fri, 29 Oct 2004 15:50:53 +0200

Hi folks, hi Derek,

Our QA Team noted problems with the xpdf and clones updates on
64bit systems, notably AMD64.

I have identified 2 problems:

- We are using "if (size * sizeof(Foo)/sizeof(Foo) != size)" checks, 
  which operate on "size_t" which is 64bit unsigned long on 64bit systems.

  However Xpdf then goes and calls "g*alloc" its own funny gmalloc/grealloc
  routines.

  Which have size passed into as "int" a 32bit quantity.

  This is happily truncated by the compiler leading again to the mentioned
  overflow.


  I have attached a patch against libgoo to change its arguments from int
  to size_t.

  Applies to xpdf2 and xpdf3.


- Several negative integer conditions went unchecked. I am not sure
  why this did not show up on 32bit systems, but it does on 64bit systems.
  Additionaly, at one place the parser could be made to enter an endless
  loop.

  I have fixed the most obvious places of those problems, more might be in
  there. Patch attached.

  Applies to xpdf2 only, xpdf3 already has checks in place.


The goo patch can be considered final I think.

The underflow patch is yet another layer of checks and patchwork.



I would call this issue public, since it can be reproduced using Chris 
Evans bad4.pdf and bad5.pdf.

Ciao, Marcus

diff -ru xpdf-2.02pl1/xpdf/XRef.cc xpdf-2.02pl1/xpdf/XRef.cc
--- xpdf-2.02pl1/xpdf/XRef.cc	2004-10-29 15:16:45.790089001 +0200
+++ xpdf-2.02pl1/xpdf/XRef.cc	2004-10-29 15:11:54.132168025 +0200
@@ -66,6 +66,8 @@
   start = str->getStart();
   pos = readTrailer();
 
+  entries = NULL;
+
   // if there was a problem with the trailer,
   // try to reconstruct the xref table
   if (pos == 0) {
@@ -76,7 +78,7 @@
 
   // trailer is ok - read the xref table
   } else {
-    if (size*sizeof(XRefEntry)/sizeof(XRefEntry) != size) {
+    if ((size < 0) || (size*sizeof(XRefEntry)/sizeof(XRefEntry) != size)) {
       error(-1, "Invalid 'size' inside xref table.");
       ok = gFalse;
       errCode = errDamaged;
@@ -181,7 +183,7 @@
     n = atoi(p);
     while ('0' <= *p && *p <= '9') ++p;
     while (isspace(*p)) ++p;
-    if (p == buf)
+    if ((p == buf) || (n < 0)) /* must make progress */
       return 0;
     pos1 += (p - buf) + n * 20;
   }
@@ -255,6 +257,10 @@
     }
     s[i] = '\0';
     first = atoi(s);
+    if (first < 0) {
+        error(-1, "Invalid 'first'");
+        goto err2;
+    }
     while ((c = str->lookChar()) != EOF && isspace(c)) {
       str->getChar();
     }
@@ -266,6 +272,10 @@
     }
     s[i] = '\0';
     n = atoi(s);
+    if (n<=0) {
+        error(-1, "Invalid 'n'");
+        goto err2;
+    }
     while ((c = str->lookChar()) != EOF && isspace(c)) {
       str->getChar();
     }
@@ -273,7 +283,7 @@
     // table size
     if (first + n > size) {
       newSize = size + 256;
-      if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+      if ((newSize < 0) || (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize)) {
         error(-1, "Invalid 'newSize'");
         goto err2;
       }
@@ -406,6 +416,10 @@
     // look for object
     } else if (isdigit(*p)) {
       num = atoi(p);
+      if (num < 0) {
+	error(-1, "Invalid 'num' parameters.");
+	return gFalse;
+      }
       do {
 	++p;
       } while (*p && isdigit(*p));
@@ -425,7 +439,7 @@
 	    if (!strncmp(p, "obj", 3)) {
 	      if (num >= size) {
 		newSize = (num + 1 + 255) & ~255;
-	        if (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize) {
+	        if ((newSize < 0) || (newSize*sizeof(XRefEntry)/sizeof(XRefEntry) != newSize)) {
 	          error(-1, "Invalid 'obj' parameters.");
 	          return gFalse;
 	        }

diff -ru xpdf-2.02pl1/goo/gmem.c xpdf-2.02pl1/goo/gmem.c
--- xpdf-2.02pl1/goo/gmem.c	2003-06-16 22:01:26.000000000 +0200
+++ xpdf-2.02pl1/goo/gmem.c	2004-10-29 15:13:34.866919791 +0200
@@ -53,9 +53,9 @@
 
 #endif /* DEBUG_MEM */
 
-void *gmalloc(int size) {
+void *gmalloc(size_t size) {
 #ifdef DEBUG_MEM
-  int size1;
+  size_t size1;
   char *mem;
   GMemHdr *hdr;
   void *data;
@@ -94,11 +94,11 @@
 #endif
 }
 
-void *grealloc(void *p, int size) {
+void *grealloc(void *p, size_t size) {
 #ifdef DEBUG_MEM
   GMemHdr *hdr;
   void *q;
-  int oldSize;
+  size_t oldSize;
 
   if (size == 0) {
     if (p)
@@ -137,7 +137,7 @@
 
 void gfree(void *p) {
 #ifdef DEBUG_MEM
-  int size;
+  size_t size;
   GMemHdr *hdr;
   GMemHdr *prevHdr, *q;
   int lst;
diff -ru xpdf-2.02pl1/goo/gmem.h xpdf-2.02pl1/goo/gmem.h
--- xpdf-2.02pl1/goo/gmem.h	2003-06-16 22:01:26.000000000 +0200
+++ xpdf-2.02pl1/goo/gmem.h	2004-10-29 15:13:50.864027201 +0200
@@ -19,13 +19,13 @@
  * Same as malloc, but prints error message and exits if malloc()
  * returns NULL.
  */
-extern void *gmalloc(int size);
+extern void *gmalloc(size_t size);
 
 /*
  * Same as realloc, but prints error message and exits if realloc()
  * returns NULL.  If <p> is NULL, calls malloc instead of realloc().
  */
-extern void *grealloc(void *p, int size);
+extern void *grealloc(void *p, size_t size);
 
 /*
  * Same as free, but checks for and ignores NULL pointers.





----- End forwarded message -----

-- 
Martin Pitt                       http://www.piware.de
Ubuntu Developer            http://www.ubuntulinux.org
Debian GNU/Linux Developer       http://www.debian.org
diff -u xpdf-3.00/debian/changelog xpdf-3.00/debian/changelog
--- xpdf-3.00/debian/changelog
+++ xpdf-3.00/debian/changelog
@@ -1,3 +1,16 @@
+xpdf (3.00-9ubuntu2) hoary; urgency=low
+
+  * SECURITY UPDATE: fix potential buffer overflow
+  * goo/gmem.[ch]: change declarations of gmalloc and grealloc to use size_t
+    instead of int; int truncated sizes to 32 bits, which made xpdf still
+    vulnerable to integer (and eventually buffer) overflow attacks on 64 bit
+    platforms like amd64.
+  * Thanks to Marcus Meissner <meissner@suse.de> for providing the patch
+  * References:
+    CAN-2004-0889 (incomplete fix in version 3.00-9)
+
+ -- Martin Pitt <mpitt@debian.org>  Mon,  1 Nov 2004 12:00:47 +0100
+
 xpdf (3.00-9ubuntu1) hoary; urgency=low
 
   * Resynchronise with Debian.
only in patch2:
unchanged:
--- xpdf-3.00.orig/goo/gmem.c
+++ xpdf-3.00/goo/gmem.c
@@ -53,9 +53,9 @@
 
 #endif /* DEBUG_MEM */
 
-void *gmalloc(int size) {
+void *gmalloc(size_t size) {
 #ifdef DEBUG_MEM
-  int size1;
+  size_t size1;
   char *mem;
   GMemHdr *hdr;
   void *data;
@@ -94,11 +94,11 @@
 #endif
 }
 
-void *grealloc(void *p, int size) {
+void *grealloc(void *p, size_t size) {
 #ifdef DEBUG_MEM
   GMemHdr *hdr;
   void *q;
-  int oldSize;
+  size_t oldSize;
 
   if (size == 0) {
     if (p)
@@ -137,7 +137,7 @@
 
 void gfree(void *p) {
 #ifdef DEBUG_MEM
-  int size;
+  size_t size;
   GMemHdr *hdr;
   GMemHdr *prevHdr, *q;
   int lst;
only in patch2:
unchanged:
--- xpdf-3.00.orig/goo/gmem.h
+++ xpdf-3.00/goo/gmem.h
@@ -19,13 +19,13 @@
  * Same as malloc, but prints error message and exits if malloc()
  * returns NULL.
  */
-extern void *gmalloc(int size);
+extern void *gmalloc(size_t size);
 
 /*
  * Same as realloc, but prints error message and exits if realloc()
  * returns NULL.  If <p> is NULL, calls malloc instead of realloc().
  */
-extern void *grealloc(void *p, int size);
+extern void *grealloc(void *p, size_t size);
 
 /*
  * Same as free, but checks for and ignores NULL pointers.
diff -u cupsys-1.1.20final+rc1/debian/changelog cupsys-1.1.20final+rc1/debian/changelog
--- cupsys-1.1.20final+rc1/debian/changelog
+++ cupsys-1.1.20final+rc1/debian/changelog
@@ -1,3 +1,15 @@
+cupsys (1.1.20final+rc1-10ubuntu3) hoary; urgency=low
+
+  * SECURITY: still CAN-2004-0888. Updated patch 36pdftopsoverflow.patch:
+    - pdftops/gmem.[ch]: change declarations of gmalloc and grealloc to use size_t
+      instead of int; int truncated sizes to 32 bits, which made xpdf still
+      vulnerable to integer (and eventually buffer) overflow attacks on 64 bit
+      platforms like amd64.
+    - pdftops/Xref.cxx: fix several unchecked negative integer conditions
+  * Thanks to Marcus Meissner <meissner@suse.de> for providing the patches.
+
+ -- Martin Pitt <mpitt@debian.org>  Mon,  1 Nov 2004 14:37:58 +0100
+
 cupsys (1.1.20final+rc1-10ubuntu2) hoary; urgency=low
 
   * Fixed debian/patches/ubuntu-localports.patch: do not comment out the
diff -u cupsys-1.1.20final+rc1/debian/patches/36pdftopsoverflow.patch cupsys-1.1.20final+rc1/debian/patches/36pdftopsoverflow.patch
--- cupsys-1.1.20final+rc1/debian/patches/36pdftopsoverflow.patch
+++ cupsys-1.1.20final+rc1/debian/patches/36pdftopsoverflow.patch
@@ -1,6 +1,6 @@
---- cupsys-1.1.14.orig/pdftops/Catalog.cxx
+--- cupsys-1.1.14/pdftops/Catalog.cxx
 +++ cupsys-1.1.14/pdftops/Catalog.cxx
-@@ -20,6 +20,7 @@
+@@ -22,6 +22,7 @@
  #include "Error.h"
  #include "Link.h"
  #include "Catalog.h"
@@ -8,9 +8,9 @@
  
  //------------------------------------------------------------------------
  // Catalog
-@@ -61,6 +62,12 @@
+@@ -64,6 +65,12 @@
    }
-   pagesSize = numPages0 = obj.getInt();
+   pagesSize = numPages0 = (int)obj.getNum();
    obj.free();
 +  if ((pagesSize >= INT_MAX / sizeof(Page *)) ||
 +      (pagesSize >= INT_MAX / sizeof(Ref))) {
@@ -21,7 +21,7 @@
    pages = (Page **)gmalloc(pagesSize * sizeof(Page *));
    pageRefs = (Ref *)gmalloc(pagesSize * sizeof(Ref));
    for (i = 0; i < pagesSize; ++i) {
-@@ -153,6 +160,11 @@
+@@ -191,6 +198,11 @@
        }
        if (start >= pagesSize) {
  	pagesSize += 32;
@@ -33,51 +33,157 @@
  	pages = (Page **)grealloc(pages, pagesSize * sizeof(Page *));
  	pageRefs = (Ref *)grealloc(pageRefs, pagesSize * sizeof(Ref));
  	for (j = pagesSize - 32; j < pagesSize; ++j) {
---- cupsys-1.1.14.orig/pdftops/XRef.cxx
-+++ cupsys-1.1.14/pdftops/XRef.cxx
-@@ -25,6 +25,7 @@
+--- cupsys-1.1.14/pdftops/gmem.c
++++ cupsys-1.1.14/pdftops/gmem.c
+@@ -53,9 +53,9 @@
+ 
+ #endif /* DEBUG_MEM */
+ 
+-void *gmalloc(int size) {
++void *gmalloc(size_t size) {
+ #ifdef DEBUG_MEM
+-  int size1;
++  size_t size1;
+   char *mem;
+   GMemHdr *hdr;
+   void *data;
+@@ -94,11 +94,11 @@
  #endif
+ }
+ 
+-void *grealloc(void *p, int size) {
++void *grealloc(void *p, size_t size) {
+ #ifdef DEBUG_MEM
+   GMemHdr *hdr;
+   void *q;
+-  int oldSize;
++  size_t oldSize;
+ 
+   if (size == 0) {
+     if (p)
+@@ -137,7 +137,7 @@
+ 
+ void gfree(void *p) {
+ #ifdef DEBUG_MEM
+-  int size;
++  size_t size;
+   GMemHdr *hdr;
+   GMemHdr *prevHdr, *q;
+   int lst;
+--- cupsys-1.1.14/pdftops/gmem.h
++++ cupsys-1.1.214/pdftops/gmem.h
+@@ -19,13 +19,13 @@
+  * Same as malloc, but prints error message and exits if malloc()
+  * returns NULL.
+  */
+-extern void *gmalloc(int size);
++extern void *gmalloc(size_t size);
+ 
+ /*
+  * Same as realloc, but prints error message and exits if realloc()
+  * returns NULL.  If <p> is NULL, calls malloc instead of realloc().
+  */
+-extern void *grealloc(void *p, int size);
++extern void *grealloc(void *p, size_t size);
+ 
+ /*
+  * Same as free, but checks for and ignores NULL pointers.
+--- cupsys-1.1.14/pdftops/XRef.cxx
++++ cupsys-1.1.14/pdftops/XRef.cxx
+@@ -28,6 +28,7 @@
  #include "Error.h"
+ #include "ErrorCodes.h"
  #include "XRef.h"
 +#include <limits.h>
  
  //------------------------------------------------------------------------
  
-@@ -71,6 +72,11 @@
+@@ -66,6 +67,8 @@
+   start = str->getStart();
+   pos = readTrailer();
+ 
++  entries = NULL;
++
+   // if there was a problem with the trailer,
+   // try to reconstruct the xref table
+   if (pos == 0) {
+@@ -76,6 +79,11 @@
  
    // trailer is ok - read the xref table
    } else {
-+    if ( size >= INT_MAX/sizeof(XRefEntry)) {
++    if (size < 0 || size >= INT_MAX/sizeof(XRefEntry)) {
 +      error(-1, "Invalid 'size' inside xref table.");
 +      ok = gFalse;
 +      return;
 +    }
      entries = (XRefEntry *)gmalloc(size * sizeof(XRefEntry));
      for (i = 0; i < size; ++i) {
-       entries[i].offset = -1;
-@@ -258,6 +264,10 @@
+       entries[i].offset = 0xffffffff;
+@@ -182,7 +190,7 @@
+     n = atoi(p);
+     while ('0' <= *p && *p <= '9') ++p;
+     while (isspace(*p)) ++p;
+-    if (p == buf) {
++    if (n < 0 || p == buf) {
+       goto err1;
+     }
+     pos1 += (p - buf) + n * 20;
+@@ -267,6 +275,10 @@
+     }
+     s[i] = '\0';
+     first = atoi(s);
++    if (first < 0) {
++        error(-1, "Invalid 'first'");
++        goto err2;
++    }
+     while ((c = str->lookChar()) != EOF && isspace(c)) {
+       str->getChar();
+     }
+@@ -278,6 +290,10 @@
+     }
+     s[i] = '\0';
+     n = atoi(s);
++    if (n<=0) {
++        error(-1, "Invalid 'n'");
++        goto err2;
++    }
+     while ((c = str->lookChar()) != EOF && isspace(c)) {
+       str->getChar();
+     }
+@@ -285,6 +301,10 @@
      // table size
      if (first + n > size) {
        newSize = first + n;
-+      if (newSize >= INT_MAX/sizeof(XRefEntry)) {
++      if (newSize < 0 || newSize >= INT_MAX/sizeof(XRefEntry)) {
 +	error(-1, "Invalid 'newSize'");
 +	goto err2;
 +      }
        entries = (XRefEntry *)grealloc(entries, newSize * sizeof(XRefEntry));
        for (i = size; i < newSize; ++i) {
  	entries[i].offset = 0xffffffff;
-@@ -399,6 +409,10 @@
+@@ -416,6 +436,10 @@
+     // look for object
+     } else if (isdigit(*p)) {
+       num = atoi(p);
++      if (num < 0) {
++	error(-1, "Invalid 'num' parameters.");
++	return gFalse;
++      }
+       do {
+ 	++p;
+       } while (*p && isdigit(*p));
+@@ -435,6 +459,10 @@
  	    if (!strncmp(p, "obj", 3)) {
  	      if (num >= size) {
  		newSize = (num + 1 + 255) & ~255;
-+		if (newSize >= INT_MAX / sizeof(XRefEntry)) {
++		if (newSize < 0 || newSize >= INT_MAX / sizeof(XRefEntry)) {
 +		  error(-1, "Invalid 'obj' parameters.");
 +		  return gFalse;
 +		}
  		entries = (XRefEntry *)
  		            grealloc(entries, newSize * sizeof(XRefEntry));
  		for (i = size; i < newSize; ++i) {
-@@ -420,6 +434,10 @@
+@@ -456,6 +484,10 @@
      } else if (!strncmp(p, "endstream", 9)) {
        if (streamEndsLen == streamEndsSize) {
  	streamEndsSize += 64;
@@ -89,3 +195,2 @@
-				       streamEndsSize * sizeof(int));
+ 				       streamEndsSize * sizeof(int));
        }
-       streamEnds[streamEndsLen++] = pos;
diff -u tetex-bin-2.0.2/debian/rules tetex-bin-2.0.2/debian/rules
--- tetex-bin-2.0.2/debian/rules
+++ tetex-bin-2.0.2/debian/rules
@@ -47,6 +47,8 @@
 	patch -p1 -Ni debian/patches/patch-texdoc
 	patch -p1 -NRi debian/patches/patch-tmp || true
 	patch -p1 -Ni debian/patches/patch-tmp
+	patch -p1 -NRi debian/patches/patch-more-CAN-2004-0888 || true
+	patch -p1 -Ni debian/patches/patch-more-CAN-2004-0888
 	cp -f /usr/share/misc/config.guess /usr/share/misc/config.sub ./texk/
 	cp -f /usr/share/misc/config.guess /usr/share/misc/config.sub ./utils/texinfo/
 	cp -f /usr/share/misc/config.guess /usr/share/misc/config.sub ./config/
@@ -85,6 +87,7 @@
 	# Add here commands to clean up after the build process.
 	# Make sure all of our expected symlinks are in place
 	sh debian/restore-symlinks
+	patch -p1 -NRi debian/patches/patch-more-CAN-2004-0888 || true
 	patch -p1 -NRi debian/patches/patch-tmp || true
 	patch -p1 -NRi debian/patches/patch-deb || true
 	patch -p1 -NRi debian/patches/patch-src || true
diff -u tetex-bin-2.0.2/debian/changelog tetex-bin-2.0.2/debian/changelog
--- tetex-bin-2.0.2/debian/changelog
+++ tetex-bin-2.0.2/debian/changelog
@@ -1,3 +1,19 @@
+tetex-bin (2.0.2-23ubuntu1) hoary; urgency=low
+
+  * SECURITY UPDATE: more buffer overflows in xpdf library
+  * Fixed more integer overflows discovered by Markus Meissner
+    <meissner@suse.de>, thanks to him for discovering this.
+  * Added debian/patches/patch-more-CAN-2004-0888:
+    - libs/xpdf/goo/gmem.[ch]: change declarations of gmalloc and grealloc to
+      use size_t instead of int; int truncated sizes to 32 bits, which made
+      xpdf still vulnerable to integer (and eventually buffer) overflow
+      attacks on 64 bit platforms like amd64.
+    - libs/xpdf/xpdf/XRef.cc: fix several unchecked negative integer conditions
+  * References:
+    CAN-2004-0888
+
+ -- Martin Pitt <mpitt@debian.org>  Mon,  1 Nov 2004 15:14:34 +0100
+
 tetex-bin (2.0.2-23) unstable; urgency=high
 
   * Security fix for the xpdf code included in pdftex. Many thanks to
only in patch2:
unchanged:
--- tetex-bin-2.0.2.orig/debian/patches/patch-more-CAN-2004-0888
+++ tetex-bin-2.0.2/debian/patches/patch-more-CAN-2004-0888
@@ -0,0 +1,138 @@
+diff -Nur tetex-bin-2.0.2/libs/xpdf/goo/gmem.c tetex-bin-2.0.2.new/libs/xpdf/goo/gmem.c
+--- tetex-bin-2.0.2/libs/xpdf/goo/gmem.c	2002-11-03 23:15:36.000000000 +0100
++++ tetex-bin-2.0.2.new/libs/xpdf/goo/gmem.c	2004-11-01 15:09:05.303145312 +0100
+@@ -53,9 +53,9 @@
+ 
+ #endif /* DEBUG_MEM */
+ 
+-void *gmalloc(int size) {
++void *gmalloc(size_t size) {
+ #ifdef DEBUG_MEM
+-  int size1;
++  size_t size1;
+   char *mem;
+   GMemHdr *hdr;
+   void *data;
+@@ -94,11 +94,11 @@
+ #endif
+ }
+ 
+-void *grealloc(void *p, int size) {
++void *grealloc(void *p, size_t size) {
+ #ifdef DEBUG_MEM
+   GMemHdr *hdr;
+   void *q;
+-  int oldSize;
++  size_t oldSize;
+ 
+   if (size == 0) {
+     if (p)
+@@ -137,7 +137,7 @@
+ 
+ void gfree(void *p) {
+ #ifdef DEBUG_MEM
+-  int size;
++  size_t size;
+   GMemHdr *hdr;
+   GMemHdr *prevHdr, *q;
+   int lst;
+diff -Nur tetex-bin-2.0.2/libs/xpdf/goo/gmem.h tetex-bin-2.0.2.new/libs/xpdf/goo/gmem.h
+--- tetex-bin-2.0.2/libs/xpdf/goo/gmem.h	2002-11-03 23:15:36.000000000 +0100
++++ tetex-bin-2.0.2.new/libs/xpdf/goo/gmem.h	2004-11-01 15:09:05.363136192 +0100
+@@ -19,13 +19,13 @@
+  * Same as malloc, but prints error message and exits if malloc()
+  * returns NULL.
+  */
+-extern void *gmalloc(int size);
++extern void *gmalloc(size_t size);
+ 
+ /*
+  * Same as realloc, but prints error message and exits if realloc()
+  * returns NULL.  If <p> is NULL, calls malloc instead of realloc().
+  */
+-extern void *grealloc(void *p, int size);
++extern void *grealloc(void *p, size_t size);
+ 
+ /*
+  * Same as free, but checks for and ignores NULL pointers.
+diff -Nur tetex-bin-2.0.2/libs/xpdf/xpdf/XRef.cc tetex-bin-2.0.2.new/libs/xpdf/xpdf/XRef.cc
+--- tetex-bin-2.0.2/libs/xpdf/xpdf/XRef.cc	2004-11-01 15:08:42.263647848 +0100
++++ tetex-bin-2.0.2.new/libs/xpdf/xpdf/XRef.cc	2004-11-01 15:10:01.625583000 +0100
+@@ -67,6 +67,8 @@
+   start = str->getStart();
+   pos = readTrailer();
+ 
++  entries = NULL;
++
+   // if there was a problem with the trailer,
+   // try to reconstruct the xref table
+   if (pos == 0) {
+@@ -77,7 +79,7 @@
+ 
+   // trailer is ok - read the xref table
+   } else {
+-    if (size >= INT_MAX/sizeof(XRefEntry)) {
++    if (size < 0 || size >= INT_MAX/sizeof(XRefEntry)) {
+       error(-1, "Invalid 'size' inside xref table.");
+       ok = gFalse;
+       errCode = errDamaged;
+@@ -182,7 +184,7 @@
+     n = atoi(p);
+     while ('0' <= *p && *p <= '9') ++p;
+     while (isspace(*p)) ++p;
+-    if (p == buf)
++    if ((p == buf) || (n < 0)) /* must make progress */
+       return 0;
+     pos1 += (p - buf) + n * 20;
+   }
+@@ -256,6 +258,10 @@
+     }
+     s[i] = '\0';
+     first = atoi(s);
++    if (first < 0) {
++        error(-1, "Invalid 'first'");
++        goto err2;
++    }
+     while ((c = str->lookChar()) != EOF && isspace(c)) {
+       str->getChar();
+     }
+@@ -267,6 +273,10 @@
+     }
+     s[i] = '\0';
+     n = atoi(s);
++    if (n<=0) {
++        error(-1, "Invalid 'n'");
++        goto err2;
++    }
+     while ((c = str->lookChar()) != EOF && isspace(c)) {
+       str->getChar();
+     }
+@@ -274,7 +284,7 @@
+     // table size
+     if (first + n > size) {
+       newSize = size + 256;
+-      if (newSize >= INT_MAX/sizeof(XRefEntry)) {
++      if (newSize < 0 || newSize >= INT_MAX/sizeof(XRefEntry)) {
+         error(-1, "Invalid 'newSize'");
+         goto err2;
+       }
+@@ -402,6 +412,10 @@
+     // look for object
+     } else if (isdigit(*p)) {
+       num = atoi(p);
++      if (num < 0) {
++	error(-1, "Invalid 'num' parameters.");
++	return gFalse;
++      }
+       do {
+ 	++p;
+       } while (*p && isdigit(*p));
+@@ -421,7 +435,7 @@
+ 	    if (!strncmp(p, "obj", 3)) {
+ 	      if (num >= size) {
+ 		newSize = (num + 1 + 255) & ~255;
+-	        if (newSize >= INT_MAX/sizeof(XRefEntry)) {
++	        if (newSize < 0 || newSize >= INT_MAX/sizeof(XRefEntry)) {
+ 	          error(-1, "Invalid 'obj' parameters.");
+ 	          return gFalse;
+ 	        }

Attachment: signature.asc
Description: Digital signature


Reply to: