diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 009fb61984638..ef05c9b077942 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -528,6 +528,25 @@ impl OutputFilenames { pub fn filestem(&self) -> String { format!("{}{}", self.out_filestem, self.extra) } + + pub fn contains_path(&self, input_path: &PathBuf) -> bool { + let input_path = input_path.canonicalize().ok(); + if input_path.is_none() { + return false + } + match self.single_output_file { + Some(ref output_path) => output_path.canonicalize().ok() == input_path, + None => { + for k in self.outputs.keys() { + let output_path = self.path(k.to_owned()); + if output_path.canonicalize().ok() == input_path { + return true; + } + } + false + } + } + } } pub fn host_triple() -> &'static str { @@ -596,6 +615,12 @@ impl Options { ).map(|(src, dst)| (src.clone(), dst.clone())).collect() ) } + + /// True if there will be an output file generated + pub fn will_create_output_file(&self) -> bool { + !self.debugging_opts.parse_only && // The file is just being parsed + !self.debugging_opts.ls // The file is just being queried + } } // The type of entry function, so diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 9e5de8d54e9de..a288ff6316f83 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -71,6 +71,7 @@ use profile; pub fn compile_input(sess: &Session, cstore: &CStore, + input_path: &Option, input: &Input, outdir: &Option, output: &Option, @@ -142,6 +143,20 @@ pub fn compile_input(sess: &Session, }; let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess); + + // Ensure the source file isn't accidentally overwritten during compilation. + match *input_path { + Some(ref input_path) => { + if outputs.contains_path(input_path) && sess.opts.will_create_output_file() { + sess.err(&format!( + "the input file \"{}\" would be overwritten by the generated executable", + input_path.display())); + return Err(CompileIncomplete::Stopped); + } + }, + None => {} + } + let crate_name = ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input); let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 29d3d31e45155..60857505c7ac5 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -232,7 +232,7 @@ pub fn run_compiler<'a>(args: &[String], let loader = file_loader.unwrap_or(box RealFileLoader); let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping())); let mut sess = session::build_session_with_codemap( - sopts, input_file_path, descriptions, codemap, emitter_dest, + sopts, input_file_path.clone(), descriptions, codemap, emitter_dest, ); rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); @@ -252,6 +252,7 @@ pub fn run_compiler<'a>(args: &[String], let control = callbacks.build_controller(&sess, &matches); (driver::compile_input(&sess, &cstore, + &input_file_path, &input, &odir, &ofile, diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index abb902003706c..06d00dec62693 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -263,7 +263,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec, } let res = panic::catch_unwind(AssertUnwindSafe(|| { - driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control) + driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control) })); let compile_result = match res { diff --git a/src/test/run-make/issue-19371/foo.rs b/src/test/run-make/issue-19371/foo.rs index cfe8048638a86..f0ab1d5dc0fec 100644 --- a/src/test/run-make/issue-19371/foo.rs +++ b/src/test/run-make/issue-19371/foo.rs @@ -71,5 +71,5 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) { let (sess, cstore) = basic_sess(sysroot); let control = CompileController::basic(); let input = Input::Str { name: FileName::Anon, input: code }; - let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control); + let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control); } diff --git a/src/test/run-make/output-filename-overwrites-input/Makefile b/src/test/run-make/output-filename-overwrites-input/Makefile new file mode 100644 index 0000000000000..0554627d67753 --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + cp foo.rs $(TMPDIR)/foo + $(RUSTC) $(TMPDIR)/foo 2>&1 \ + | $(CGREP) -e "the input file \".*foo\" would be overwritten by the generated executable" + $(RUSTC) foo.rs 2>&1 && $(RUSTC) -Z ls $(TMPDIR)/foo 2>&1 + cp foo.rs $(TMPDIR)/foo.rs + $(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo.rs 2>&1 \ + | $(CGREP) -e "the input file \".*foo.rs\" would be overwritten by the generated executable" diff --git a/src/test/run-make/output-filename-overwrites-input/foo.rs b/src/test/run-make/output-filename-overwrites-input/foo.rs new file mode 100644 index 0000000000000..046d27a9f0fe5 --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/run-make/weird-output-filenames/Makefile b/src/test/run-make/weird-output-filenames/Makefile index a5543e3b2c4d0..f161fe9f8e8df 100644 --- a/src/test/run-make/weird-output-filenames/Makefile +++ b/src/test/run-make/weird-output-filenames/Makefile @@ -7,8 +7,8 @@ all: cp foo.rs $(TMPDIR)/.foo.bar $(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \ | $(CGREP) -e "invalid character.*in crate name:" - cp foo.rs $(TMPDIR)/+foo+bar - $(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \ + cp foo.rs $(TMPDIR)/+foo+bar.rs + $(RUSTC) $(TMPDIR)/+foo+bar.rs 2>&1 \ | $(CGREP) -e "invalid character.*in crate name:" cp foo.rs $(TMPDIR)/-foo.rs $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \