Skip to content

Commit 8fbfa66

Browse files
committed
auto merge of #19563 : alexcrichton/rust/issue-19501, r=pnkfelix
One of the causes of #19501 was that the metadata on OSX was getting corrupted. For any one particular invocation of the compiler the metadata file inside of an rlib archive would have extra bytes appended to the end of it. These extra bytes end up confusing rbml and have it run off the end of the array (resulting in the out of bounds detected). This commit prepends the length of metadata to the start of the metadata to ensure that we always slice the precise amount that we want, and it also un-ignores the test from #19502. Closes #19501
2 parents b25e100 + daafff5 commit 8fbfa66

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

src/librustc/metadata/cstore.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,18 @@ impl crate_metadata {
231231

232232
impl MetadataBlob {
233233
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
234-
match *self {
234+
let slice = match *self {
235235
MetadataVec(ref vec) => vec.as_slice(),
236236
MetadataArchive(ref ar) => ar.as_slice(),
237+
};
238+
if slice.len() < 4 {
239+
&[]
240+
} else {
241+
let len = ((slice[0] as u32) << 24) |
242+
((slice[1] as u32) << 16) |
243+
((slice[2] as u32) << 8) |
244+
((slice[3] as u32) << 0);
245+
slice.slice(4, len as uint + 4)
237246
}
238247
}
239248
}

src/librustc/metadata/encoder.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1979,7 +1979,32 @@ pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't',
19791979
pub fn encode_metadata(parms: EncodeParams, krate: &ast::Crate) -> Vec<u8> {
19801980
let mut wr = SeekableMemWriter::new();
19811981
encode_metadata_inner(&mut wr, parms, krate);
1982-
wr.unwrap().into_iter().collect()
1982+
let mut v = wr.unwrap();
1983+
1984+
// And here we run into yet another obscure archive bug: in which metadata
1985+
// loaded from archives may have trailing garbage bytes. Awhile back one of
1986+
// our tests was failing sporadially on the OSX 64-bit builders (both nopt
1987+
// and opt) by having rbml generate an out-of-bounds panic when looking at
1988+
// metadata.
1989+
//
1990+
// Upon investigation it turned out that the metadata file inside of an rlib
1991+
// (and ar archive) was being corrupted. Some compilations would generate a
1992+
// metadata file which would end in a few extra bytes, while other
1993+
// compilations would not have these extra bytes appended to the end. These
1994+
// extra bytes were interpreted by rbml as an extra tag, so they ended up
1995+
// being interpreted causing the out-of-bounds.
1996+
//
1997+
// The root cause of why these extra bytes were appearing was never
1998+
// discovered, and in the meantime the solution we're employing is to insert
1999+
// the length of the metadata to the start of the metadata. Later on this
2000+
// will allow us to slice the metadata to the precise length that we just
2001+
// generated regardless of trailing bytes that end up in it.
2002+
let len = v.len() as u32;
2003+
v.insert(0, (len >> 0) as u8);
2004+
v.insert(0, (len >> 8) as u8);
2005+
v.insert(0, (len >> 16) as u8);
2006+
v.insert(0, (len >> 24) as u8);
2007+
return v;
19832008
}
19842009

19852010
fn encode_metadata_inner(wr: &mut SeekableMemWriter,

src/test/run-pass-fulldeps/issue-13560.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// aux-build:issue-13560-1.rs
1212
// aux-build:issue-13560-2.rs
1313
// aux-build:issue-13560-3.rs
14-
// ignore-pretty FIXME #19501
1514
// ignore-stage1
1615

1716
// Regression test for issue #13560, the test itself is all in the dependent

0 commit comments

Comments
 (0)