about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2017-12-22 02:50:49 +0800
committerGitHub <noreply@github.com>2017-12-22 02:50:49 +0800
commit0ee069c70a20da4bebbe630d316481bfffa7ab42 (patch)
tree07ed5dbc4c4ce10195b8375cfa1f9adf20fe56c3
parentd4981e9742d085eed3953f2ae71c01b7d66d22e6 (diff)
parent3a29f2878f33cadb0f63094e574bad222d63aef3 (diff)
downloadrust-0ee069c70a20da4bebbe630d316481bfffa7ab42.tar.gz
rust-0ee069c70a20da4bebbe630d316481bfffa7ab42.zip
Rollup merge of #46814 - varkor:contrib-7, r=alexcrichton
Prevent rustc overwriting input files

If rustc is invoked on a file that would be overwritten by the
compilation, the compilation now fails, to avoid accidental loss. This
resolves #13019. Kudos to @estebank, whose patch I finished off.
-rw-r--r--src/librustc/session/config.rs25
-rw-r--r--src/librustc_driver/driver.rs15
-rw-r--r--src/librustc_driver/lib.rs3
-rw-r--r--src/librustdoc/test.rs2
-rw-r--r--src/test/run-make/issue-19371/foo.rs2
-rw-r--r--src/test/run-make/output-filename-overwrites-input/Makefile10
-rw-r--r--src/test/run-make/output-filename-overwrites-input/foo.rs11
-rw-r--r--src/test/run-make/weird-output-filenames/Makefile4
8 files changed, 67 insertions, 5 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 6e0372f009e..7e80139b791 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 9e5de8d54e9..a288ff6316f 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<PathBuf>,
                      input: &Input,
                      outdir: &Option<PathBuf>,
                      output: &Option<PathBuf>,
@@ -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 29d3d31e451..60857505c7a 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 0326bd090e3..8e861f10dd8 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<String>,
     }
 
     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 cfe8048638a..f0ab1d5dc0f 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 00000000000..0554627d677
--- /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 00000000000..046d27a9f0f
--- /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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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 a5543e3b2c4..f161fe9f8e8 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 \