From 16884407eb1aebbcbe876642c9e793bb1c14ac50 Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Wed, 3 Jun 2020 13:47:55 +0900 Subject: [PATCH] mkdeps: Quote CFLAGS to be safe with the shell mkdeps uses system() thus a shell to execute cc. it doesn't work if you have something like CFLAGS += -DMBEDTLS_USER_CONFIG_FILE="" because the shell interprets "<" as a redirect. to fix it, we should do either * make it shell-quote arguments * or, stop using system() this commit implements the former. some platforms provide easy ways to do the former. eg. https://netbsd.gw.com/cgi-bin/man-cgi?shquote++NetBSD-current but unfortunately none of them seems available widely. i guess the latter approach is more common. eg. https://github.com/NetBSD/src/blob/4464250282160188d09bef1ac67ec944b9a8a828/usr.bin/mkdep/mkdep.c#L137-L154 but i might be a burden for windows. (i don't know) --- tools/mkdeps.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 2 deletions(-) diff --git a/tools/mkdeps.c b/tools/mkdeps.c index 2c16531f9a..2adf3b71fc 100644 --- a/tools/mkdeps.c +++ b/tools/mkdeps.c @@ -59,6 +59,7 @@ #define MAX_BUFFER (4096) #define MAX_EXPAND (2048) +#define MAX_SHQUOTE (2048) /* MAX_PATH might be defined in stdlib.h */ @@ -123,6 +124,7 @@ static char g_expand[MAX_EXPAND]; static char g_dequoted[MAX_PATH]; static char g_posixpath[MAX_PATH]; #endif +static char g_shquote[MAX_SHQUOTE]; /**************************************************************************** * Private Functions @@ -201,7 +203,7 @@ static char *my_strtok_r(char *str, const char *delim, char **saveptr) #define strtok_r my_strtok_r #endif -static void append(char **base, char *str) +static void append(char **base, const char *str) { char *oldbase; char *newbase; @@ -296,10 +298,75 @@ static void show_usage(const char *progname, const char *msg, int exitcode) exit(exitcode); } +/**************************************************************************** + * Name: do_shquote + * + * Description: + * Escape the given string for use with the shell. + * + * The idea was taken from: + * https://netbsd.gw.com/cgi-bin/man-cgi?shquote++NetBSD-current + * However, this implementation doesn't try to elide extraneous quotes. + ****************************************************************************/ + +static const char *do_shquote(const char *argument) +{ + const char *src; + char *dest; + int len; + + src = argument; + dest = g_shquote; + len = 0; + + if (len < sizeof(g_shquote)) + { + *dest++ = '\''; + len++; + } + + while (*src && len < sizeof(g_shquote)) + { + if (*src == '\'') + { + /* Expand single quote to '\'' */ + + if (len + 4 > sizeof(g_shquote)) + { + break; + } + + src++; + memcpy(dest, "\'\\\'\'", 4); + dest += 4; + len += 4; + } + else + { + *dest++ = *src++; + len++; + } + } + + if (*src || len + 2 > sizeof(g_shquote)) + { + fprintf(stderr, + "ERROR: Truncated during shquote string is too long" + "[%lu/%zu]\n", (unsigned long)strlen(argument), + sizeof(g_shquote)); + exit(EXIT_FAILURE); + } + + *dest++ = '\''; + *dest = '\0'; + return g_shquote; +} + static void parse_args(int argc, char **argv) { char *args = NULL; int argidx; + int group = 0; /* Always look in the current directory */ @@ -314,6 +381,7 @@ static void parse_args(int argc, char **argv) g_cc = g_cflags; g_cflags = args; args = NULL; + group++; } else if (strcmp(argv[argidx], "--dep-debug") == 0) { @@ -375,7 +443,27 @@ static void parse_args(int argc, char **argv) } else { - append(&args, argv[argidx]); + const char *arg = argv[argidx]; + + /* This condition means "perform shquote for + * g_cflags, but not g_cc or g_files". + * + * It isn't safe to escape g_cc becuase, for some reasons, + * Makefile passes it as a single argument like: + * + * $(MKDEP) $(DEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) + * + * It isn't safe to escape g_files becuase + * do_dependency() uses them as bare filenames as well. + * (In addition to passing them to system().) + */ + + if (group == 1) + { + arg = do_shquote(arg); + } + + append(&args, arg); } }