Skip to content

Commit 0ee069c

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#13019. Kudos to @estebank, whose patch I finished off.
2 parents d4981e9 + 3a29f28 commit 0ee069c

File tree

8 files changed

+67
-5
lines changed

8 files changed

+67
-5
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/driver.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use profile;
7171

7272
pub fn compile_input(sess: &Session,
7373
cstore: &CStore,
74+
input_path: &Option<PathBuf>,
7475
input: &Input,
7576
outdir: &Option<PathBuf>,
7677
output: &Option<PathBuf>,
@@ -142,6 +143,20 @@ pub fn compile_input(sess: &Session,
142143
};
143144

144145
let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
146+
147+
// Ensure the source file isn't accidentally overwritten during compilation.
148+
match *input_path {
149+
Some(ref input_path) => {
150+
if outputs.contains_path(input_path) && sess.opts.will_create_output_file() {
151+
sess.err(&format!(
152+
"the input file \"{}\" would be overwritten by the generated executable",
153+
input_path.display()));
154+
return Err(CompileIncomplete::Stopped);
155+
}
156+
},
157+
None => {}
158+
}
159+
145160
let crate_name =
146161
::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
147162
let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {

src/librustc_driver/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ 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));
@@ -252,6 +252,7 @@ pub fn run_compiler<'a>(args: &[String],
252252
let control = callbacks.build_controller(&sess, &matches);
253253
(driver::compile_input(&sess,
254254
&cstore,
255+
&input_file_path,
255256
&input,
256257
&odir,
257258
&ofile,

src/librustdoc/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, cfgs: Vec<String>,
263263
}
264264

265265
let res = panic::catch_unwind(AssertUnwindSafe(|| {
266-
driver::compile_input(&sess, &cstore, &input, &out, &None, None, &control)
266+
driver::compile_input(&sess, &cstore, &None, &input, &out, &None, None, &control)
267267
}));
268268

269269
let compile_result = match res {

src/test/run-make/issue-19371/foo.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,5 @@ fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
7171
let (sess, cstore) = basic_sess(sysroot);
7272
let control = CompileController::basic();
7373
let input = Input::Str { name: FileName::Anon, input: code };
74-
let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
74+
let _ = compile_input(&sess, &cstore, &None, &input, &None, &Some(output), None, &control);
7575
}
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)