From 9510e4315705329e51b27fa2f3f688989b9fb37f Mon Sep 17 00:00:00 2001 From: Tim Retout Date: Sun, 27 Dec 2009 14:50:37 +0000 Subject: [PATCH] Apply patch from Debian Security Team for CAN-2004-1184. --- src/ChangeLog | 14 ++++++++++++++ src/gsint.h | 5 +++++ src/main.c | 22 ++++++++++++++++------ src/util.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 7557664..b5e7680 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2009-12-27 Tim Retout + + Apply patch from Debian Security Team for CAN-2004-1184. + + * gsint.h: Add shell_escape prototype. + * util.c (shell_escape): New function to escape filenames for + shell usage. + * util.c (is_open): Use shell_escape to expand command buffer. + + * main.c (main): Use single quotes when building command string, + and use shell_escape to quote contents. + + * util.c (escape_string): Check return code of xmalloc. + 2009-03-28 Tim Retout * psgen.c (recognize_eps_file): Remove ability to read EPS data diff --git a/src/gsint.h b/src/gsint.h index 933fabc..b89d3b7 100644 --- a/src/gsint.h +++ b/src/gsint.h @@ -699,4 +699,9 @@ FILE *printer_open ___P ((char *cmd, char *options, char *queue_param, */ void printer_close ___P ((void *context)); +/* + * Escape filenames for shell usage + */ +char *shell_escape ___P ((const char *fn)); + #endif /* not GSINT_H */ diff --git a/src/main.c b/src/main.c index 6f296cf..48c42fb 100644 --- a/src/main.c +++ b/src/main.c @@ -1544,9 +1544,13 @@ name width\theight\tllx\tlly\turx\tury\n\ buffer_append (&cmd, intbuf); buffer_append (&cmd, " "); - buffer_append (&cmd, "-Ddocument_title=\""); - buffer_append (&cmd, title); - buffer_append (&cmd, "\" "); + buffer_append (&cmd, "-Ddocument_title=\'"); + if ((cp = shell_escape (title)) != NULL) + { + buffer_append (&cmd, cp); + free (cp); + } + buffer_append (&cmd, "\' "); buffer_append (&cmd, "-Dtoc="); buffer_append (&cmd, toc ? "1" : "0"); @@ -1563,8 +1567,14 @@ name width\theight\tllx\tlly\turx\tury\n\ /* Append input files. */ for (i = optind; i < argc; i++) { - buffer_append (&cmd, " "); - buffer_append (&cmd, argv[i]); + char *cp; + if ((cp = shell_escape (argv[i])) != NULL) + { + buffer_append (&cmd, " \'"); + buffer_append (&cmd, cp); + buffer_append (&cmd, "\'"); + free (cp); + } } /* And do the job. */ @@ -1625,7 +1635,7 @@ name width\theight\tllx\tlly\turx\tury\n\ buffer_ptr (opts), buffer_len (opts)); } - buffer_append (&buffer, " \"%s\""); + buffer_append (&buffer, " \'%s\'"); input_filter = buffer_copy (&buffer); input_filter_stdin = "-"; diff --git a/src/util.c b/src/util.c index 01dd661..39b8441 100644 --- a/src/util.c +++ b/src/util.c @@ -1237,6 +1237,8 @@ escape_string (char *string) /* Create result. */ cp = xmalloc (len + 1); + if (cp == NULL) + return NULL; for (i = 0, j = 0; string[i]; i++) switch (string[i]) { @@ -1877,6 +1879,7 @@ is_open (InputStream *is, FILE *fp, char *fname, char *input_filter) char *cmd = NULL; int cmdlen; int i, pos; + char *cp; is->is_pipe = 1; @@ -1900,12 +1903,16 @@ is_open (InputStream *is, FILE *fp, char *fname, char *input_filter) { case 's': /* Expand cmd-buffer. */ - cmdlen += strlen (fname); - cmd = xrealloc (cmd, cmdlen); + if ((cp = shell_escape (fname)) != NULL) + { + cmdlen += strlen (cp); + cmd = xrealloc (cmd, cmdlen); - /* Paste filename. */ - strcpy (cmd + pos, fname); - pos += strlen (fname); + /* Paste filename. */ + strcpy (cmd + pos, cp); + pos += strlen (cp); + free (cp); + } i++; break; @@ -2114,3 +2121,36 @@ buffer_len (Buffer *buffer) { return buffer->len; } + +/* + * Escapes the name of a file so that the shell groks it in 'single' + * quotation marks. The resulting pointer has to be free()ed when not + * longer used. +*/ +char * +shell_escape(const char *fn) +{ + size_t len = 0; + const char *inp; + char *retval, *outp; + + for(inp = fn; *inp; ++inp) + switch(*inp) + { + case '\'': len += 4; break; + default: len += 1; break; + } + + outp = retval = malloc(len + 1); + if(!outp) + return NULL; /* perhaps one should do better error handling here */ + for(inp = fn; *inp; ++inp) + switch(*inp) + { + case '\'': *outp++ = '\''; *outp++ = '\\'; *outp++ = '\'', *outp++ = '\''; break; + default: *outp++ = *inp; break; + } + *outp = 0; + + return retval; +} -- 2.17.1