Skip to content

Commit

Permalink
add a encoding version to the actual metadata
Browse files Browse the repository at this point in the history
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 #33778.
  • Loading branch information
arielb1 committed Jul 2, 2016
1 parent 0b36fff commit e154687
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 18 deletions.
26 changes: 16 additions & 10 deletions src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

pub use self::MetadataBlob::*;

use common;
use creader;
use decoder;
use index;
Expand Down Expand Up @@ -328,20 +329,25 @@ impl CrateMetadata {
}

impl MetadataBlob {
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
let slice = match *self {
pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] {
match *self {
MetadataVec(ref vec) => &vec[..],
MetadataArchive(ref ar) => ar.as_slice(),
};
if slice.len() < 4 {
}
}

pub fn as_slice<'a>(&'a self) -> &'a [u8] {
let slice = self.as_slice_raw();
let len_offset = 4 + common::metadata_encoding_version.len();
if slice.len() < len_offset+4 {
&[] // corrupt metadata
} else {
let len = (((slice[0] as u32) << 24) |
((slice[1] as u32) << 16) |
((slice[2] as u32) << 8) |
((slice[3] as u32) << 0)) as usize;
if len + 4 <= slice.len() {
&slice[4.. len + 4]
let len = (((slice[len_offset+0] as u32) << 24) |
((slice[len_offset+1] as u32) << 16) |
((slice[len_offset+2] as u32) << 8) |
((slice[len_offset+3] as u32) << 0)) as usize;
if len <= slice.len() - 4 - len_offset {
&slice[len_offset + 4..len_offset + len + 4]
} else {
&[] // corrupt or old metadata
}
Expand Down
25 changes: 19 additions & 6 deletions src/librustc_metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1832,12 +1832,25 @@ pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
// the length of the metadata to the start of the metadata. Later on this
// will allow us to slice the metadata to the precise length that we just
// generated regardless of trailing bytes that end up in it.
let len = v.len() as u32;
v.insert(0, (len >> 0) as u8);
v.insert(0, (len >> 8) as u8);
v.insert(0, (len >> 16) as u8);
v.insert(0, (len >> 24) as u8);
return v;
//
// We also need to store the metadata encoding version here, because
// rlibs don't have it. To get older versions of rustc to ignore
// this metadata, there are 4 zero bytes at the start, which are
// treated as a length of 0 by old compilers.

let len = v.len();
let mut result = vec![];
result.push(0);
result.push(0);
result.push(0);
result.push(0);
result.extend(metadata_encoding_version.iter().cloned());
result.push((len >> 24) as u8);
result.push((len >> 16) as u8);
result.push((len >> 8) as u8);
result.push((len >> 0) as u8);
result.extend(v);
result
}

fn encode_metadata_inner(rbml_w: &mut Encoder,
Expand Down
26 changes: 24 additions & 2 deletions src/librustc_metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,21 @@ impl ArchiveMetadata {
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
}

fn verify_decompressed_encoding_version(blob: &MetadataBlob, filename: &Path)
-> Result<(), String>
{
let data = blob.as_slice_raw();
if data.len() < 4+metadata_encoding_version.len() ||
!<[u8]>::eq(&data[..4], &[0, 0, 0, 0]) ||
&data[4..4+metadata_encoding_version.len()] != metadata_encoding_version
{
Err((format!("incompatible metadata version found: '{}'",
filename.display())))
} else {
Ok(())
}
}

// Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path)
-> Result<MetadataBlob, String> {
Expand Down Expand Up @@ -797,7 +812,10 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
None => Err(format!("failed to read rlib metadata: '{}'",
filename.display())),
Some(blob) => Ok(blob)
Some(blob) => {
try!(verify_decompressed_encoding_version(&blob, filename));
Ok(blob)
}
};
}
unsafe {
Expand Down Expand Up @@ -842,7 +860,11 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
csz - vlen);
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
match flate::inflate_bytes(bytes) {
Ok(inflated) => return Ok(MetadataVec(inflated)),
Ok(inflated) => {
let blob = MetadataVec(inflated);
try!(verify_decompressed_encoding_version(&blob, filename));
return Ok(blob);
}
Err(_) => {}
}
}
Expand Down

0 comments on commit e154687

Please sign in to comment.