Skip to content

Commit 7be8487

Browse files
committed
make the metadata lock more robust and bump the metadata encoding version
check the metadata lock when loading rather than afterwards Fixes rust-lang#33733 Fixes rust-lang#33015
1 parent a72ac96 commit 7be8487

File tree

5 files changed

+38
-31
lines changed

5 files changed

+38
-31
lines changed

src/librustc_metadata/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,7 @@ pub fn rustc_version() -> String {
252252
}
253253

254254
pub const tag_panic_strategy: usize = 0x114;
255+
256+
// NB: increment this if you change the format of metadata such that
257+
// rustc_version can't be found.
258+
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2];

src/librustc_metadata/creader.rs

+2-21
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
//! Validates all used crates and extern libraries and loads their metadata
1414
15-
use common::rustc_version;
1615
use cstore::{self, CStore, CrateSource, MetadataBlob};
1716
use decoder;
1817
use loader::{self, CratePaths};
@@ -234,25 +233,6 @@ impl<'a> CrateReader<'a> {
234233
return ret;
235234
}
236235

237-
fn verify_rustc_version(&self,
238-
name: &str,
239-
span: Span,
240-
metadata: &MetadataBlob) {
241-
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
242-
if crate_rustc_version != Some(rustc_version()) {
243-
let mut err = struct_span_fatal!(self.sess, span, E0514,
244-
"the crate `{}` has been compiled with {}, which is \
245-
incompatible with this version of rustc",
246-
name,
247-
crate_rustc_version
248-
.as_ref().map(|s| &**s)
249-
.unwrap_or("an old version of rustc"));
250-
err.help("consider removing the compiled binaries and recompiling \
251-
with your current version of rustc");
252-
err.emit();
253-
}
254-
}
255-
256236
fn verify_no_symbol_conflicts(&self,
257237
span: Span,
258238
metadata: &MetadataBlob) {
@@ -294,7 +274,6 @@ impl<'a> CrateReader<'a> {
294274
explicitly_linked: bool)
295275
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
296276
cstore::CrateSource) {
297-
self.verify_rustc_version(name, span, &lib.metadata);
298277
self.verify_no_symbol_conflicts(span, &lib.metadata);
299278

300279
// Claim this crate number and cache it
@@ -379,6 +358,7 @@ impl<'a> CrateReader<'a> {
379358
rejected_via_hash: vec!(),
380359
rejected_via_triple: vec!(),
381360
rejected_via_kind: vec!(),
361+
rejected_via_version: vec!(),
382362
should_match_name: true,
383363
};
384364
match self.load(&mut load_ctxt) {
@@ -506,6 +486,7 @@ impl<'a> CrateReader<'a> {
506486
rejected_via_hash: vec!(),
507487
rejected_via_triple: vec!(),
508488
rejected_via_kind: vec!(),
489+
rejected_via_version: vec!(),
509490
should_match_name: true,
510491
};
511492
let library = self.load(&mut load_ctxt).or_else(|| {

src/librustc_metadata/csearch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use cstore;
12+
use common;
1213
use decoder;
1314
use encoder;
1415
use loader;
@@ -587,7 +588,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
587588

588589
fn metadata_encoding_version(&self) -> &[u8]
589590
{
590-
encoder::metadata_encoding_version
591+
common::metadata_encoding_version
591592
}
592593

593594
/// Returns a map from a sufficiently visible external item (i.e. an external item that is

src/librustc_metadata/encoder.rs

-4
Original file line numberDiff line numberDiff line change
@@ -1851,10 +1851,6 @@ fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) {
18511851
}
18521852
}
18531853

1854-
// NB: Increment this as you change the metadata encoding version.
1855-
#[allow(non_upper_case_globals)]
1856-
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1857-
18581854
pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
18591855
let mut wr = Cursor::new(Vec::new());
18601856

src/librustc_metadata/loader.rs

+30-5
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@
213213
//! metadata::loader or metadata::creader for all the juicy details!
214214
215215
use cstore::{MetadataBlob, MetadataVec, MetadataArchive};
216+
use common::{metadata_encoding_version, rustc_version};
216217
use decoder;
217-
use encoder;
218218

219219
use rustc::hir::svh::Svh;
220220
use rustc::session::Session;
@@ -260,6 +260,7 @@ pub struct Context<'a> {
260260
pub rejected_via_hash: Vec<CrateMismatch>,
261261
pub rejected_via_triple: Vec<CrateMismatch>,
262262
pub rejected_via_kind: Vec<CrateMismatch>,
263+
pub rejected_via_version: Vec<CrateMismatch>,
263264
pub should_match_name: bool,
264265
}
265266

@@ -336,6 +337,10 @@ impl<'a> Context<'a> {
336337
struct_span_err!(self.sess, self.span, E0462,
337338
"found staticlib `{}` instead of rlib or dylib{}",
338339
self.ident, add)
340+
} else if !self.rejected_via_version.is_empty() {
341+
struct_span_err!(self.sess, self.span, E0514,
342+
"found crate `{}` compiled by an incompatible version of rustc{}",
343+
self.ident, add)
339344
} else {
340345
struct_span_err!(self.sess, self.span, E0463,
341346
"can't find crate for `{}`{}",
@@ -350,7 +355,7 @@ impl<'a> Context<'a> {
350355
}
351356
}
352357
if !self.rejected_via_hash.is_empty() {
353-
err.note("perhaps this crate needs to be recompiled?");
358+
err.note("perhaps that crate needs to be recompiled?");
354359
let mismatches = self.rejected_via_hash.iter();
355360
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
356361
err.note(&format!("crate `{}` path #{}: {}",
@@ -367,13 +372,22 @@ impl<'a> Context<'a> {
367372
}
368373
}
369374
if !self.rejected_via_kind.is_empty() {
370-
err.help("please recompile this crate using --crate-type lib");
375+
err.help("please recompile that crate using --crate-type lib");
371376
let mismatches = self.rejected_via_kind.iter();
372377
for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
373378
err.note(&format!("crate `{}` path #{}: {}",
374379
self.ident, i+1, path.display()));
375380
}
376381
}
382+
if !self.rejected_via_version.is_empty() {
383+
err.help(&format!("please recompile that crate using this compiler ({})",
384+
rustc_version()));
385+
let mismatches = self.rejected_via_version.iter();
386+
for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() {
387+
err.note(&format!("crate `{}` path #{}: {} compiled by {:?}",
388+
self.ident, i+1, path.display(), got));
389+
}
390+
}
377391

378392
err.emit();
379393
self.sess.abort_if_errors();
@@ -591,6 +605,17 @@ impl<'a> Context<'a> {
591605
}
592606

593607
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option<Svh> {
608+
let crate_rustc_version = decoder::crate_rustc_version(crate_data);
609+
if crate_rustc_version != Some(rustc_version()) {
610+
let message = crate_rustc_version.unwrap_or(format!("an unknown compiler"));
611+
info!("Rejecting via version: expected {} got {}", rustc_version(), message);
612+
self.rejected_via_version.push(CrateMismatch {
613+
path: libpath.to_path_buf(),
614+
got: message
615+
});
616+
return None;
617+
}
618+
594619
if self.should_match_name {
595620
match decoder::maybe_get_crate_name(crate_data) {
596621
Some(ref name) if self.crate_name == *name => {}
@@ -801,12 +826,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
801826
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
802827
let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
803828
let cvbuf: *const u8 = cbuf as *const u8;
804-
let vlen = encoder::metadata_encoding_version.len();
829+
let vlen = metadata_encoding_version.len();
805830
debug!("checking {} bytes of metadata-version stamp",
806831
vlen);
807832
let minsz = cmp::min(vlen, csz);
808833
let buf0 = slice::from_raw_parts(cvbuf, minsz);
809-
let version_ok = buf0 == encoder::metadata_encoding_version;
834+
let version_ok = buf0 == metadata_encoding_version;
810835
if !version_ok {
811836
return Err((format!("incompatible metadata version found: '{}'",
812837
filename.display())));

0 commit comments

Comments
 (0)