Skip to content

Commit 9745d4e

Browse files
committed
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 ```
1 parent c87ba3f commit 9745d4e

File tree

5 files changed

+73
-3
lines changed

5 files changed

+73
-3
lines changed

src/librustc/session/config.rs

+33
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,33 @@ impl OutputFilenames {
399399
pub fn filestem(&self) -> String {
400400
format!("{}{}", self.out_filestem, self.extra)
401401
}
402+
403+
pub fn is_path_used(&self, path: &PathBuf) -> bool {
404+
fn eq(p1: &PathBuf, p2: &PathBuf) -> bool {
405+
let p1 = match p1.canonicalize() {
406+
Ok(p) => Some(p),
407+
_ => None,
408+
};
409+
let p2 = match p2.canonicalize() {
410+
Ok(p) => Some(p),
411+
_ => None,
412+
};
413+
p1 == p2
414+
}
415+
416+
match self.single_output_file {
417+
Some(ref p) => eq(&p, path),
418+
None => {
419+
for k in self.outputs.keys() {
420+
let opath: PathBuf = self.path(k.to_owned());
421+
if eq(&opath, path) {
422+
return true;
423+
}
424+
}
425+
false
426+
}
427+
}
428+
}
402429
}
403430

404431
pub fn host_triple() -> &'static str {
@@ -455,6 +482,12 @@ impl Options {
455482
self.incremental.is_none() ||
456483
self.cg.codegen_units == 1
457484
}
485+
486+
/// True if there will be an output file generated
487+
pub fn will_create_output_file(&self) -> bool {
488+
!self.debugging_opts.parse_only || // we will generate an output file and
489+
self.debugging_opts.ls // we're not just querying an existing file
490+
}
458491
}
459492

460493
// The type of entry function, so

src/librustc_driver/lib.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,26 @@ pub fn run_compiler_with_file_loader<'a, L>(args: &[String],
210210
let codemap = Rc::new(CodeMap::with_file_loader(loader));
211211
let sess = session::build_session_with_codemap(sopts,
212212
&dep_graph,
213-
input_file_path,
213+
input_file_path.clone(),
214214
descriptions,
215215
cstore.clone(),
216216
codemap);
217+
218+
match input_file_path {
219+
Some(ifile) => {
220+
// This isn't used later in the compilation process, it's only used to check for
221+
// overwrites of the source file.
222+
if driver::build_output_filenames(&input, &odir, &ofile, &[], &sess)
223+
.is_path_used(&ifile) && !sess.opts.will_create_output_file() {
224+
sess.err(&format!(
225+
"the input file \"{}\" would be overwritten by the generated executable",
226+
ifile.display()));
227+
return (Err(1), Some(sess));
228+
}
229+
},
230+
None => (),
231+
}
232+
217233
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
218234
let mut cfg = config::build_configuration(&sess, cfg);
219235
target_features::add_configuration(&mut cfg, &sess);
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+
| grep "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+
| grep "the input file \".*foo.rs\" would be overwritten by the generated executable"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2014 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

+2-2
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
| grep "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
| grep "invalid character.*in crate name:"
1313
cp foo.rs $(TMPDIR)/-foo.rs
1414
$(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \

0 commit comments

Comments
 (0)