aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony Brandon <anthony.brandon@gmail.com>2014-11-05 17:23:46 +0000
committerManuel López-Ibáñez <manu@gcc.gnu.org>2014-11-05 17:23:46 +0000
commit9c7a77fcc3d2895ec72639aa7a2067280a612268 (patch)
treef8a561245dafdb2b46ed8280e973df9662ea69bd
parent701cade1a260d5a78662e304a7cac0aaf2d77951 (diff)
downloadgcc-9c7a77fcc3d2895ec72639aa7a2067280a612268.zip
gcc-9c7a77fcc3d2895ec72639aa7a2067280a612268.tar.gz
gcc-9c7a77fcc3d2895ec72639aa7a2067280a612268.tar.bz2
re PR driver/36312 (should refuse to overwrite input file with output file)
gcc/testsuite/ChangeLog: 2014-11-05 Anthony Brandon <anthony.brandon@gmail.com> PR driver/36312 * gcc.misc-tests/output.exp: New test case for identical input and output files. include/ChangeLog: 2014-11-05 Anthony Brandon <anthony.brandon@gmail.com> PR driver/36312 * filenames.h: Add prototype for canonical_filename_eq. gcc/ChangeLog: 2014-11-05 Anthony Brandon <anthony.brandon@gmail.com> PR driver/36312 * diagnostic-core.h: Add prototype for fatal_error. * diagnostic.c (fatal_error): New function fatal_error. * gcc.c (store_arg): Remove have_o_argbuf_index. (process_command): Check if input and output files are the same. * toplev.c (init_asm_output): Check if input and output files are the same. libiberty/ChangeLog: 2014-11-05 Anthony Brandon <anthony.brandon@gmail.com> PR driver/36312 * filename_cmp.c (canonical_filename_eq): New function to check if file names are the same. * functions.texi: Updated with documentation for new function. From-SVN: r217149
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/diagnostic-core.h2
-rw-r--r--gcc/diagnostic.c17
-rw-r--r--gcc/gcc.c19
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.misc-tests/output.exp66
-rw-r--r--gcc/toplev.c11
-rw-r--r--include/ChangeLog5
-rw-r--r--include/filenames.h2
-rw-r--r--libiberty/ChangeLog7
-rw-r--r--libiberty/filename_cmp.c29
-rw-r--r--libiberty/functions.texi18
12 files changed, 179 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c5b14a0..778ce1f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+2014-11-05 Anthony Brandon <anthony.brandon@gmail.com>
+
+ PR driver/36312
+ * diagnostic-core.h: Add prototype for fatal_error.
+ * diagnostic.c (fatal_error): New function fatal_error.
+ * gcc.c (store_arg): Remove have_o_argbuf_index.
+ (process_command): Check if input and output files are the same.
+ * toplev.c (init_asm_output): Check if input and output files are
+ the same.
+
2014-11-05 Joseph Myers <joseph@codesourcery.com>
PR preprocessor/9449
diff --git a/gcc/diagnostic-core.h b/gcc/diagnostic-core.h
index a8245de8..2fba279 100644
--- a/gcc/diagnostic-core.h
+++ b/gcc/diagnostic-core.h
@@ -68,6 +68,8 @@ extern void error_n (location_t, int, const char *, const char *, ...)
extern void error_at (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3);
extern void fatal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
ATTRIBUTE_NORETURN;
+extern void fatal_error (location_t, const char *, ...) ATTRIBUTE_GCC_DIAG(2,3)
+ ATTRIBUTE_NORETURN;
/* Pass one of the OPT_W* from options.h as the second parameter. */
extern bool pedwarn (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 642cbe3..f7f8aaa 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1163,6 +1163,23 @@ fatal_error (const char *gmsgid, ...)
gcc_unreachable ();
}
+/* An error which is severe enough that we make no attempt to
+ continue. Do not use this for internal consistency checks; that's
+ internal_error. Use of this function should be rare. */
+void
+fatal_error (location_t loc, const char *gmsgid, ...)
+{
+ diagnostic_info diagnostic;
+ va_list ap;
+
+ va_start (ap, gmsgid);
+ diagnostic_set_info (&diagnostic, gmsgid, &ap, loc, DK_FATAL);
+ report_diagnostic (&diagnostic);
+ va_end (ap);
+
+ gcc_unreachable ();
+}
+
/* An internal consistency check has failed. We make no attempt to
continue. Note that unless there is debugging value to be had from
a more specific message, or some other good reason, you should use
diff --git a/gcc/gcc.c b/gcc/gcc.c
index e013d52..6f144de 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -1702,17 +1702,15 @@ typedef const char *const_char_p; /* For DEF_VEC_P. */
static vec<const_char_p> argbuf;
-/* Position in the argbuf vector containing the name of the output file
- (the value associated with the "-o" flag). */
-
-static int have_o_argbuf_index = 0;
-
/* Were the options -c, -S or -E passed. */
static int have_c = 0;
/* Was the option -o passed. */
static int have_o = 0;
+/* Pointer to output file name passed in with -o. */
+static const char *output_file = 0;
+
/* This is the list of suffixes and codes (%g/%u/%U/%j) and the associated
temp file. If the HOST_BIT_BUCKET is used for %j, no entry is made for
it here. */
@@ -1762,8 +1760,6 @@ store_arg (const char *arg, int delete_always, int delete_failure)
{
argbuf.safe_push (arg);
- if (strcmp (arg, "-o") == 0)
- have_o_argbuf_index = argbuf.length ();
if (delete_always || delete_failure)
{
const char *p;
@@ -3713,6 +3709,7 @@ 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;
/* Save the output name in case -save-temps=obj was used. */
save_temps_prefix = xstrdup (arg);
/* On some systems, ld cannot handle "-o" without a space. So
@@ -4052,6 +4049,14 @@ process_command (unsigned int decoded_options_count,
CL_DRIVER, &handlers, global_dc);
}
+ if (output_file && strcmp (output_file, "-"))
+ {
+ int i;
+ for (i = 0; i < n_infiles; i++)
+ if (canonical_filename_eq (infiles[i].name, output_file))
+ fatal_error ("output file %s is the same as input file", output_file);
+ }
+
/* If -save-temps=obj and -o name, create the prefix to use for %b.
Otherwise just make -save-temps=obj the same as -save-temps=cwd. */
if (save_temps_flag == SAVE_TEMPS_OBJ && save_temps_prefix != NULL)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 924ed28..a8aa838 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-11-05 Anthony Brandon <anthony.brandon@gmail.com>
+
+ PR driver/36312
+ * gcc.misc-tests/output.exp: New test case for identical input and
+ output files.
+
2014-11-05 Joseph Myers <joseph@codesourcery.com>
PR preprocessor/9449
diff --git a/gcc/testsuite/gcc.misc-tests/output.exp b/gcc/testsuite/gcc.misc-tests/output.exp
new file mode 100644
index 0000000..aac7607
--- /dev/null
+++ b/gcc/testsuite/gcc.misc-tests/output.exp
@@ -0,0 +1,66 @@
+# Copyright (C) 2005-2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Run GCC with the input file also specified as output file. Check that the
+# compiler prints an error message and does not overwrite the input file.
+
+load_lib gcc-defs.exp
+load_lib target-supports.exp
+
+# These tests don't run runtest_file_p consistently if it
+# doesn't return the same values, so disable parallelization
+# of this *.exp file. The first parallel runtest to reach
+# this will run all the tests serially.
+if ![gcc_parallel_test_run_p output] {
+ return
+}
+
+# I'm not sure if this is needed here. It was in options.exp.
+gcc_parallel_test_enable 0
+
+proc check_gcc_overwrite_input {} {
+ set filename test-[pid]
+ set fd [open $filename.c w]
+ puts $fd "int main (void) \{ return 0; \}"
+ close $fd
+ remote_download host $filename.c
+ set test "input overwrite test"
+ set compiler cc1
+ set gcc_output [gcc_target_compile $filename.c $filename.c executable ""]
+
+ # Is this right, or do I need to use something like remote_upload?
+ set fd [open $filename.c r]
+ set file_data [read $fd]
+ close $fd
+ remote_file build delete $filename.c
+
+ # check if the contents of the input file has changed
+ if {!($file_data eq "int main (void) \{ return 0; \}\n")} {
+ fail "$test (input overwritten)"
+ return
+ }
+
+ # check if the error message was printed
+ if {![regexp -- "same as input" $gcc_output]} {
+ fail "$test (no error printed)"
+ return
+ }
+ pass $test
+}
+
+check_gcc_overwrite_input
+
+gcc_parallel_test_enable 1
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9c75dd8..d3bd35c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -942,10 +942,17 @@ init_asm_output (const char *name)
}
if (!strcmp (asm_file_name, "-"))
asm_out_file = stdout;
- else
+ else if (!canonical_filename_eq (asm_file_name, name))
asm_out_file = fopen (asm_file_name, "w");
+ else
+ /* Use fatal_error (UNKOWN_LOCATION) instead of just fatal_error to
+ prevent gcc from printing the first line in the current file. */
+ fatal_error (UNKNOWN_LOCATION,
+ "output file %s is the same as input file",
+ asm_file_name);
if (asm_out_file == 0)
- fatal_error ("can%'t open %s for writing: %m", asm_file_name);
+ fatal_error (UNKNOWN_LOCATION,
+ "can%'t open %s for writing: %m", asm_file_name);
}
if (!flag_syntax_only)
diff --git a/include/ChangeLog b/include/ChangeLog
index e482682..27c3c55 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2014-11-05 Anthony Brandon <anthony.brandon@gmail.com>
+
+ PR driver/36312
+ * filenames.h: Add prototype for canonical_filename_eq.
+
2014-10-28 Richard Henderson <rth@redhat.com>
* longlong.h [__alpha] (umul_ppmm): Disable for c++.
diff --git a/include/filenames.h b/include/filenames.h
index e799a51..470c5e0 100644
--- a/include/filenames.h
+++ b/include/filenames.h
@@ -90,6 +90,8 @@ extern hashval_t filename_hash (const void *s);
extern int filename_eq (const void *s1, const void *s2);
+extern int canonical_filename_eq (const char *a, const char *b);
+
#ifdef __cplusplus
}
#endif
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index ff06b18..738965c 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-05 Anthony Brandon <anthony.brandon@gmail.com>
+
+ PR driver/36312
+ * filename_cmp.c (canonical_filename_eq): New function to check if
+ file names are the same.
+ * functions.texi: Updated with documentation for new function.
+
2014-11-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* sigsetmask.c (_POSIX_SOURCE): Remove.
diff --git a/libiberty/filename_cmp.c b/libiberty/filename_cmp.c
index 9e16d24..150488c 100644
--- a/libiberty/filename_cmp.c
+++ b/libiberty/filename_cmp.c
@@ -24,8 +24,13 @@
#include <string.h>
#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
#include "filenames.h"
#include "safe-ctype.h"
+#include "libiberty.h"
/*
@@ -190,3 +195,27 @@ filename_eq (const void *s1, const void *s2)
/* The casts are for -Wc++-compat. */
return filename_cmp ((const char *) s1, (const char *) s2) == 0;
}
+
+/*
+
+@deftypefn Extension int canonical_filename_eq (const char *@var{a}, const char *@var{b})
+
+Return non-zero if file names @var{a} and @var{b} are equivalent.
+This function compares the canonical versions of the filenames as returned by
+@code{lrealpath()}, so that so that different file names pointing to the same
+underlying file are treated as being identical.
+
+@end deftypefn
+
+*/
+
+int
+canonical_filename_eq (const char * a, const char * b)
+{
+ char * ca = lrealpath(a);
+ char * cb = lrealpath(b);
+ int res = filename_eq (ca, cb);
+ free (ca);
+ free (cb);
+ return res;
+}
diff --git a/libiberty/functions.texi b/libiberty/functions.texi
index 3627285..9ed9ff0 100644
--- a/libiberty/functions.texi
+++ b/libiberty/functions.texi
@@ -125,6 +125,16 @@ Uses @code{malloc} to allocate storage for @var{nelem} objects of
@end deftypefn
+@c filename_cmp.c:201
+@deftypefn Extension int canonical_filename_eq (const char *@var{a}, const char *@var{b})
+
+Return non-zero if file names @var{a} and @var{b} are equivalent.
+This function compares the canonical versions of the filenames as returned by
+@code{lrealpath()}, so that so that different file names pointing to the same
+underlying file are treated as being identical.
+
+@end deftypefn
+
@c choose-temp.c:45
@deftypefn Extension char* choose_temp_base (void)
@@ -286,7 +296,7 @@ value 1). If @var{valu} is zero, zero is returned.
@end deftypefn
-@c filename_cmp.c:32
+@c filename_cmp.c:37
@deftypefn Extension int filename_cmp (const char *@var{s1}, const char *@var{s2})
Return zero if the two file names @var{s1} and @var{s2} are equivalent.
@@ -303,7 +313,7 @@ and backward slashes are equal.
@end deftypefn
-@c filename_cmp.c:178
+@c filename_cmp.c:183
@deftypefn Extension int filename_eq (const void *@var{s1}, const void *@var{s2})
Return non-zero if file names @var{s1} and @var{s2} are equivalent.
@@ -311,7 +321,7 @@ This function is for use with hashtab.c hash tables.
@end deftypefn
-@c filename_cmp.c:147
+@c filename_cmp.c:152
@deftypefn Extension hashval_t filename_hash (const void *@var{s})
Return the hash value for file name @var{s} that will be compared
@@ -320,7 +330,7 @@ This function is for use with hashtab.c hash tables.
@end deftypefn
-@c filename_cmp.c:89
+@c filename_cmp.c:94
@deftypefn Extension int filename_ncmp (const char *@var{s1}, const char *@var{s2}, size_t @var{n})
Return zero if the two file names @var{s1} and @var{s2} are equivalent