Skip to content

Commit c76cdce

Browse files
committed
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.
1 parent 53a6d14 commit c76cdce

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

src/librustc/session/config.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,25 @@ impl OutputFilenames {
528528
pub fn filestem(&self) -> String {
529529
format!("{}{}", self.out_filestem, self.extra)
530530
}
531+
532+
pub fn contains_path(&self, input_path: &PathBuf) -> bool {
533+
let input_path = input_path.canonicalize().ok();
534+
if input_path.is_none() {
535+
return false
536+
}
537+
match self.single_output_file {
538+
Some(ref output_path) => output_path.canonicalize().ok() == input_path,
539+
None => {
540+
for k in self.outputs.keys() {
541+
let output_path = self.path(k.to_owned());
542+
if output_path.canonicalize().ok() == input_path {
543+
return true;
544+
}
545+
}
546+
false
547+
}
548+
}
549+
}
531550
}
532551

533552
pub fn host_triple() -> &'static str {
@@ -596,6 +615,12 @@ impl Options {
596615
).map(|(src, dst)| (src.clone(), dst.clone())).collect()
597616
)
598617
}
618+
619+
/// True if there will be an output file generated
620+
pub fn will_create_output_file(&self) -> bool {
621+
!self.debugging_opts.parse_only && // The file is just being parsed
622+
!self.debugging_opts.ls // The file is just being queried
623+
}
599624
}
600625

601626
// The type of entry function, so

src/librustc_driver/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,11 +232,25 @@ pub fn run_compiler<'a>(args: &[String],
232232
let loader = file_loader.unwrap_or(box RealFileLoader);
233233
let codemap = Rc::new(CodeMap::with_file_loader(loader, sopts.file_path_mapping()));
234234
let mut sess = session::build_session_with_codemap(
235-
sopts, input_file_path, descriptions, codemap, emitter_dest,
235+
sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
236236
);
237237
rustc_trans::init(&sess);
238238
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
239239

240+
// Ensure the source file isn't accidentally overwritten during compilation.
241+
match input_file_path {
242+
Some(input_file_path) => {
243+
if driver::build_output_filenames(&input, &odir, &ofile, &[], &sess)
244+
.contains_path(&input_file_path) && sess.opts.will_create_output_file() {
245+
sess.err(&format!(
246+
"the input file \"{}\" would be overwritten by the generated executable",
247+
input_file_path.display()));
248+
return (Err(CompileIncomplete::Stopped), Some(sess));
249+
}
250+
},
251+
None => {}
252+
}
253+
240254
let mut cfg = config::build_configuration(&sess, cfg);
241255
target_features::add_configuration(&mut cfg, &sess);
242256
sess.parse_sess.config = cfg;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-include ../tools.mk
2+
3+
all:
4+
cp foo.rs $(TMPDIR)/foo
5+
$(RUSTC) $(TMPDIR)/foo 2>&1 \
6+
| $(CGREP) -e "the input file \".*foo\" would be overwritten by the generated executable"
7+
$(RUSTC) foo.rs 2>&1 && $(RUSTC) -Z ls $(TMPDIR)/foo 2>&1
8+
cp foo.rs $(TMPDIR)/foo.rs
9+
$(RUSTC) $(TMPDIR)/foo.rs -o $(TMPDIR)/foo.rs 2>&1 \
10+
| $(CGREP) -e "the input file \".*foo.rs\" would be overwritten by the generated executable"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn main() {}

src/test/run-make/weird-output-filenames/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ all:
77
cp foo.rs $(TMPDIR)/.foo.bar
88
$(RUSTC) $(TMPDIR)/.foo.bar 2>&1 \
99
| $(CGREP) -e "invalid character.*in crate name:"
10-
cp foo.rs $(TMPDIR)/+foo+bar
11-
$(RUSTC) $(TMPDIR)/+foo+bar 2>&1 \
10+
cp foo.rs $(TMPDIR)/+foo+bar.rs
11+
$(RUSTC) $(TMPDIR)/+foo+bar.rs 2>&1 \
1212
| $(CGREP) -e "invalid character.*in crate name:"
1313
cp foo.rs $(TMPDIR)/-foo.rs
1414
$(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \

0 commit comments

Comments
 (0)