On Windows, GCC is very likely to be installed in a directory
containing spaces. The patch from the original PR was used
downstream in MSYS2, while this patch provides a more general
way to fix the issue.

Currently, there is no dedicated test suite for specs. I have a
script for roughly checking the functionality of this part.

Bootstrapped and regtested on x86_64-linux-gnu and x86_64-w64-mingw32.

-- >8 --

do_spec_1() treats whitespace characters (' ' and '\t') as argument
terminators, causing splitting to occur. Therefore, we need to wrap
all spec functions whose return values should not be split
(e.g. file path) with the quote_spec() function. For example,
"dir with space/something.o" will be split into
"dir" "with" and "space/something.o".

pass_through_libs_spec_func() is somewhat special because the
multiple arguments it returns are expected to be split by ' ', but
each individual argument should not be split. Therefore, each
individual argument must be quoted first and then concatenated.

        PR driver/90692

gcc/ChangeLog:

        * gcc.cc (if_exists_spec_function): Escape special characters.
        (if_exists_else_spec_function): Likewise.
        (if_exists_then_else_spec_function): Likewise.
        (version_compare_spec_function): Likewise.
        (find_file_spec_function): Likewise.
        (find_plugindir_spec_function): Likewise.
        (pass_through_libs_spec_func): Likewise.
        (find_fortran_preinclude_file): Likewise.

Signed-off-by: Wang Jinghao <[email protected]>
---
 gcc/gcc.cc | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 43b0158ee02..82f1e23b500 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -10532,7 +10532,7 @@ if_exists_spec_function (int argc, const char **argv)
 {
   /* Must have only one argument.  */
   if (argc == 1 && IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
-    return argv[0];
+    return quote_spec (xstrdup (argv[0]));
 
   return NULL;
 }
@@ -10550,9 +10550,9 @@ if_exists_else_spec_function (int argc, const char 
**argv)
     return NULL;
 
   if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
-    return argv[0];
+    return quote_spec (xstrdup (argv[0]));
 
-  return argv[1];
+  return quote_spec (xstrdup (argv[1]));
 }
 
 /* if-exists-then-else built-in spec function.
@@ -10570,10 +10570,10 @@ if_exists_then_else_spec_function (int argc, const 
char **argv)
     return NULL;
 
   if (IS_ABSOLUTE_PATH (argv[0]) && ! access (argv[0], R_OK))
-    return argv[1];
+    return quote_spec (xstrdup (argv[1]));
 
   if (argc == 3)
-    return argv[2];
+    return quote_spec (xstrdup (argv[2]));
 
   return NULL;
 }
@@ -10771,7 +10771,7 @@ version_compare_spec_function (int argc, const char 
**argv)
   if (! result)
     return NULL;
 
-  return argv[nargs + 2];
+  return quote_spec (xstrdup (argv[nargs + 2]));
 }
 
 /* %:include builtin spec function.  This differs from %include in that it
@@ -10805,7 +10805,7 @@ find_file_spec_function (int argc, const char **argv)
     abort ();
 
   file = find_file (argv[0]);
-  return file;
+  return quote_spec (xstrdup (file));
 }
 
 
@@ -10815,13 +10815,13 @@ find_file_spec_function (int argc, const char **argv)
 static const char *
 find_plugindir_spec_function (int argc, const char **argv ATTRIBUTE_UNUSED)
 {
-  const char *option;
+  char *option;
 
   if (argc != 0)
     abort ();
 
   option = concat ("-iplugindir=", find_file ("plugin"), NULL);
-  return option;
+  return quote_spec (option);
 }
 
 
@@ -10999,13 +10999,17 @@ pass_through_libs_spec_func (int argc, const char 
**argv)
            break;
          else if (!*lopt)
            lopt = argv[n];
-         prepended = concat (prepended, "-plugin-opt=-pass-through=-l",
-               lopt, " ", NULL);
+         char *arg = concat ("-plugin-opt=-pass-through=-l", lopt, NULL);
+         arg = quote_spec (arg);
+         prepended = concat (prepended, arg, " ", NULL);
+         free (arg);
        }
       else if (!strcmp (".a", argv[n] + strlen (argv[n]) - 2))
        {
-         prepended = concat (prepended, "-plugin-opt=-pass-through=",
-               argv[n], " ", NULL);
+         char *arg = concat ("-plugin-opt=-pass-through=", argv[n], NULL);
+         arg = quote_spec (arg);
+         prepended = concat (prepended, arg, " ", NULL);
+         free (arg);
        }
       if (prepended != old)
        free (old);
@@ -11235,6 +11239,8 @@ find_fortran_preinclude_file (int argc, const char 
**argv)
     }
 
   path_prefix_reset (&prefixes);
+  if (result)
+    result = quote_spec (result);
   return result;
 }
 
-- 
2.52.0

Reply via email to