Skip to content

Commit

Permalink
make the metadata lock more robust and bump the metadata encoding ver…
Browse files Browse the repository at this point in the history
…sion

check the metadata lock when loading rather than afterwards

Fixes #33733
Fixes #33015
  • Loading branch information
arielb1 committed Jul 2, 2016
1 parent c333ebb commit 0b36fff
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 31 deletions.
4 changes: 4 additions & 0 deletions src/librustc_metadata/common.rs
Expand Up @@ -252,3 +252,7 @@ pub fn rustc_version() -> String {
}

pub const tag_panic_strategy: usize = 0x114;

// NB: increment this if you change the format of metadata such that
// rustc_version can't be found.
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2];
23 changes: 2 additions & 21 deletions src/librustc_metadata/creader.rs
Expand Up @@ -12,7 +12,6 @@

//! Validates all used crates and extern libraries and loads their metadata

use common::rustc_version;
use cstore::{self, CStore, CrateSource, MetadataBlob};
use decoder;
use loader::{self, CratePaths};
Expand Down Expand Up @@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
return ret;
}

fn verify_rustc_version(&self,
name: &str,
span: Span,
metadata: &MetadataBlob) {
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
if crate_rustc_version != Some(rustc_version()) {
let mut err = struct_span_fatal!(self.sess, span, E0514,
"the crate `{}` has been compiled with {}, which is \
incompatible with this version of rustc",
name,
crate_rustc_version
.as_ref().map(|s| &**s)
.unwrap_or("an old version of rustc"));
err.help("consider removing the compiled binaries and recompiling \
with your current version of rustc");
err.emit();
}
}

fn verify_no_symbol_conflicts(&self,
span: Span,
metadata: &MetadataBlob) {
Expand Down Expand Up @@ -296,7 +276,6 @@ impl<'a> CrateReader<'a> {
explicitly_linked: bool)
-> (ast::CrateNum, Rc<cstore::CrateMetadata>,
cstore::CrateSource) {
self.verify_rustc_version(name, span, &lib.metadata);
self.verify_no_symbol_conflicts(span, &lib.metadata);

// Claim this crate number and cache it
Expand Down Expand Up @@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
rejected_via_kind: vec!(),
rejected_via_version: vec!(),
should_match_name: true,
};
match self.load(&mut load_ctxt) {
Expand Down Expand Up @@ -517,6 +497,7 @@ impl<'a> CrateReader<'a> {
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
rejected_via_kind: vec!(),
rejected_via_version: vec!(),
should_match_name: true,
};
let library = self.load(&mut load_ctxt).or_else(|| {
Expand Down
3 changes: 2 additions & 1 deletion src/librustc_metadata/csearch.rs
Expand Up @@ -9,6 +9,7 @@
// except according to those terms.

use cstore;
use common;
use decoder;
use encoder;
use loader;
Expand Down Expand Up @@ -588,7 +589,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {

fn metadata_encoding_version(&self) -> &[u8]
{
encoder::metadata_encoding_version
common::metadata_encoding_version
}

/// Returns a map from a sufficiently visible external item (i.e. an external item that is
Expand Down
4 changes: 0 additions & 4 deletions src/librustc_metadata/encoder.rs
Expand Up @@ -1799,10 +1799,6 @@ fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) {
}
}

// NB: Increment this as you change the metadata encoding version.
#[allow(non_upper_case_globals)]
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];

pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
let mut wr = Cursor::new(Vec::new());

Expand Down
35 changes: 30 additions & 5 deletions src/librustc_metadata/loader.rs
Expand Up @@ -213,8 +213,8 @@
//! metadata::loader or metadata::creader for all the juicy details!

use cstore::{MetadataBlob, MetadataVec, MetadataArchive};
use common::{metadata_encoding_version, rustc_version};
use decoder;
use encoder;

use rustc::hir::svh::Svh;
use rustc::session::Session;
Expand Down Expand Up @@ -260,6 +260,7 @@ pub struct Context<'a> {
pub rejected_via_hash: Vec<CrateMismatch>,
pub rejected_via_triple: Vec<CrateMismatch>,
pub rejected_via_kind: Vec<CrateMismatch>,
pub rejected_via_version: Vec<CrateMismatch>,
pub should_match_name: bool,
}

Expand Down Expand Up @@ -336,6 +337,10 @@ impl<'a> Context<'a> {
struct_span_err!(self.sess, self.span, E0462,
"found staticlib `{}` instead of rlib or dylib{}",
self.ident, add)
} else if !self.rejected_via_version.is_empty() {
struct_span_err!(self.sess, self.span, E0514,
"found crate `{}` compiled by an incompatible version of rustc{}",
self.ident, add)
} else {
struct_span_err!(self.sess, self.span, E0463,
"can't find crate for `{}`{}",
Expand All @@ -350,7 +355,7 @@ impl<'a> Context<'a> {
}
}
if !self.rejected_via_hash.is_empty() {
err.note("perhaps this crate needs to be recompiled?");
err.note("perhaps that crate needs to be recompiled?");
let mismatches = self.rejected_via_hash.iter();
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
err.note(&format!("crate `{}` path #{}: {}",
Expand All @@ -367,13 +372,22 @@ impl<'a> Context<'a> {
}
}
if !self.rejected_via_kind.is_empty() {
err.help("please recompile this crate using --crate-type lib");
err.help("please recompile that crate using --crate-type lib");
let mismatches = self.rejected_via_kind.iter();
for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
err.note(&format!("crate `{}` path #{}: {}",
self.ident, i+1, path.display()));
}
}
if !self.rejected_via_version.is_empty() {
err.help(&format!("please recompile that crate using this compiler ({})",
rustc_version()));
let mismatches = self.rejected_via_version.iter();
for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() {
err.note(&format!("crate `{}` path #{}: {} compiled by {:?}",
self.ident, i+1, path.display(), got));
}
}

err.emit();
self.sess.abort_if_errors();
Expand Down Expand Up @@ -591,6 +605,17 @@ impl<'a> Context<'a> {
}

fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option<Svh> {
let crate_rustc_version = decoder::crate_rustc_version(crate_data);
if crate_rustc_version != Some(rustc_version()) {
let message = crate_rustc_version.unwrap_or(format!("an unknown compiler"));
info!("Rejecting via version: expected {} got {}", rustc_version(), message);
self.rejected_via_version.push(CrateMismatch {
path: libpath.to_path_buf(),
got: message
});
return None;
}

if self.should_match_name {
match decoder::maybe_get_crate_name(crate_data) {
Some(ref name) if self.crate_name == *name => {}
Expand Down Expand Up @@ -801,12 +826,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
let cvbuf: *const u8 = cbuf as *const u8;
let vlen = encoder::metadata_encoding_version.len();
let vlen = metadata_encoding_version.len();
debug!("checking {} bytes of metadata-version stamp",
vlen);
let minsz = cmp::min(vlen, csz);
let buf0 = slice::from_raw_parts(cvbuf, minsz);
let version_ok = buf0 == encoder::metadata_encoding_version;
let version_ok = buf0 == metadata_encoding_version;
if !version_ok {
return Err((format!("incompatible metadata version found: '{}'",
filename.display())));
Expand Down

0 comments on commit 0b36fff

Please sign in to comment.