You can do 
 pdftohtml -c -dev 'jpeg /dev/null;cat /etc/passwd;#' /path/to/some/pdf/fil
and voila, you'll get your /etc/passwd printed on screen

Definitely not nice.

This is because we are using plain system() to run the gs command and it's easy 
to inject stuff there

The poors man solution is trying to escape the strings but it's really 
impossible.

The real solution is moving to a fork+exec solution (path attached).

The problem with that is that we loose support for platforms with system() and 
without fork+exec (Windows).

So here comes my question, anyone with Windows experience can implement a path 
for my patch that works fine?

Another solution would be just killing the gs invokation from pdftohtml since i 
don't really see it's point.

Comments?

Cheers,
  Albert
diff --git a/CMakeLists.txt b/CMakeLists.txt
index af894d1..892058d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -177,6 +177,15 @@ if(CMAKE_USE_PTHREADS_INIT)
   set(HAVE_PTHREAD ON)
 endif(CMAKE_USE_PTHREADS_INIT)
 
+check_cxx_source_compiles("
+#include <unistd.h>
+
+int main()
+{
+  return execvp(NULL, NULL);
+}
+" HAVE_EXECVP)
+
 if(ENABLE_ZLIB)
   include_directories(${ZLIB_INCLUDE_DIR})
 endif(ENABLE_ZLIB)
diff --git a/config.h.cmake b/config.h.cmake
index 3c7b968..e056d7f 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -55,6 +55,9 @@
 /* Define if you have the iconv() function and it works. */
 #cmakedefine HAVE_ICONV 1
 
+/* Define if you have the execvp() function. */
+#cmakedefine HAVE_EXECVP 1
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #cmakedefine HAVE_INTTYPES_H 1
 
diff --git a/configure.ac b/configure.ac
index 71cd3b9..5adfb67 100644
--- a/configure.ac
+++ b/configure.ac
@@ -131,6 +131,7 @@ dnl ##### (99% of xpdf is written in C++.)
 AC_LANG_CPLUSPLUS
 
 AC_CHECK_DECL(gettimeofday, [AC_CHECK_FUNC(gettimeofday, AC_DEFINE(HAVE_GETTIMEOFDAY, 1, [Defines if gettimeofday is available on your system]))],[],[#include <sys/time.h>])
+AC_CHECK_DECL(execvp, [AC_CHECK_FUNC(execvp, AC_DEFINE(HAVE_EXECVP, 1, [Defines if execvp is available on your system]))],[],[#include <unistd.h>])
 AC_CHECK_FUNC(localtime_r, AC_DEFINE(HAVE_LOCALTIME_R, 1, [Defines if localtime_r is available on your system]))
 AC_CHECK_FUNC(gmtime_r, AC_DEFINE(HAVE_GMTIME_R, 1, [Defines if gmtime_r is available on your system]))
 
diff --git a/goo/gfile.cc b/goo/gfile.cc
index 7522424..fd596b9 100644
--- a/goo/gfile.cc
+++ b/goo/gfile.cc
@@ -52,6 +52,13 @@
 #include "GooString.h"
 #include "gfile.h"
 
+#if HAVE_EXECVP
+#  include <sys/types.h>
+#  include <sys/wait.h>
+#  include <errno.h>
+#  include "gmem.h"
+#endif
+
 // Some systems don't define this, so just make it something reasonably
 // large.
 #ifndef PATH_MAX
@@ -545,11 +552,42 @@ GBool openTempFile(GooString **name, FILE **f, const char *mode) {
 #endif
 }
 
-GBool executeCommand(char *cmd) {
-#ifdef VMS
-  return system(cmd) ? gTrue : gFalse;
+GBool executeCommand(int nCommands, const char *cmd, ...) {
+#if HAVE_EXECVP
+  pid_t pid = fork();
+  if (pid == -1) {
+    return gFalse;
+  } else if (pid != 0) {
+    pid_t ret;
+    int status;
+    while ((ret = waitpid(pid, &status, 0)) == -1) {
+      if (errno != EINTR) {
+	return gFalse;
+      }
+    }
+    if (ret == pid && WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+      return gTrue;
+    } else {
+      return gFalse;
+    }
+  } else {
+    char **args = (char**)gmallocn(nCommands + 2, sizeof(char *));
+    va_list var_args;
+    va_start(var_args, cmd);
+    args[0] = (char*)cmd;
+    for(int j = 0; j < nCommands; ++j) {
+      args[j + 1] = va_arg(var_args, char *);
+    }
+    va_end(var_args);
+    args[nCommands + 1] = NULL;
+    if (execvp(cmd, args) == -1) {
+      _exit(127);
+    }
+    return 0;
+  }
 #else
-  return system(cmd) ? gFalse : gTrue;
+sdf
+  return gFalse;
 #endif
 }
 
diff --git a/goo/gfile.h b/goo/gfile.h
index d4b9082..043cf17 100644
--- a/goo/gfile.h
+++ b/goo/gfile.h
@@ -105,7 +105,7 @@ extern time_t getModTime(char *fileName);
 extern GBool openTempFile(GooString **name, FILE **f, const char *mode);
 
 // Execute <command>.  Returns true on success.
-extern GBool executeCommand(char *cmd);
+extern GBool executeCommand(int nCommands, const char *cmd, ...);
 
 #ifdef WIN32
 // Convert a file name from Latin-1 to UTF-8.
diff --git a/utils/pdftohtml.cc b/utils/pdftohtml.cc
index d6475b0..f7463dd 100644
--- a/utils/pdftohtml.cc
+++ b/utils/pdftohtml.cc
@@ -470,36 +470,19 @@ int main(int argc, char *argv[]) {
       /*sprintf(buf, "%s -sDEVICE=png16m -dBATCH -dNOPROMPT -dNOPAUSE -r%d -sOutputFile=%s%%03d.png -g%dx%d -q %s", GHOSTSCRIPT, resolution, htmlFileName->getCString(), w, h,
       psFileName->getCString());*/
 
-      GooString *gsCmd = new GooString(GHOSTSCRIPT);
-      GooString *tw, *th, *sc;
-      gsCmd->append(" -sDEVICE=");
-      gsCmd->append(gsDevice);
-      gsCmd->append(" -dBATCH -dNOPROMPT -dNOPAUSE -r");
-      sc = GooString::fromInt(static_cast<int>(72*scale));
-      gsCmd->append(sc);
-      gsCmd->append(" -sOutputFile=");
-      gsCmd->append("\"");
-      gsCmd->append(htmlFileName);
-      gsCmd->append("%03d.");
-      gsCmd->append(extension);
-      gsCmd->append("\" -g");
-      tw = GooString::fromInt(static_cast<int>(scale*w));
-      gsCmd->append(tw);
-      gsCmd->append("x");
-      th = GooString::fromInt(static_cast<int>(scale*h));
-      gsCmd->append(th);
-      gsCmd->append(" -q \"");
-      gsCmd->append(psFileName);
-      gsCmd->append("\"");
+      GooString *gsd = GooString::format("-sDEVICE={0:s}", gsDevice);
+      GooString *sc = GooString::format("-r{0:d}", static_cast<int>(72*scale));
+      GooString *of = GooString::format("-sOutputFile={0:t}%03d.{1:s}", htmlFileName, extension);
+      GooString *t = GooString::format("-g{0:d}x{1:d}", static_cast<int>(scale*w), static_cast<int>(scale*h));
       //    printf("running: %s\n", gsCmd->getCString());
-      if( !executeCommand(gsCmd->getCString()) && !errQuiet) {
+      if( !executeCommand(9, GHOSTSCRIPT, gsd->getCString(), "-dBATCH", "-dNOPROMPT", "-dNOPAUSE", sc->getCString(), of->getCString(), t->getCString(), "-q", psFileName->getCString()) && !errQuiet) {
         error(errIO, -1, "Failed to launch Ghostscript!\n");
       }
       unlink(psFileName->getCString());
-      delete tw;
-      delete th;
+      delete gsd;
       delete sc;
-      delete gsCmd;
+      delete of;
+      delete t;
       delete psFileName;
     }
   }
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to