Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not rely on file extensions after path canonicalization. #32828

Merged
merged 2 commits into from
Apr 13, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 29 additions & 11 deletions src/librustc_metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ use rustc_back::target::Target;

use std::cmp;
use std::collections::HashMap;
use std::fmt;
use std::fs;
use std::io::prelude::*;
use std::io;
Expand Down Expand Up @@ -283,6 +284,21 @@ pub struct CratePaths {

pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";

#[derive(Copy, Clone, PartialEq)]
enum CrateFlavor {
Rlib,
Dylib
}

impl fmt::Display for CrateFlavor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
CrateFlavor::Rlib => "rlib",
CrateFlavor::Dylib => "dylib"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a comma at the end of this line please?

})
}
}

impl CratePaths {
fn paths(&self) -> Vec<PathBuf> {
match (&self.dylib, &self.rlib) {
Expand Down Expand Up @@ -457,8 +473,8 @@ impl<'a> Context<'a> {
let mut libraries = Vec::new();
for (_hash, (rlibs, dylibs)) in candidates {
let mut metadata = None;
let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut metadata);
let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut metadata);
match metadata {
Some(metadata) => {
libraries.push(Library {
Expand Down Expand Up @@ -515,7 +531,7 @@ impl<'a> Context<'a> {
// read the metadata from it if `*slot` is `None`. If the metadata couldn't
// be read, it is assumed that the file isn't a valid rust library (no
// errors are emitted).
fn extract_one(&mut self, m: HashMap<PathBuf, PathKind>, flavor: &str,
fn extract_one(&mut self, m: HashMap<PathBuf, PathKind>, flavor: CrateFlavor,
slot: &mut Option<MetadataBlob>) -> Option<(PathBuf, PathKind)> {
let mut ret = None::<(PathBuf, PathKind)>;
let mut error = 0;
Expand All @@ -535,7 +551,7 @@ impl<'a> Context<'a> {
let mut err: Option<DiagnosticBuilder> = None;
for (lib, kind) in m {
info!("{} reading metadata from: {}", flavor, lib.display());
let metadata = match get_metadata_section(self.target, &lib) {
let metadata = match get_metadata_section(self.target, flavor, &lib) {
Ok(blob) => {
if self.crate_matches(blob.as_slice(), &lib) {
blob
Expand Down Expand Up @@ -702,8 +718,8 @@ impl<'a> Context<'a> {

// Extract the rlib/dylib pair.
let mut metadata = None;
let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut metadata);
let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut metadata);

if rlib.is_none() && dylib.is_none() { return None }
match metadata {
Expand Down Expand Up @@ -746,21 +762,21 @@ impl ArchiveMetadata {
}

// Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(target: &Target, filename: &Path)
fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path)
-> Result<MetadataBlob, String> {
let start = Instant::now();
let ret = get_metadata_section_imp(target, filename);
let ret = get_metadata_section_imp(target, flavor, filename);
info!("reading {:?} => {:?}", filename.file_name().unwrap(),
start.elapsed());
return ret
}

fn get_metadata_section_imp(target: &Target, filename: &Path)
fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Path)
-> Result<MetadataBlob, String> {
if !filename.exists() {
return Err(format!("no such file: '{}'", filename.display()));
}
if filename.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
if flavor == CrateFlavor::Rlib {
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
// internally to read the file. We also avoid even using a memcpy by
// just keeping the archive along while the metadata is in use.
Expand Down Expand Up @@ -864,7 +880,9 @@ pub fn read_meta_section_name(target: &Target) -> &'static str {
// A diagnostic function for dumping crate metadata to an output stream
pub fn list_file_metadata(target: &Target, path: &Path,
out: &mut io::Write) -> io::Result<()> {
match get_metadata_section(target, path) {
let filename = path.file_name().unwrap().to_str().unwrap();
let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib } else { CrateFlavor::Dylib };
match get_metadata_section(target, flavor, path) {
Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
Err(msg) => {
write!(out, "{}\n", msg)
Expand Down