diff --git a/Tmain/abnormal-output-file-names.d/input.c b/Tmain/abnormal-output-file-names.d/input.c new file mode 100644 index 0000000000..6d1a0d47b7 --- /dev/null +++ b/Tmain/abnormal-output-file-names.d/input.c @@ -0,0 +1 @@ +int x; diff --git a/Tmain/abnormal-output-file-names.d/run.sh b/Tmain/abnormal-output-file-names.d/run.sh new file mode 100644 index 0000000000..b15a766c1a --- /dev/null +++ b/Tmain/abnormal-output-file-names.d/run.sh @@ -0,0 +1,39 @@ +# Copyright: 2016 Masatake YAMATO +# License: GPL-2 + +CTAGS=$1 + +rm -f ./"'" +rm -f ./'"' +rm -f ./'$(ls)' +rm -f ./'a b' + +${CTAGS} --quiet --options=NONE -o ./"'" --extra=-pF input.c +${CTAGS} --quiet --options=NONE -o ./'"' --extra=-pF input.c +${CTAGS} --quiet --options=NONE -o ./'$(ls)' --extra=-pF input.c +${CTAGS} --quiet --options=NONE -o ./'a b' --extra=-pF input.c + +echo '#' SINGLE QUOTE +if [ -e "'" ]; then + cat "'" +fi + +echo '#' DOUBLE QUOTES +if [ -e '"' ]; then + cat '"' +fi + +echo '#' PROCESS SUBSTITUTION +if [ -e '$(ls)' ]; then + cat '$(ls)' +fi + +echo '#' SPACE +if [ -e 'a b' ]; then + cat 'a b' +fi + +rm -f ./"'" +rm -f ./'"' +rm -f ./'$(ls)' +rm -f ./'a b' diff --git a/Tmain/abnormal-output-file-names.d/stderr-expected.txt b/Tmain/abnormal-output-file-names.d/stderr-expected.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tmain/abnormal-output-file-names.d/stdout-expected.txt b/Tmain/abnormal-output-file-names.d/stdout-expected.txt new file mode 100644 index 0000000000..5d1129ea84 --- /dev/null +++ b/Tmain/abnormal-output-file-names.d/stdout-expected.txt @@ -0,0 +1,8 @@ +# SINGLE QUOTE +x input.c /^int x;$/;" v typeref:typename:int +# DOUBLE QUOTES +x input.c /^int x;$/;" v typeref:typename:int +# PROCESS SUBSTITUTION +x input.c /^int x;$/;" v typeref:typename:int +# SPACE +x input.c /^int x;$/;" v typeref:typename:int diff --git a/main/sort.c b/main/sort.c index 7ee7ce0a23..46ffd48a3d 100644 --- a/main/sort.c +++ b/main/sort.c @@ -55,17 +55,44 @@ extern void catFile (MIO *mio) # define PE_CONST const #endif +/* + Output file name should not be evaluated in system(3) function. + The name must be used as is. Quotations are required to block the + evaluation. + + Normal single-quotes are used to quote a cstring: + a => 'a' + " => '"' + + If a single-quote is included in the cstring, use double quotes for quoting it. + ' => ''"'"'' +*/ +static void appendCstringWithQuotes (vString *dest, const char* cstr) +{ + const char* o; + + vStringPut (dest, '\''); + for (o = cstr; *o; o++) + { + if (*o == '\'') + vStringCatS (dest, "'\"'\"'"); + else + vStringPut (dest, *o); + } + vStringPut (dest, '\''); +} + extern void externalSortTags (const bool toStdout, MIO *tagFile) { const char *const sortNormalCommand = "sort -u"; const char *const sortFoldedCommand = "sort -u -f"; const char *sortCommand = Option.sorted == SO_FOLDSORTED ? sortFoldedCommand : sortNormalCommand; +# ifndef HAVE_SETENV PE_CONST char *const sortOrder1 = "LC_COLLATE=C"; PE_CONST char *const sortOrder2 = "LC_ALL=C"; - const size_t length = 4 + strlen (sortOrder1) + strlen (sortOrder2) + - strlen (sortCommand) + (2 * strlen (tagFileName ())); - char *const cmd = (char *) malloc (length + 1); +# endif + vString *cmd = vStringNew (); int ret = -1; if (cmd != NULL) @@ -80,19 +107,29 @@ extern void externalSortTags (const bool toStdout, MIO *tagFile) putenv (sortOrder1); putenv (sortOrder2); # endif - if (toStdout) - sprintf (cmd, "%s", sortCommand); - else - sprintf (cmd, "%s -o %s %s", sortCommand, - tagFileName (), tagFileName ()); + vStringCatS (cmd, sortCommand); + if (! toStdout) + { + vStringCatS (cmd, " -o "); + appendCstringWithQuotes (cmd, tagFileName ()); + vStringPut (cmd, ' '); + appendCstringWithQuotes (cmd, tagFileName ()); + } #else - if (toStdout) - sprintf (cmd, "%s %s %s", sortOrder1, sortOrder2, sortCommand); - else - sprintf (cmd, "%s %s %s -o %s %s", sortOrder1, sortOrder2, - sortCommand, tagFileName (), tagFileName ()); + vStringCatS (cmd, sortOrder1); + vStringPut (cmd, ' '); + vStringCatS (cmd, sortOrder2); + vStringPut (cmd, ' '); + vStringCatS (cmd, sortCommand); + if (! toStdout) + { + vStringCats (cmd, " -o "); + appendCstringWithQuotes (cmd, tagFileName ()); + vStringPut (cmd, ' '); + appendCstringWithQuotes (cmd, tagFileName ()); + } #endif - verbose ("system (\"%s\")\n", cmd); + verbose ("system (\"%s\")\n", vStringValue (cmd)); if (toStdout) { const int fdstdin = 0; @@ -105,15 +142,14 @@ extern void externalSortTags (const bool toStdout, MIO *tagFile) error (FATAL | PERROR, "cannot redirect stdin"); if (lseek (fdstdin, 0, SEEK_SET) != 0) error (FATAL | PERROR, "cannot rewind tag file"); - ret = system (cmd); + ret = system (vStringValue (cmd)); if (dup2 (fdsave, fdstdin) < 0) error (FATAL | PERROR, "cannot restore stdin fd"); close (fdsave); } else - ret = system (cmd); - free (cmd); - + ret = system (vStringValue (cmd)); + vStringDelete (cmd); } if (ret != 0) error (FATAL | PERROR, "cannot sort tag file");