Users might be using a space in their build directory path. To allow
specifying such a root for the module mapper started by GCC, we need the
command to allow quotes. Previously quoting a path passed to the module
mapper was not possible, so replace the custom argv parsing with
wordexp(), which supports standard shell quoting rules.

This also should fix PR110153, although my intention was really to fix
passing parameters to the "--root" parameter.

I'm somewhat unsure about using wordexp. This function seems to be
referenced by libsanitizer already, but maybe "core" GCC can not depend
on the function? Do I need to add any system checks? I think it is
widely supported, but I am not that familiar with requirements regarding
standard library functions.

PR c++/110153

Signed-off-by: Nicolas Werner <nicolas.wer...@hotmail.de>
---
 gcc/cp/mapper-client.cc | 36 +++++++++++++-----------------------
 1 file changed, 13 insertions(+), 23 deletions(-)

diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
index 9477feeee31..bf91b825bc0 100644
--- a/gcc/cp/mapper-client.cc
+++ b/gcc/cp/mapper-client.cc
@@ -28,6 +28,7 @@ along with GCC; see the file COPYING3.  If not see
 #define INCLUDE_VECTOR
 #define INCLUDE_MAP
 #include "system.h"
+#include <wordexp.h>
 
 #include "line-map.h"
 #include "rich-location.h"
@@ -59,29 +60,17 @@ spawn_mapper_program (char const **errmsg, std::string 
&name,
   char *str = new char[name.size ()];
   memcpy (str, name.c_str () + 1, name.size ());
 
-  for (auto ptr = str; ; ++ptr)
-    {
-      while (*ptr == ' ')
-       ptr++;
-      if (!*ptr)
-       break;
-
-      if (!arg_no)
-       {
-         /* @name means look in the compiler's install dir.  */
-         if (ptr[0] == '@')
-           ptr++;
-         else
-           full_program_name = nullptr;
-       }
-
-      argv[arg_no++] = ptr;
-      while (*ptr && *ptr != ' ')
-       ptr++;
-      if (!*ptr)
-       break;
-      *ptr = 0;
-    }
+  wordexp_t words = {};
+  wordexp (str, &words, WRDE_UNDEF|WRDE_NOCMD);
+  for (size_t i = 0; i < words.we_wordc && i < name.size () / 2 + 1; i++)
+  {
+    argv[i] = words.we_wordv[i];
+    arg_no++;
+  }
+  if (arg_no && argv[0][0] == '@')
+    argv[0] = argv[0] + 1;
+  else
+    full_program_name = nullptr;
   argv[arg_no] = nullptr;
 
   auto *pex = pex_init (PEX_USE_PIPES, progname, NULL);
@@ -110,6 +99,7 @@ spawn_mapper_program (char const **errmsg, std::string 
&name,
     }
   delete[] str;
   delete[] argv;
+  wordfree (&words);
 
   int fd_from = -1, fd_to = -1;
   if (!*errmsg)
-- 
2.49.0




Reply via email to