From eebddb1fff7d6b87ef7938881b2e5c9fdb702dad Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Wed, 30 Apr 2014 00:24:38 -0400 Subject: system: Escape special characters for Zenity. When invoking Zenity to display an error message, some characters can have special meanings to the shell. Escape these properly so that the error message is always shown correctly. This fixes #355. --- src/i_system.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/i_system.c b/src/i_system.c index 5b6989bf..5aa57348 100644 --- a/src/i_system.c +++ b/src/i_system.c @@ -262,6 +262,7 @@ void I_Quit (void) exit(0); } +#if !defined(_WIN32) && !defined(__MACOSX__) #define ZENITY_BINARY "/usr/bin/zenity" // returns non-zero if zenity is available @@ -271,11 +272,56 @@ static int ZenityAvailable(void) return system(ZENITY_BINARY " --help >/dev/null 2>&1") == 0; } +// Escape special characters in the given string so that they can be +// safely enclosed in shell quotes. + +static char *EscapeShellString(char *string) +{ + char *result; + char *r, *s; + + // In the worst case, every character might be escaped. + result = malloc(strlen(string) * 2 + 3); + r = result; + + // Enclosing quotes. + *r = '"'; + ++r; + + for (s = string; *s != '\0'; ++s) + { + // From the bash manual: + // + // "Enclosing characters in double quotes preserves the literal + // value of all characters within the quotes, with the exception + // of $, `, \, and, when history expansion is enabled, !." + // + // Therefore, escape these characters by prefixing with a backslash. + + if (strchr("$`\\!", *s) != NULL) + { + *r = '\\'; + ++r; + } + + *r = *s; + ++r; + } + + // Enclosing quotes. + *r = '"'; + ++r; + *r = '\0'; + + return result; +} + // Open a native error box with a message using zenity static int ZenityErrorBox(char *message) { - int *result; + int result; + char *escaped_message; char *errorboxpath; static size_t errorboxpath_size; @@ -284,17 +330,24 @@ static int ZenityErrorBox(char *message) return 0; } - errorboxpath_size = strlen(ZENITY_BINARY) + strlen(message) + 19; + escaped_message = EscapeShellString(message); + + errorboxpath_size = strlen(ZENITY_BINARY) + strlen(escaped_message) + 19; errorboxpath = malloc(errorboxpath_size); - M_snprintf(errorboxpath, errorboxpath_size, "%s --error --text=\"%s\"", ZENITY_BINARY, message); + M_snprintf(errorboxpath, errorboxpath_size, "%s --error --text=%s", + ZENITY_BINARY, escaped_message); result = system(errorboxpath); free(errorboxpath); + free(escaped_message); return result; } +#endif /* !defined(_WIN32) && !defined(__MACOSX__) */ + + // // I_Error // -- cgit v1.2.3