Currently, commands like:
gcc -o file.c -lm
will delete the user's code.

This patch checks the suffix of the output, and errors if the output ends in
any of the suffixes listed in default_compilers.

Unfortunately, I couldn't come up with a better heuristic to diagnose this case
more specifically, so it is now not possible to directly make executables with
said suffixes. I am unsure if any users are depending on this.

        PR driver/80182
        * gcc.cc (process_command): fatal_error if the output has the suffix of
          a source file.
        (have_c): Change type to bool.
        (have_O): Change type to bool.
        (have_E): Change type to bool.
        (have_S): New global variable.
        (driver_handle_option): Assign have_S

Signed-off-by: Peter Damianov <peter0...@disroot.org>
---
 gcc/gcc.cc | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 830a4700a87..53169c16460 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2127,13 +2127,16 @@ static vec<const_char_p> at_file_argbuf;
 static bool in_at_file = false;
 
 /* Were the options -c, -S or -E passed.  */
-static int have_c = 0;
+static bool have_c = false;
 
 /* Was the option -o passed.  */
-static int have_o = 0;
+static bool have_o = false;
 
 /* Was the option -E passed.  */
-static int have_E = 0;
+static bool have_E = false;
+
+/* Was the option -S passed.  */
+static bool have_S = false;
 
 /* Pointer to output file name passed in with -o. */
 static const char *output_file = 0;
@@ -4593,6 +4596,10 @@ driver_handle_option (struct gcc_options *opts,
       have_E = true;
       break;
 
+    case OPT_S:
+      have_S = true;
+      break;
+
     case OPT_x:
       spec_lang = arg;
       if (!strcmp (spec_lang, "none"))
@@ -5058,6 +5065,22 @@ process_command (unsigned int decoded_options_count,
                       output_file);
     }
 
+  /* Reject output file names that have the same suffix as a source
+     file. This is to catch mistakes like: gcc -o file.c -lm
+     that could delete the user's code. */
+  if (have_o && output_file != NULL && !have_E && !have_S)
+    {
+      const char* filename = lbasename(output_file);
+      const char* suffix = strchr(filename, '.');
+      if (suffix != NULL)
+       for (int i = 0; i < n_default_compilers; ++i)
+         if (!strcmp(suffix, default_compilers[i].suffix))
+           fatal_error (input_location,
+                        "output file suffix %qs could be a source file",
+                        suffix);
+    }
+
+
   if (output_file != NULL && output_file[0] == '\0')
     fatal_error (input_location, "output filename may not be empty");
 
-- 
2.39.2

Reply via email to