On Sat, May 4, 2024 at 9:36 PM Peter Damianov <peter0...@disroot.org> wrote:
>
> Currently, commands like:
> gcc -o file.c -lm
> will delete the user's code.

Since there's an error from the linker in the end (missing 'main'), I wonder if
the linker can avoid truncating/opening the output file instead?  A trivial
solution might be to open a temporary file first and only atomically replace
the output file with the temporary file when there were no errors?

> 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.

A way to provide a workaround would be to require the file not existing.  So
change the heuristic to only trigger if the output file exists (and is
non-empty?).

Richard.

>         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