public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] driver: Output to a temp file; rename upon success [PR80182]
@ 2024-05-11 14:41 Peter Damianov
  0 siblings, 0 replies; only message in thread
From: Peter Damianov @ 2024-05-11 14:41 UTC (permalink / raw)
  To: gcc-patches; +Cc: richard.guenther, iain, Peter Damianov

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

This patch makes the linker write executables to a temp file, and then renames
the temp file if successful. This fixes the case above, but has limitations.
The source file will still get overwritten if the link "succeeds", such as the
case of: gcc -o file.c -lm -r

It's not perfect, but it should hopefully stop some people from ruining their
day.

gcc/ChangeLog:
	PR driver/80182
	* gcc.cc (output_file_temp): New global variable
	(driver_handle_option): Create temp file for executable output
	(driver::maybe_run_linker): Rename output_file_temp to output_file if
	the linker ran successfully

Signed-off-by: Peter Damianov <peter0x44@disroot.org>
---
 gcc/gcc.cc | 50 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 33 insertions(+), 17 deletions(-)

diff --git a/gcc/gcc.cc b/gcc/gcc.cc
index 830a4700a87..cd796d190de 100644
--- a/gcc/gcc.cc
+++ b/gcc/gcc.cc
@@ -2138,6 +2138,11 @@ static int have_E = 0;
 /* Pointer to output file name passed in with -o. */
 static const char *output_file = 0;
 
+/* We write the output file to a temp file, and rename it if linking
+   is successful. This is to prevent mistakes like: gcc -o file.c -lm from
+   deleting the user's code.  */
+static const char *output_file_temp = 0;
+
 /* Pointer to input file name passed in with -truncate.
    This file should be truncated after linking. */
 static const char *totruncate_file = 0;
@@ -2294,7 +2299,7 @@ close_at_file (void)
 
   record_temp_file (temp_file, !save_temps_flag, !save_temps_flag);
 }
-\f
+
 /* Load specs from a file name named FILENAME, replacing occurrences of
    various different types of line-endings, \r\n, \n\r and just \r, with
    a single \n.  */
@@ -4610,10 +4615,13 @@ driver_handle_option (struct gcc_options *opts,
 #if defined(HAVE_TARGET_EXECUTABLE_SUFFIX) || defined(HAVE_TARGET_OBJECT_SUFFIX)
       arg = convert_filename (arg, ! have_c, 0);
 #endif
-      output_file = arg;
+      output_file_temp = output_file = arg;
+      /* If creating an executable, output to a temp file.  */
+      if (!have_c)
+	output_file_temp = make_temp_file("");
       /* On some systems, ld cannot handle "-o" without a space.  So
 	 split the option from its argument.  */
-      save_switch ("-o", 1, &arg, validated, true);
+      save_switch ("-o", 1, &output_file_temp, validated, true);
       return true;
 
     case OPT_pie:
@@ -9266,22 +9274,30 @@ driver::maybe_run_linker (const char *argv0) const
       linker_was_run = (tmp != execution_count);
     }
 
-  /* If options said don't run linker,
-     complain about input files to be given to the linker.  */
-
-  if (! linker_was_run && !seen_error ())
-    for (i = 0; (int) i < n_infiles; i++)
-      if (explicit_link_files[i]
-	  && !(infiles[i].language && infiles[i].language[0] == '*'))
+  if (!seen_error ())
+    {
+      if (linker_was_run)
+	/* If the linker finished without errors, rename the output from the
+	   temporary file to the real output name.  */
+	rename(output_file_temp, output_file);
+      else
 	{
-	  warning (0, "%s: linker input file unused because linking not done",
-		   outfiles[i]);
-	  if (access (outfiles[i], F_OK) < 0)
-	    /* This is can be an indication the user specifed an errorneous
-	       separated option value, (or used the wrong prefix for an
-	       option).  */
-	    error ("%s: linker input file not found: %m", outfiles[i]);
+	  /* If options said don't run linker,
+	     complain about input files to be given to the linker.  */
+	  for (i = 0; (int) i < n_infiles; i++)
+	    if (explicit_link_files[i]
+		&& !(infiles[i].language && infiles[i].language[0] == '*'))
+	      {
+		warning (0, "%s: linker input file unused because linking not done",
+			 outfiles[i]);
+		if (access (outfiles[i], F_OK) < 0)
+		  /* This is can be an indication the user specifed an errorneous
+		     separated option value, (or used the wrong prefix for an
+		     option).  */
+		  error ("%s: linker input file not found: %m", outfiles[i]);
+	      }
 	}
+    }
 }
 
 /* The end of "main".  */
-- 
2.39.2


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-05-11 14:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-11 14:41 [PATCH] driver: Output to a temp file; rename upon success [PR80182] Peter Damianov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).