Skip to content

Commit 8a2e05e

Browse files
committed
add a encoding version to the actual metadata
previously, only .so files included a metadata encoding version, *outside* of the zlib compressed area. This adds an encoding version inside the metadata itself, in both .so and .rlib files. Fixes rust-lang#33778.
1 parent 7be8487 commit 8a2e05e

File tree

3 files changed

+59
-18
lines changed

3 files changed

+59
-18
lines changed

src/librustc_metadata/cstore.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
pub use self::MetadataBlob::*;
1717

18+
use common;
1819
use creader;
1920
use decoder;
2021
use index;
@@ -311,20 +312,25 @@ impl crate_metadata {
311312
}
312313

313314
impl MetadataBlob {
314-
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
315-
let slice = match *self {
315+
pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] {
316+
match *self {
316317
MetadataVec(ref vec) => &vec[..],
317318
MetadataArchive(ref ar) => ar.as_slice(),
318-
};
319-
if slice.len() < 4 {
319+
}
320+
}
321+
322+
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
323+
let slice = self.as_slice_raw();
324+
let len_offset = 4 + common::metadata_encoding_version.len();
325+
if slice.len() < len_offset+4 {
320326
&[] // corrupt metadata
321327
} else {
322-
let len = (((slice[0] as u32) << 24) |
323-
((slice[1] as u32) << 16) |
324-
((slice[2] as u32) << 8) |
325-
((slice[3] as u32) << 0)) as usize;
326-
if len + 4 <= slice.len() {
327-
&slice[4.. len + 4]
328+
let len = (((slice[len_offset+0] as u32) << 24) |
329+
((slice[len_offset+1] as u32) << 16) |
330+
((slice[len_offset+2] as u32) << 8) |
331+
((slice[len_offset+3] as u32) << 0)) as usize;
332+
if len <= slice.len() - 4 - len_offset {
333+
&slice[len_offset + 4..len_offset + len + 4]
328334
} else {
329335
&[] // corrupt or old metadata
330336
}

src/librustc_metadata/encoder.rs

+19-6
Original file line numberDiff line numberDiff line change
@@ -1884,12 +1884,25 @@ pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
18841884
// the length of the metadata to the start of the metadata. Later on this
18851885
// will allow us to slice the metadata to the precise length that we just
18861886
// generated regardless of trailing bytes that end up in it.
1887-
let len = v.len() as u32;
1888-
v.insert(0, (len >> 0) as u8);
1889-
v.insert(0, (len >> 8) as u8);
1890-
v.insert(0, (len >> 16) as u8);
1891-
v.insert(0, (len >> 24) as u8);
1892-
return v;
1887+
//
1888+
// We also need to store the metadata encoding version here, because
1889+
// rlibs don't have it. To get older versions of rustc to ignore
1890+
// this metadata, there are 4 zero bytes at the start, which are
1891+
// treated as a length of 0 by old compilers.
1892+
1893+
let len = v.len();
1894+
let mut result = vec![];
1895+
result.push(0);
1896+
result.push(0);
1897+
result.push(0);
1898+
result.push(0);
1899+
result.extend(metadata_encoding_version.iter().cloned());
1900+
result.push((len >> 24) as u8);
1901+
result.push((len >> 16) as u8);
1902+
result.push((len >> 8) as u8);
1903+
result.push((len >> 0) as u8);
1904+
result.extend(v);
1905+
result
18931906
}
18941907

18951908
fn encode_metadata_inner(rbml_w: &mut Encoder,

src/librustc_metadata/loader.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,21 @@ impl ArchiveMetadata {
767767
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
768768
}
769769

770+
fn verify_decompressed_encoding_version(blob: &MetadataBlob, filename: &Path)
771+
-> Result<(), String>
772+
{
773+
let data = blob.as_slice_raw();
774+
if data.len() < 4+metadata_encoding_version.len() ||
775+
!<[u8]>::eq(&data[..4], &[0, 0, 0, 0]) ||
776+
&data[4..4+metadata_encoding_version.len()] != metadata_encoding_version
777+
{
778+
Err((format!("incompatible metadata version found: '{}'",
779+
filename.display())))
780+
} else {
781+
Ok(())
782+
}
783+
}
784+
770785
// Just a small wrapper to time how long reading metadata takes.
771786
fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path)
772787
-> Result<MetadataBlob, String> {
@@ -797,7 +812,10 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
797812
return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
798813
None => Err(format!("failed to read rlib metadata: '{}'",
799814
filename.display())),
800-
Some(blob) => Ok(blob)
815+
Some(blob) => {
816+
try!(verify_decompressed_encoding_version(&blob, filename));
817+
Ok(blob)
818+
}
801819
};
802820
}
803821
unsafe {
@@ -842,7 +860,11 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
842860
csz - vlen);
843861
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
844862
match flate::inflate_bytes(bytes) {
845-
Ok(inflated) => return Ok(MetadataVec(inflated)),
863+
Ok(inflated) => {
864+
let blob = MetadataVec(inflated);
865+
try!(verify_decompressed_encoding_version(&blob, filename));
866+
return Ok(blob);
867+
}
846868
Err(_) => {}
847869
}
848870
}

0 commit comments

Comments
 (0)