Skip to content

Commit 0b36fff

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 #33733 Fixes #33015
1 parent c333ebb commit 0b36fff

File tree

5 files changed

+38
-31
lines changed

5 files changed

+38
-31
lines changed

src/librustc_metadata/common.rs

Lines changed: 4 additions & 0 deletions
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

Lines changed: 2 additions & 21 deletions
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};
@@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
236235
return ret;
237236
}
238237

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

302281
// Claim this crate number and cache it
@@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
381360
rejected_via_hash: vec!(),
382361
rejected_via_triple: vec!(),
383362
rejected_via_kind: vec!(),
363+
rejected_via_version: vec!(),
384364
should_match_name: true,
385365
};
386366
match self.load(&mut load_ctxt) {
@@ -517,6 +497,7 @@ impl<'a> CrateReader<'a> {
517497
rejected_via_hash: vec!(),
518498
rejected_via_triple: vec!(),
519499
rejected_via_kind: vec!(),
500+
rejected_via_version: vec!(),
520501
should_match_name: true,
521502
};
522503
let library = self.load(&mut load_ctxt).or_else(|| {

src/librustc_metadata/csearch.rs

Lines changed: 2 additions & 1 deletion
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;
@@ -588,7 +589,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
588589

589590
fn metadata_encoding_version(&self) -> &[u8]
590591
{
591-
encoder::metadata_encoding_version
592+
common::metadata_encoding_version
592593
}
593594

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

src/librustc_metadata/encoder.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,10 +1799,6 @@ fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) {
17991799
}
18001800
}
18011801

1802-
// NB: Increment this as you change the metadata encoding version.
1803-
#[allow(non_upper_case_globals)]
1804-
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
1805-
18061802
pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
18071803
let mut wr = Cursor::new(Vec::new());
18081804

src/librustc_metadata/loader.rs

Lines changed: 30 additions & 5 deletions
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)