Skip to content

Commit 4dbef01

Browse files
committed
rustc: Check that the output file is writeable before linking
This is because on Linux, the linker will silently overwrite a read-only file.
1 parent 1cf029c commit 4dbef01

File tree

4 files changed

+45
-26
lines changed

4 files changed

+45
-26
lines changed

src/librustc/back/link.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,16 @@ pub fn link_binary(sess: Session,
959959
}
960960
}
961961

962+
fn is_writeable(p: &Path) -> bool {
963+
use std::libc::consts::os::posix88::S_IWUSR;
964+
965+
!os::path_exists(p) ||
966+
(match p.get_mode() {
967+
None => false,
968+
Some(m) => m & S_IWUSR as uint == S_IWUSR as uint
969+
})
970+
}
971+
962972
pub fn link_args(sess: Session,
963973
obj_filename: &Path,
964974
out_filename: &Path,
@@ -982,6 +992,21 @@ pub fn link_args(sess: Session,
982992
out_filename.clone()
983993
};
984994

995+
// Make sure the output and obj_filename are both writeable.
996+
// Mac, FreeBSD, and Windows system linkers check this already --
997+
// however, the Linux linker will happily overwrite a read-only file.
998+
// We should be consistent.
999+
let obj_is_writeable = is_writeable(obj_filename);
1000+
let out_is_writeable = is_writeable(&output);
1001+
if !out_is_writeable {
1002+
sess.fatal(format!("Output file {} is not writeable -- check its permissions.",
1003+
output.display()));
1004+
}
1005+
else if !obj_is_writeable {
1006+
sess.fatal(format!("Object file {} is not writeable -- check its permissions.",
1007+
obj_filename.display()));
1008+
}
1009+
9851010
// The default library location, we need this to find the runtime.
9861011
// The location of crates will be determined as needed.
9871012
// FIXME (#9639): This needs to handle non-utf8 paths

src/librustpkg/rustpkg.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ impl CtxMethods for BuildContext {
556556
debug2!("In declare inputs for {}", id.to_str());
557557
for cs in to_do.iter() {
558558
for c in cs.iter() {
559-
let path = pkg_src.start_dir.join(&c.file).normalize();
559+
let path = pkg_src.start_dir.join(&c.file);
560560
debug2!("Recording input: {}", path.display());
561561
// FIXME (#9639): This needs to handle non-utf8 paths
562562
inputs.push((~"file", path.as_str().unwrap().to_owned()));
@@ -623,19 +623,19 @@ impl CtxMethods for BuildContext {
623623
// Declare all the *inputs* to the declared input too, as inputs
624624
for executable in subex.iter() {
625625
exe_thing.discover_input("binary",
626-
executable.to_str(),
626+
executable.as_str().unwrap().to_owned(),
627627
workcache_support::digest_only_date(executable));
628628
}
629629
for library in sublib.iter() {
630630
exe_thing.discover_input("binary",
631-
library.to_str(),
631+
library.as_str().unwrap().to_owned(),
632632
workcache_support::digest_only_date(library));
633633
}
634634

635635
for transitive_dependency in sub_build_inputs.iter() {
636636
exe_thing.discover_input(
637637
"file",
638-
transitive_dependency.to_str(),
638+
transitive_dependency.as_str().unwrap().to_owned(),
639639
workcache_support::digest_file_with_date(transitive_dependency));
640640
}
641641

src/librustpkg/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ fn touch_source_file(workspace: &Path, pkgid: &PkgId) {
516516
// should be able to do this w/o a process
517517
// FIXME (#9639): This needs to handle non-utf8 paths
518518
// n.b. Bumps time up by 2 seconds to get around granularity issues
519-
if run::process_output("touch", [~"-A", ~"02", p.to_str()]).status != 0 {
519+
if run::process_output("touch", [~"-A", ~"02", p.as_str().unwrap().to_owned()]).status != 0 {
520520
let _ = cond.raise((pkg_src_dir.clone(), ~"Bad path"));
521521
}
522522
}

src/librustpkg/util.rs

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,8 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
441441
// Now we know that this crate has a discovered dependency on
442442
// installed_path
443443
// FIXME (#9639): This needs to handle non-utf8 paths
444-
add_dep(self.deps, self.parent_crate.to_str(),
445-
(~"binary", installed_path.to_str()));
444+
add_dep(self.deps, self.parent_crate.as_str().unwrap().to_owned(),
445+
(~"binary", installed_path.as_str().unwrap().to_owned()));
446446
self.exec.discover_input("binary",
447447
installed_path.as_str().unwrap(),
448448
digest_only_date(installed_path));
@@ -492,6 +492,10 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
492492
self.exec.discover_input("binary",
493493
dep.as_str().unwrap(),
494494
digest_only_date(dep));
495+
add_dep(self.deps,
496+
self.parent_crate.as_str().unwrap().to_owned(),
497+
(~"binary", dep.as_str().unwrap().to_owned()));
498+
495499
// Also, add an additional search path
496500
let dep_dir = dep.dir_path();
497501
debug2!("Installed {} into {}", dep.display(), dep_dir.display());
@@ -502,41 +506,31 @@ impl<'self> Visitor<()> for ViewItemVisitor<'self> {
502506
lib_name, outputs_disc.len(), inputs_disc.len());
503507
// It must have installed *something*...
504508
assert!(!outputs_disc.is_empty());
505-
let target_workspace = outputs_disc[0].pop();
506-
for dep in outputs_disc.iter() {
507-
debug2!("Discovering a binary input: {}", dep.to_str());
508-
self.exec.discover_input("binary", dep.to_str(),
509-
digest_only_date(dep));
510-
add_dep(self.deps,
511-
self.parent_crate.to_str(),
512-
(~"binary", dep.to_str()));
513-
}
509+
let mut target_workspace = outputs_disc[0].clone();
510+
target_workspace.pop();
514511
for &(ref what, ref dep) in inputs_disc.iter() {
515512
if *what == ~"file" {
516513
add_dep(self.deps,
517-
self.parent_crate.to_str(),
518-
(~"file", dep.to_str()));
519-
514+
self.parent_crate.as_str().unwrap().to_owned(),
515+
(~"file", dep.clone()));
520516
self.exec.discover_input(*what,
521517
*dep,
522518
digest_file_with_date(
523519
&Path::new(dep.as_slice())));
524-
}
525-
else if *what == ~"binary" {
520+
} else if *what == ~"binary" {
526521
add_dep(self.deps,
527-
self.parent_crate.to_str(),
528-
(~"binary", dep.to_str()));
522+
self.parent_crate.as_str().unwrap().to_owned(),
523+
(~"binary", dep.clone()));
529524
self.exec.discover_input(*what,
530525
*dep,
531526
digest_only_date(
532527
&Path::new(dep.as_slice())));
533-
}
534-
else {
528+
} else {
535529
fail2!("Bad kind: {}", *what);
536530
}
537531
// Also, add an additional search path
538532
debug2!("Installed {} into {}",
539-
lib_name, target_workspace.to_str());
533+
lib_name, target_workspace.as_str().unwrap().to_owned());
540534
(self.save)(target_workspace.clone());
541535
}
542536
}

0 commit comments

Comments
 (0)