diff options
| author | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-07-02 00:36:33 +0300 |
|---|---|---|
| committer | Ariel Ben-Yehuda <ariel.byd@gmail.com> | 2016-07-02 14:53:50 +0300 |
| commit | 7be84879c6f1632883c87d60e4a558ee6dc96cda (patch) | |
| tree | 1d6690453cb59758089ed15061a5284016cdec66 | |
| parent | a72ac96d6cd9c7de3478b5e7c003ee712ca1b932 (diff) | |
| download | rust-7be84879c6f1632883c87d60e4a558ee6dc96cda.tar.gz rust-7be84879c6f1632883c87d60e4a558ee6dc96cda.zip | |
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
| -rw-r--r-- | src/librustc_metadata/common.rs | 4 | ||||
| -rw-r--r-- | src/librustc_metadata/creader.rs | 23 | ||||
| -rw-r--r-- | src/librustc_metadata/csearch.rs | 3 | ||||
| -rw-r--r-- | src/librustc_metadata/encoder.rs | 4 | ||||
| -rw-r--r-- | src/librustc_metadata/loader.rs | 35 |
5 files changed, 38 insertions, 31 deletions
diff --git a/src/librustc_metadata/common.rs b/src/librustc_metadata/common.rs index 2b972af07ff..b3ca399132b 100644 --- a/src/librustc_metadata/common.rs +++ b/src/librustc_metadata/common.rs @@ -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]; diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index ad6bb2dbac2..90f4ebc1a1e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -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}; @@ -234,25 +233,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) { @@ -294,7 +274,6 @@ impl<'a> CrateReader<'a> { explicitly_linked: bool) -> (ast::CrateNum, Rc<cstore::crate_metadata>, 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 @@ -379,6 +358,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) { @@ -506,6 +486,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(|| { diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index b87b5492f04..d1f6f7e1ff2 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -9,6 +9,7 @@ // except according to those terms. use cstore; +use common; use decoder; use encoder; use loader; @@ -587,7 +588,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 diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 928601095b0..1d1a29cb376 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1851,10 +1851,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()); diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index a5b1c3d301b..0886a2fa9fc 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -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()))); |
