rust/src/librustc/session/search_paths.rs

74 lines
2.1 KiB
Rust
Raw Normal View History

// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::slice;
2015-01-28 13:34:18 +00:00
#[derive(Clone, Debug)]
pub struct SearchPaths {
paths: Vec<(PathKind, Path)>,
}
pub struct Iter<'a> {
kind: PathKind,
iter: slice::Iter<'a, (PathKind, Path)>,
}
2015-01-28 13:34:18 +00:00
#[derive(Eq, PartialEq, Clone, Copy, Debug)]
pub enum PathKind {
Native,
Crate,
Dependency,
rustc: Fix a leak in dependency= paths With the addition of separate search paths to the compiler, it was intended that applications such as Cargo could require a `--extern` flag per `extern crate` directive in the source. The system can currently be subverted, however, due to the `existing_match()` logic in the crate loader. When loading crates we first attempt to match an `extern crate` directive against all previously loaded crates to avoid reading metadata twice. This "hit the cache if possible" step was erroneously leaking crates across the search path boundaries, however. For example: extern crate b; extern crate a; If `b` depends on `a`, then it will load crate `a` when the `extern crate b` directive is being processed. When the compiler reaches `extern crate a` it will use the previously loaded version no matter what. If the compiler was not invoked with `-L crate=path/to/a`, it will still succeed. This behavior is allowing `extern crate` declarations in Cargo without a corresponding declaration in the manifest of a dependency, which is considered a bug. This commit fixes this problem by keeping track of the origin search path for a crate. Crates loaded from the dependency search path are not candidates for crates which are loaded from the crate search path. As a result of this fix, this is a likely a breaking change for a number of Cargo packages. If the compiler starts informing that a crate can no longer be found, it likely means that the dependency was forgotten in your Cargo.toml. [breaking-change]
2015-01-06 16:46:07 +00:00
ExternFlag,
All,
}
impl SearchPaths {
pub fn new() -> SearchPaths {
SearchPaths { paths: Vec::new() }
}
pub fn add_path(&mut self, path: &str) {
let (kind, path) = if path.starts_with("native=") {
2015-01-18 00:15:52 +00:00
(PathKind::Native, &path["native=".len()..])
} else if path.starts_with("crate=") {
2015-01-18 00:15:52 +00:00
(PathKind::Crate, &path["crate=".len()..])
} else if path.starts_with("dependency=") {
2015-01-18 00:15:52 +00:00
(PathKind::Dependency, &path["dependency=".len()..])
} else if path.starts_with("all=") {
2015-01-18 00:15:52 +00:00
(PathKind::All, &path["all=".len()..])
} else {
(PathKind::All, path)
};
self.paths.push((kind, Path::new(path)));
}
pub fn iter(&self, kind: PathKind) -> Iter {
Iter { kind: kind, iter: self.paths.iter() }
}
}
2015-01-02 04:26:38 +00:00
impl<'a> Iterator for Iter<'a> {
rustc: Fix a leak in dependency= paths With the addition of separate search paths to the compiler, it was intended that applications such as Cargo could require a `--extern` flag per `extern crate` directive in the source. The system can currently be subverted, however, due to the `existing_match()` logic in the crate loader. When loading crates we first attempt to match an `extern crate` directive against all previously loaded crates to avoid reading metadata twice. This "hit the cache if possible" step was erroneously leaking crates across the search path boundaries, however. For example: extern crate b; extern crate a; If `b` depends on `a`, then it will load crate `a` when the `extern crate b` directive is being processed. When the compiler reaches `extern crate a` it will use the previously loaded version no matter what. If the compiler was not invoked with `-L crate=path/to/a`, it will still succeed. This behavior is allowing `extern crate` declarations in Cargo without a corresponding declaration in the manifest of a dependency, which is considered a bug. This commit fixes this problem by keeping track of the origin search path for a crate. Crates loaded from the dependency search path are not candidates for crates which are loaded from the crate search path. As a result of this fix, this is a likely a breaking change for a number of Cargo packages. If the compiler starts informing that a crate can no longer be found, it likely means that the dependency was forgotten in your Cargo.toml. [breaking-change]
2015-01-06 16:46:07 +00:00
type Item = (&'a Path, PathKind);
2015-01-02 04:26:38 +00:00
rustc: Fix a leak in dependency= paths With the addition of separate search paths to the compiler, it was intended that applications such as Cargo could require a `--extern` flag per `extern crate` directive in the source. The system can currently be subverted, however, due to the `existing_match()` logic in the crate loader. When loading crates we first attempt to match an `extern crate` directive against all previously loaded crates to avoid reading metadata twice. This "hit the cache if possible" step was erroneously leaking crates across the search path boundaries, however. For example: extern crate b; extern crate a; If `b` depends on `a`, then it will load crate `a` when the `extern crate b` directive is being processed. When the compiler reaches `extern crate a` it will use the previously loaded version no matter what. If the compiler was not invoked with `-L crate=path/to/a`, it will still succeed. This behavior is allowing `extern crate` declarations in Cargo without a corresponding declaration in the manifest of a dependency, which is considered a bug. This commit fixes this problem by keeping track of the origin search path for a crate. Crates loaded from the dependency search path are not candidates for crates which are loaded from the crate search path. As a result of this fix, this is a likely a breaking change for a number of Cargo packages. If the compiler starts informing that a crate can no longer be found, it likely means that the dependency was forgotten in your Cargo.toml. [breaking-change]
2015-01-06 16:46:07 +00:00
fn next(&mut self) -> Option<(&'a Path, PathKind)> {
loop {
match self.iter.next() {
Some(&(kind, ref p)) if self.kind == PathKind::All ||
kind == PathKind::All ||
rustc: Fix a leak in dependency= paths With the addition of separate search paths to the compiler, it was intended that applications such as Cargo could require a `--extern` flag per `extern crate` directive in the source. The system can currently be subverted, however, due to the `existing_match()` logic in the crate loader. When loading crates we first attempt to match an `extern crate` directive against all previously loaded crates to avoid reading metadata twice. This "hit the cache if possible" step was erroneously leaking crates across the search path boundaries, however. For example: extern crate b; extern crate a; If `b` depends on `a`, then it will load crate `a` when the `extern crate b` directive is being processed. When the compiler reaches `extern crate a` it will use the previously loaded version no matter what. If the compiler was not invoked with `-L crate=path/to/a`, it will still succeed. This behavior is allowing `extern crate` declarations in Cargo without a corresponding declaration in the manifest of a dependency, which is considered a bug. This commit fixes this problem by keeping track of the origin search path for a crate. Crates loaded from the dependency search path are not candidates for crates which are loaded from the crate search path. As a result of this fix, this is a likely a breaking change for a number of Cargo packages. If the compiler starts informing that a crate can no longer be found, it likely means that the dependency was forgotten in your Cargo.toml. [breaking-change]
2015-01-06 16:46:07 +00:00
kind == self.kind => {
return Some((p, kind))
}
Some(..) => {}
None => return None,
}
}
}
}