1
0
Fork 0
forked from nuttx/nuttx-update

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="<mbedtls/user_config.h>"

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. 4464250282/usr.bin/mkdep/mkdep.c (L137-L154)
but i might be a burden for windows. (i don't know)
This commit is contained in:
YAMAMOTO Takashi 2020-06-03 13:47:55 +09:00 committed by Xiang Xiao
parent 698ac72dae
commit 16884407eb

View file

@ -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);
}
}