See attached.
In case of too many mail/BTS/web gateways, I posted a backup copy at
http://recycle.lbl.gov/~ldoolitt/087a_SECURITY_libXpm_vulnerabilities.diff

When I say "tested" I mean tested in isolation.
My attempts to fully test the debian build process
have so far failed, for (I think) unrelated reasons.
apt-src and I are not friends yet.

    - Larry
Candidate response to debian bug #308783, based on
http://ftp.x.org/pub/X11R6.8.1/patches/X11R6.8.1-to-X11R6.8.2.patch.gz

This patch is to be applied _after_
$ md5sum 087_SECURITY_libXpm_vulnerabilities.diff
810923ff9eac7eb83d96870a4fbaab15  087_SECURITY_libXpm_vulnerabilities.diff

Other than sorting out the patch basis and removing fuzz, my only contribution
is to remove a compilation warning caused by a missing FUNC(xpmPipeThrough, ...)
in RdFToI.c.  Verified against the full X11R6.8.2 sources: the only
other differences are CVS tags and some trailing spaces in the source.

Tested, works.  2005-05-23  Larry Doolittle  <[EMAIL PROTECTED]>

diff -ur xc~/extras/Xpm/lib/RdFToI.c xc/extras/Xpm/lib/RdFToI.c
--- xc~/extras/Xpm/lib/RdFToI.c 2005-05-23 10:12:01.211131000 -0700
+++ xc/extras/Xpm/lib/RdFToI.c  2005-05-23 10:22:48.159031812 -0700
@@ -36,15 +36,11 @@
 /* October 2004, source code review by Thomas Biege <[EMAIL PROTECTED]> */
 
 #include "XpmI.h"
-#include <sys/stat.h>
-#if !defined(NO_ZPIPE) && defined(WIN32)
-# define popen _popen
-# define pclose _pclose
-# if defined(STAT_ZFILE)
-#  include <io.h>
-#  define stat _stat
-#  define fstat _fstat
-# endif
+#ifndef NO_ZPIPE
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #endif
 
 LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata));
@@ -122,89 +118,132 @@
 }
 #endif /* CXPMPROG */
 
-/*
- * open the given file to be read as an xpmData which is returned.
- */
 #ifndef NO_ZPIPE
-       FILE *s_popen(char *cmd, const char *type);
-#else
-#      define s_popen popen
+/* Do not depend on errno after read_through */
+FUNC(xpmPipeThrough, FILE*, (int fd, const char* cmd, const char* arg1, const 
char* mode));
+FILE*
+xpmPipeThrough(fd, cmd, arg1, mode)
+    int fd;
+    const char* cmd;
+    const char* arg1;
+    const char* mode;
+{
+    FILE* fp;
+    int status, fds[2], in = 0, out = 1;
+    pid_t pid;
+    if ( 'w' == *mode )
+       out = 0, in = 1;
+    if ( pipe(fds) < 0 )
+       return NULL;
+    pid = fork();
+    if ( pid < 0 )
+       goto fail1;
+    if ( 0 == pid )
+    {
+       close(fds[in]);
+       if ( dup2(fds[out], out) < 0 )
+           goto err;
+       close(fds[out]);
+       if ( dup2(fd, in) < 0 )
+           goto err;
+       close(fd);
+       pid = fork();
+       if ( pid < 0 )
+           goto err;
+       if ( 0 == pid )
+       {
+           execlp(cmd, cmd, arg1, NULL);
+           perror(cmd);
+           goto err;
+       }
+       _exit(0);
+    err:
+       _exit(1);
+    }
+    close(fds[out]);
+    /* calling process: wait for first child */
+    while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
+       ;
+    if ( WIFSIGNALED(status) ||
+        (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
+       goto fail2;
+    fp = fdopen(fds[in], mode);
+    if ( !fp )
+       goto fail2;
+    close(fd); /* still open in 2nd child */
+    return fp;
+fail1:
+    close(fds[out]);
+fail2:
+    close(fds[in]);
+    return NULL;
+}
 #endif
 
+/*
+ * open the given file to be read as an xpmData which is returned.
+ */
 static int
 OpenReadFile(filename, mdata)
     char *filename;
     xpmData *mdata;
 {
-#ifndef NO_ZPIPE
-    char buf[BUFSIZ];
-# ifdef STAT_ZFILE
-    char *compressfile;
-    struct stat status;
-# endif
-#endif
-
     if (!filename) {
        mdata->stream.file = (stdin);
        mdata->type = XPMFILE;
     } else {
-#ifndef NO_ZPIPE
-       size_t len = strlen(filename);
-
-       if (len == 0)
-               return(XpmOpenFailed);
-       if ((len > 2) && !strcmp(".Z", filename + (len - 2))) {
-           mdata->type = XPMPIPE;
-           snprintf(buf, sizeof(buf), "uncompress -c \"%s\"", filename);
-           if (!(mdata->stream.file = s_popen(buf, "r")))
-               return (XpmOpenFailed);
-
-       } else if ((len > 3) && !strcmp(".gz", filename + (len - 3))) {
-           mdata->type = XPMPIPE;
-           snprintf(buf, sizeof(buf), "gunzip -qc \"%s\"", filename);
-           if (!(mdata->stream.file = s_popen(buf, "r")))
-               return (XpmOpenFailed);
-
-       } else {
-# ifdef STAT_ZFILE
-           if (!(compressfile = (char *) XpmMalloc(len + 4)))
+       int fd = open(filename, O_RDONLY);
+#if defined(NO_ZPIPE)
+       if ( fd < 0 )
+           return XpmOpenFailed;
+#else
+       const char* ext = NULL;
+       if ( fd >= 0 )
+           ext = strrchr(filename, '.');
+#ifdef STAT_ZFILE /* searching for z-files if the given name not found */
+       else
+       {
+           size_t len = strlen(filename);
+           char *compressfile = (char *) XpmMalloc(len + 4);
+           if ( !compressfile )
                return (XpmNoMemory);
-
-           snprintf(compressfile, len+4, "%s.Z", filename);
-           if (!stat(compressfile, &status)) {
-               snprintf(buf, sizeof(buf), "uncompress -c \"%s\"", 
compressfile);
-               if (!(mdata->stream.file = s_popen(buf, "r"))) {
+           strcpy(compressfile, filename);
+           strcpy(compressfile + len, ext = ".Z");
+           fd = open(compressfile, O_RDONLY);
+           if ( fd < 0 )
+           {
+               strcpy(compressfile + len, ext = ".gz");
+               fd = open(compressfile, O_RDONLY);
+               if ( fd < 0 )
+               {
                    XpmFree(compressfile);
-                   return (XpmOpenFailed);
-               }
-               mdata->type = XPMPIPE;
-           } else {
-               snprintf(compressfile, len+4, "%s.gz", filename);
-               if (!stat(compressfile, &status)) {
-                   snprintf(buf, sizeof(buf), "gunzip -c \"%s\"", 
compressfile);
-                   if (!(mdata->stream.file = s_popen(buf, "r"))) {
-                       XpmFree(compressfile);
-                       return (XpmOpenFailed);
-                   }
-                   mdata->type = XPMPIPE;
-               } else {
-# endif
-#endif
-                   if (!(mdata->stream.file = fopen(filename, "r"))) {
-#if !defined(NO_ZPIPE) && defined(STAT_ZFILE)
-                       XpmFree(compressfile);
-#endif
-                       return (XpmOpenFailed);
-                   }
-                   mdata->type = XPMFILE;
-#ifndef NO_ZPIPE
-# ifdef STAT_ZFILE
+                   return XpmOpenFailed;
                }
            }
            XpmFree(compressfile);
-# endif
        }
 #endif
+       if ( ext && !strcmp(ext, ".Z") )
+       {
+           mdata->type = XPMPIPE;
+           mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
+       }
+       else if ( ext && !strcmp(ext, ".gz") )
+       {
+           mdata->type = XPMPIPE;
+           mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
+       }
+       else
+#endif /* z-files */
+       {
+           mdata->type = XPMFILE;
+           mdata->stream.file = fdopen(fd, "r");
+       }
+       if (!mdata->stream.file)
+       {
+           close(fd);
+           return (XpmOpenFailed);
+       }
     }
     mdata->CommentLength = 0;
 #ifdef CXPMPROG
@@ -221,15 +260,6 @@
 xpmDataClose(mdata)
     xpmData *mdata;
 {
-    switch (mdata->type) {
-    case XPMFILE:
-       if (mdata->stream.file != (stdin))
-           fclose(mdata->stream.file);
-       break;
-#ifndef NO_ZPIPE
-    case XPMPIPE:
+    if (mdata->stream.file != (stdin))
        fclose(mdata->stream.file);
-       break;
-#endif
-    }
 }
diff -ur xc~/extras/Xpm/lib/WrFFrI.c xc/extras/Xpm/lib/WrFFrI.c
--- xc~/extras/Xpm/lib/WrFFrI.c 2005-05-23 09:28:21.000000000 -0700
+++ xc/extras/Xpm/lib/WrFFrI.c  2005-05-23 10:20:24.000366045 -0700
@@ -38,12 +38,14 @@
  * Lorens Younes ([EMAIL PROTECTED]) 4/96
  */
 
-/* October 2004, source code review by Thomas Biege <[EMAIL PROTECTED]> */
-
 #include "XpmI.h"
-#if !defined(NO_ZPIPE) && defined(WIN32)
-# define popen _popen
-# define pclose _pclose
+
+#ifndef NO_ZPIPE
+#include "sys/wait.h"
+#include "sys/types.h"
+#include "fcntl.h"
+#include "unistd.h"
+#include "errno.h"
 #endif
 
 /* MS Windows define a function called WriteFile @#%#&!!! */
@@ -124,7 +126,7 @@
        /* let's try to make a valid C syntax name */
        if (index(name, '.')) {
            strncpy(new_name, name, sizeof(new_name));
-           new_name[sizeof(new_name)-1] = 0;
+           new_name[sizeof(new_name)-1] = '\0';
            /* change '.' to '_' */
            name = s = new_name;
            while ((dot = index(s, '.'))) {
@@ -134,8 +136,7 @@
        }
        if (index(name, '-')) {
            if (name != new_name) {
-               strncpy(new_name, name, sizeof(new_name));
-               new_name[sizeof(new_name)-1] = 0;
+               strcpy(new_name, name);
                name = new_name;
            }
            /* change '-' to '_' */
@@ -301,55 +302,48 @@
     fprintf(file, ",\n\"XPMENDEXT\"");
 }
 
+
+#ifndef NO_ZPIPE
+FUNC(xpmPipeThrough, FILE*, (int fd,
+                            const char* cmd,
+                            const char* arg1,
+                            const char* mode));
+#endif
+
 /*
  * open the given file to be written as an xpmData which is returned
  */
-#ifndef NO_ZPIPE
-       FILE *s_popen(char *cmd, const char *type);
-#else
-#      define s_popen popen
-#endif
 static int
 OpenWriteFile(filename, mdata)
     char *filename;
     xpmData *mdata;
 {
-#ifndef NO_ZPIPE
-    char buf[BUFSIZ];
-
-#endif
-
     if (!filename) {
        mdata->stream.file = (stdout);
        mdata->type = XPMFILE;
     } else {
 #ifndef NO_ZPIPE
-       size_t len = strlen(filename);
-
-       if (len == 0)
-               return(XpmOpenFailed);
-
+       size_t len;
+#endif
+       int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+       if ( fd < 0 )
+           return(XpmOpenFailed);
+#ifndef NO_ZPIPE
+       len = strlen(filename);
        if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
-           snprintf(buf, sizeof(buf), "compress > \"%s\"", filename);
-           if (!(mdata->stream.file = s_popen(buf, "w")))
-               return (XpmOpenFailed);
-
+           mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w");
            mdata->type = XPMPIPE;
        } else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
-           snprintf(buf, sizeof(buf), "gzip -q > \"%s\"", filename);
-           if (!(mdata->stream.file = s_popen(buf, "w")))
-               return (XpmOpenFailed);
-
+           mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w");
            mdata->type = XPMPIPE;
-       } else {
+       } else
 #endif
-           if (!(mdata->stream.file = fopen(filename, "w")))
-               return (XpmOpenFailed);
-
+       {
+           mdata->stream.file = fdopen(fd, "w");
            mdata->type = XPMFILE;
-#ifndef NO_ZPIPE
        }
-#endif
+       if (!mdata->stream.file)
+           return (XpmOpenFailed);
     }
     return (XpmSuccess);
 }
@@ -361,15 +355,7 @@
 xpmDataClose(mdata)
     xpmData *mdata;
 {
-    switch (mdata->type) {
-    case XPMFILE:
-       if (mdata->stream.file != (stdout))
-           fclose(mdata->stream.file);
-       break;
-#ifndef NO_ZPIPE
-    case XPMPIPE:
+    if (mdata->stream.file != (stdout))
        fclose(mdata->stream.file);
-       break;
-#endif
-    }
 }
+

Attachment: signature.asc
Description: Digital signature

Reply via email to