make the metadata lock more robust and bump the metadata encoding version
check the metadata lock when loading rather than afterwards Fixes #33733 Fixes #33015
This commit is contained in:
parent
c333ebbe63
commit
0b36fff4d7
5 changed files with 38 additions and 31 deletions
|
@ -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];
|
||||
|
|
|
@ -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};
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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(|| {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use cstore;
|
||||
use common;
|
||||
use decoder;
|
||||
use encoder;
|
||||
use loader;
|
||||
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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 `{}`{}",
|
||||
|
@ -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 #{}: {}",
|
||||
|
@ -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();
|
||||
|
@ -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 => {}
|
||||
|
@ -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())));
|
||||
|
|
Loading…
Add table
Reference in a new issue