153 lines
5.3 KiB
Diff
153 lines
5.3 KiB
Diff
commit 2b7cd725d0612f13eb5a461778ca525cd489119b
|
|
Author: Masatake YAMATO <yamato@redhat.com>
|
|
Date: Tue Dec 13 05:16:00 2022 +0900
|
|
|
|
main: quote output file name before passing it to system(3) function
|
|
|
|
Following command line doesn't work:
|
|
|
|
$ ctags -o 'a b' ...
|
|
|
|
because a shell lauched from system(3) deals a whitespace between 'a'
|
|
and 'b' as a separator. The output file name is passed to system(3)
|
|
to run external sort command.
|
|
|
|
This commit adds code to put double and single quoets around the output
|
|
file name before passing it to system(3).
|
|
|
|
The issue is reported by Lorenz Hipp <lhipp@idealbonn.de> in a private mail.
|
|
|
|
This commit is based on e00c55d7a0204dc1d0ae316141323959e1e16162 of
|
|
Universal Ctags <https://github.com/universal-ctags/ctags>.
|
|
|
|
An example session of RHEL8:
|
|
|
|
[yamato@control]/tmp/ctags-5.8% git clone ssh://git@gitlab.consulting.redhat.com:2222/yamato/temp-test.git
|
|
Cloning into 'temp-test'...
|
|
Enter passphrase for key '/home/yamato/.ssh/id_rsa':
|
|
remote: Enumerating objects: 4, done.
|
|
remote: Counting objects: 100% (4/4), done.
|
|
remote: Compressing objects: 100% (4/4), done.
|
|
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
|
|
Receiving objects: 100% (4/4), done.
|
|
[yamato@control]/tmp/ctags-5.8% cd temp-test
|
|
[yamato@control]/tmp/ctags-5.8/temp-test% ls -l ~/.ctags
|
|
ls: cannot access '/home/yamato/.ctags': No such file or directory
|
|
[yamato@control]/tmp/ctags-5.8/temp-test% ../ctags hello.c
|
|
[yamato@control]/tmp/ctags-5.8/temp-test% ls
|
|
hello.c 'tags tags; echo Hi $(id -un), your systems is cracked!'
|
|
[yamato@control]/tmp/ctags-5.8/temp-test% valgrind ../ctags hello.c
|
|
==2076943== Memcheck, a memory error detector
|
|
==2076943== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
|
|
==2076943== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
|
|
==2076943== Command: ../ctags hello.c
|
|
==2076943==
|
|
==2076943==
|
|
==2076943== HEAP SUMMARY:
|
|
==2076943== in use at exit: 0 bytes in 0 blocks
|
|
==2076943== total heap usage: 5,048 allocs, 5,048 frees, 365,311 bytes allocated
|
|
==2076943==
|
|
==2076943== All heap blocks were freed -- no leaks are possible
|
|
==2076943==
|
|
==2076943== For lists of detected and suppressed errors, rerun with: -s
|
|
==2076943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
|
|
|
|
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
|
|
|
|
diff --git a/sort.c b/sort.c
|
|
index 09ba87a..fd60a94 100644
|
|
--- a/sort.c
|
|
+++ b/sort.c
|
|
@@ -53,17 +53,44 @@ extern void catFile (const char *const name)
|
|
# 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 boolean toStdout)
|
|
{
|
|
const char *const sortNormalCommand = "sort -u -o";
|
|
const char *const sortFoldedCommand = "sort -u -f -o";
|
|
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)
|
|
@@ -73,20 +100,35 @@ extern void externalSortTags (const boolean toStdout)
|
|
#ifdef HAVE_SETENV
|
|
setenv ("LC_COLLATE", "C", 1);
|
|
setenv ("LC_ALL", "C", 1);
|
|
- sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
|
|
+ vStringCatS (cmd, sortCommand);
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
#else
|
|
# ifdef HAVE_PUTENV
|
|
putenv (sortOrder1);
|
|
putenv (sortOrder2);
|
|
- sprintf (cmd, "%s %s %s", sortCommand, tagFileName (), tagFileName ());
|
|
+ vStringCatS (cmd, sortCommand);
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
# else
|
|
- sprintf (cmd, "%s %s %s %s %s", sortOrder1, sortOrder2, sortCommand,
|
|
- tagFileName (), tagFileName ());
|
|
+ vStringCatS (cmd, sortOrder1);
|
|
+ vStringPut (cmd, ' ');
|
|
+ vStringCatS (cmd, sortOrder2);
|
|
+ vStringPut (cmd, ' ');
|
|
+ vStringCatS (cmd, sortCommand);
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
+ vStringPut (cmd, ' ');
|
|
+ appendCstringWithQuotes (cmd, tagFileName ());
|
|
# endif
|
|
#endif
|
|
- verbose ("system (\"%s\")\n", cmd);
|
|
- ret = system (cmd);
|
|
- free (cmd);
|
|
+ verbose ("system (\"%s\")\n", vStringValue (cmd));
|
|
+ ret = system (vStringValue (cmd));
|
|
+ vStringDelete (cmd);
|
|
|
|
}
|
|
if (ret != 0)
|
|
|