From 9745d4e5d0e1b1e34b26da95f81fcd76f82466ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 1 Jun 2016 01:37:44 -0700 Subject: [PATCH] Do not overwrite input file if it has no extension Check wether the source file has the same path as the executable to be generated and fail early if it would overwrite the source file with the executable. ```bash % echo 'fn main(){}' > file && ./rustc file error: the input file "file" would be overwritten by the generated executable error: aborting due to previous error % echo 'fn main(){}' > file.rs && ./rustc file.rs -o file.rs error: the input file "file.rs" would be overwritten by the generated executable error: aborting due to previous error ``` --- src/librustc/session/config.rs | 33 +++++++++++++++++++ src/librustc_driver/lib.rs | 18 +++++++++- .../output-filename-overwrites-input/Makefile | 10 ++++++ .../output-filename-overwrites-input/foo.rs | 11 +++++++ .../run-make/weird-output-filenames/Makefile | 4 +-- 5 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make/output-filename-overwrites-input/Makefile create mode 100644 src/test/run-make/output-filename-overwrites-input/foo.rs diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2009e18f6ee20..9b400de2e89e6 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -399,6 +399,33 @@ impl OutputFilenames { pub fn filestem(&self) -> String { format!("{}{}", self.out_filestem, self.extra) } + + pub fn is_path_used(&self, path: &PathBuf) -> bool { + fn eq(p1: &PathBuf, p2: &PathBuf) -> bool { + let p1 = match p1.canonicalize() { + Ok(p) => Some(p), + _ => None, + }; + let p2 = match p2.canonicalize() { + Ok(p) => Some(p), + _ => None, + }; + p1 == p2 + } + + match self.single_output_file { + Some(ref p) => eq(&p, path), + None => { + for k in self.outputs.keys() { + let opath: PathBuf = self.path(k.to_owned()); + if eq(&opath, path) { + return true; + } + } + false + } + } + } } pub fn host_triple() -> &'static str { @@ -455,6 +482,12 @@ impl Options { self.incremental.is_none() || self.cg.codegen_units == 1 } + + /// True if there will be an output file generated + pub fn will_create_output_file(&self) -> bool { + !self.debugging_opts.parse_only || // we will generate an output file and + self.debugging_opts.ls // we're not just querying an existing file + } } // The type of entry function, so diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index fbd48fc42c92d..92779da5b9b3e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -210,10 +210,26 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String], let codemap = Rc::new(CodeMap::with_file_loader(loader)); let sess = session::build_session_with_codemap(sopts, &dep_graph, - input_file_path, + input_file_path.clone(), descriptions, cstore.clone(), codemap); + + match input_file_path { + Some(ifile) => { + // This isn't used later in the compilation process, it's only used to check for + // overwrites of the source file. + if driver::build_output_filenames(&input, &odir, &ofile, &[], &sess) + .is_path_used(&ifile) && !sess.opts.will_create_output_file() { + sess.err(&format!( + "the input file \"{}\" would be overwritten by the generated executable", + ifile.display())); + return (Err(1), Some(sess)); + } + }, + None => (), + } + rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg); target_features::add_configuration(&mut cfg, &sess); 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..f7f517fb4f8d9 --- /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 \ + | grep "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 \ + | grep "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..8ae3d072362ed --- /dev/null +++ b/src/test/run-make/output-filename-overwrites-input/foo.rs @@ -0,0 +1,11 @@ +// Copyright 2014 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 8b69c68279dca..ccc55cbfedda9 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 \ | grep "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 \ | grep "invalid character.*in crate name:" cp foo.rs $(TMPDIR)/-foo.rs $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \