Skip to content

Commit 1e45b63

Browse files
authored
Auto merge of #37931 - eddyb:meta-version, r=jseyfried
rustc_metadata: don't break the version check when CrateRoot changes. In #36551 I made `rustc_version` a field of `CrateRoot`, but despite it being the first field, one could still break the version check by changing `CrateRoot` so older compilers couldn't fully decode it (e.g. #37463). This PR fixes #37803 by moving the version string back at the beginning of metadata, right after the 32-bit big-endian absolute position of `CrateRoot`, and by incrementing `METADATA_VERSION`.
2 parents d5814b0 + f4c68d2 commit 1e45b63

File tree

4 files changed

+31
-18
lines changed

4 files changed

+31
-18
lines changed

src/librustc_metadata/decoder.rs

+4
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,10 @@ impl<'a, 'tcx> MetadataBlob {
421421
self.raw_bytes().starts_with(METADATA_HEADER)
422422
}
423423

424+
pub fn get_rustc_version(&self) -> String {
425+
Lazy::with_position(METADATA_HEADER.len() + 4).decode(self)
426+
}
427+
424428
pub fn get_root(&self) -> CrateRoot {
425429
let slice = self.raw_bytes();
426430
let offset = METADATA_HEADER.len();

src/librustc_metadata/encoder.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -1278,7 +1278,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
12781278
let link_meta = self.link_meta;
12791279
let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateTypeProcMacro);
12801280
let root = self.lazy(&CrateRoot {
1281-
rustc_version: rustc_version(),
12821281
name: link_meta.crate_name,
12831282
triple: tcx.sess.opts.target_triple.clone(),
12841283
hash: link_meta.crate_hash,
@@ -1368,7 +1367,8 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13681367
// Will be filed with the root position after encoding everything.
13691368
cursor.write_all(&[0, 0, 0, 0]).unwrap();
13701369

1371-
let root = EncodeContext {
1370+
let root = {
1371+
let mut ecx = EncodeContext {
13721372
opaque: opaque::Encoder::new(&mut cursor),
13731373
tcx: tcx,
13741374
reexports: reexports,
@@ -1378,8 +1378,15 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13781378
lazy_state: LazyState::NoNode,
13791379
type_shorthands: Default::default(),
13801380
predicate_shorthands: Default::default(),
1381-
}
1382-
.encode_crate_root();
1381+
};
1382+
1383+
// Encode the rustc version string in a predictable location.
1384+
rustc_version().encode(&mut ecx).unwrap();
1385+
1386+
// Encode all the entries and extra information in the crate,
1387+
// culminating in the `CrateRoot` which points to all of it.
1388+
ecx.encode_crate_root()
1389+
};
13831390
let mut result = cursor.into_inner();
13841391

13851392
// Encode the root position.

src/librustc_metadata/locator.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -639,25 +639,26 @@ impl<'a> Context<'a> {
639639
}
640640

641641
fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option<Svh> {
642-
let root = metadata.get_root();
643-
if let Some(is_proc_macro) = self.is_proc_macro {
644-
if root.macro_derive_registrar.is_some() != is_proc_macro {
645-
return None;
646-
}
647-
}
648-
649642
let rustc_version = rustc_version();
650-
if root.rustc_version != rustc_version {
643+
let found_version = metadata.get_rustc_version();
644+
if found_version != rustc_version {
651645
info!("Rejecting via version: expected {} got {}",
652646
rustc_version,
653-
root.rustc_version);
647+
found_version);
654648
self.rejected_via_version.push(CrateMismatch {
655649
path: libpath.to_path_buf(),
656-
got: root.rustc_version,
650+
got: found_version,
657651
});
658652
return None;
659653
}
660654

655+
let root = metadata.get_root();
656+
if let Some(is_proc_macro) = self.is_proc_macro {
657+
if root.macro_derive_registrar.is_some() != is_proc_macro {
658+
return None;
659+
}
660+
}
661+
661662
if self.should_match_name {
662663
if self.crate_name != root.name {
663664
info!("Rejecting via crate name");

src/librustc_metadata/schema.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ pub fn rustc_version() -> String {
3434

3535
/// Metadata encoding version.
3636
/// NB: increment this if you change the format of metadata such that
37-
/// the rustc version can't be found to compare with `RUSTC_VERSION`.
38-
pub const METADATA_VERSION: u8 = 3;
37+
/// the rustc version can't be found to compare with `rustc_version()`.
38+
pub const METADATA_VERSION: u8 = 4;
3939

4040
/// Metadata header which includes `METADATA_VERSION`.
4141
/// To get older versions of rustc to ignore this metadata,
4242
/// there are 4 zero bytes at the start, which are treated
4343
/// as a length of 0 by old compilers.
4444
///
45-
/// This header is followed by the position of the `CrateRoot`.
45+
/// This header is followed by the position of the `CrateRoot`,
46+
/// which is encoded as a 32-bit big-endian unsigned integer,
47+
/// and further followed by the rustc version string.
4648
pub const METADATA_HEADER: &'static [u8; 12] =
4749
&[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
4850

@@ -163,7 +165,6 @@ pub enum LazyState {
163165

164166
#[derive(RustcEncodable, RustcDecodable)]
165167
pub struct CrateRoot {
166-
pub rustc_version: String,
167168
pub name: Symbol,
168169
pub triple: String,
169170
pub hash: hir::svh::Svh,

0 commit comments

Comments
 (0)