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 #33778.
This commit is contained in:
parent
0b36fff4d7
commit
e154687f57
3 changed files with 59 additions and 18 deletions
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
pub use self::MetadataBlob::*;
|
||||
|
||||
use common;
|
||||
use creader;
|
||||
use decoder;
|
||||
use index;
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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(_) => {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue