Blame SOURCES/ctags-CVE-2022-4515.patch

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