[DVIPDFMx] dvipdfmx status?

Karl Berry karl at freefriends.org
Sat Mar 5 08:45:34 KST 2011


Hello?  Anyone :)?

---------------------------------------
From: karl at freefriends.org (Karl Berry)
To: dvipdfmx at ktug.or.kr
Subject: dpxfile.c patch for system() protection

Hi ChoF, Matthias, all,

Akira sent this new code last fall:

    Date: Sat, 09 Oct 2010 16:40:20 +0900
    From: "Akira Kakuto" <kakuto at fuk.kindai.ac.jp>
    Subject: Re: [XeTeX] File name bug when using \includegraphics

The idea is that the simple invocation of system() is a security hazard,
because it's run through /bin/sh and the filename can trivially contain
stuff like `rm -rf /` or any other malicious command.

The change protects things with quotes.  We do similar things now in TeX
and dvips, etc.  Patch below.

Ok?  Can you apply, if you haven't already?


Also, I'll take this opportunity to mention that my goal for this year
is to have the major software updates made by the beginning of April.
I'm not sure if other changes have been made to dvipdfmx since last
year, but it would be nice to have a new release just with this change.
Possible?

Thanks,
Karl

--- dpxfile.c	(revision 21543)
+++ dpxfile.c	(working copy)
@@ -35,6 +35,24 @@
 
 #include "dpxfile.h"
 
+#include <kpathsea/lib.h>
+#include <kpathsea/concatn.h>
+#include <string.h>
+#ifdef WIN32
+#include <io.h>
+#include <process.h>
+#else
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h> 
+#endif
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(val) ((unsigned)(val) >> 8)
+#endif
+#ifndef WIFEXITED
+# define WIFEXITED(val) (((val) & 255) == 0)
+#endif
+#endif
+
 static int verbose = 0;
 
 void
@@ -132,8 +150,98 @@
 #endif
 static char  _tmpbuf[_MAX_PATH+1];
 #endif /* MIKTEX */
+
+static int exec_spawn (char *cmd)
+{
+  char **cmdv, **qv;
+  char *p, *pp;
+  char buf[512];
+  int  i, ret;
 
+  if (!cmd || !*cmd)
+    return -1;
+  i = 0;
+  p = cmd;
+  while (*p) {
+    if (*p == ' ' || *p == '\t')
+      i++;
+    p++;
+  }
+  cmdv = (char **) xmalloc (sizeof (char *) * (i+2));
+  p = cmd;
+  qv = cmdv;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  while (*p) {
+    pp = buf;
+    if (*p == '"') {
+      p++;
+      while (*p != '"') {
+        if (*p == '\0') {
+          free (cmdv);
+          return -1;
+        }
+        *pp++ = *p++;
+      }
+      p++;
+    } else if (*p == '\'') {
+      p++;
+      while (*p != '\'') {
+        if (*p == '\0') {
+          free (cmdv);
+          return -1;
+        }
+        *pp++ = *p++;
+      }
+      p++;
+    } else {
+      while (*p != ' ' && *p != '\t' && *p)
+        *pp++ = *p++;
+    }
+    *pp = '\0';
+    if ((pp = strchr (buf, ' ')) || (pp = strchr (buf, '\t'))) {
+#ifdef WIN32
+      *qv = concatn ("\"", buf, "\"", NULL);
+#else
+      *qv = concatn ("'", buf, "'", NULL);
+#endif
+    } else {
+      *qv = concat (buf, "");
+    }
+    while (*p == ' ' || *p == '\t')
+      p++;
+    qv++;
+  }
+  *qv = NULL;
+#ifdef WIN32
+  ret = spawnvp (_P_WAIT, *cmdv, cmdv);
+#else
+  i = fork ();
+  if (i < 0)
+    ret = -1;
+  else if (i == 0) {
+    if (execvp (*cmdv, cmdv))
+      ret = -1;
+  } else {
+    if (wait (&ret) == i) {
+      ret = (WIFEXITED (ret) ? WEXITSTATUS (ret) : -1);
+    } else {
+      ret = -1;
+    }
+  }
+#endif
+  qv = cmdv;
+  if (qv) {
+    while (*qv) {
+      free (*qv);
+      qv++;
+    }
+    free (cmdv);
+  }
+  return ret;
+}
 
+
 /* ensuresuffix() returns a copy of basename if sfx is "". */
 static char *
 ensuresuffix (const char *basename, const char *sfx)
@@ -750,7 +858,7 @@
     return -1;
   }
 
-  error = system(cmd);
+  error = exec_spawn(cmd);
   if (error)
     WARN("Filtering file via command -->%s<-- failed.", cmd);
   RELEASE(cmd);



More information about the dvipdfmx mailing list