about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-12-16 00:52:35 +0000
committerbors <bors@rust-lang.org>2016-12-16 00:52:35 +0000
commit8ae904062b2700a797138d2b8274f2e141ea1e53 (patch)
tree553d6d10c11789417c8dbf00727d3716644519f3 /src
parent8f02c429ad3e2ad687a222d1daae2e04bb9bb876 (diff)
parent7bc10545d635bc1f4a5632703823a6f18113df9c (diff)
downloadrust-8ae904062b2700a797138d2b8274f2e141ea1e53.tar.gz
rust-8ae904062b2700a797138d2b8274f2e141ea1e53.zip
Auto merge of #38352 - bluss:unaligned-metadata, r=eddyb
Fix unaligned loads in librustc_metadata

Creating a `&[u32]` from an `&[u8]` is not necessarily valid, and crashes
on certain platforms if the data is not well aligned.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_metadata/index.rs16
1 files changed, 12 insertions, 4 deletions
diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs
index 53e6988c756..5b52b268849 100644
--- a/src/librustc_metadata/index.rs
+++ b/src/librustc_metadata/index.rs
@@ -70,7 +70,7 @@ impl<'tcx> LazySeq<Index> {
                index,
                words.len());
 
-        let position = u32::from_le(words[index]);
+        let position = u32::from_le(words[index].get());
         if position == u32::MAX {
             debug!("Index::lookup: position=u32::MAX");
             None
@@ -84,7 +84,7 @@ impl<'tcx> LazySeq<Index> {
                                bytes: &'a [u8])
                                -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
         let words = &bytes_to_words(&bytes[self.position..])[..self.len];
-        words.iter().enumerate().filter_map(|(index, &position)| {
+        words.iter().map(|word| word.get()).enumerate().filter_map(|(index, position)| {
             if position == u32::MAX {
                 None
             } else {
@@ -95,8 +95,16 @@ impl<'tcx> LazySeq<Index> {
     }
 }
 
-fn bytes_to_words(b: &[u8]) -> &[u32] {
-    unsafe { slice::from_raw_parts(b.as_ptr() as *const u32, b.len() / 4) }
+#[repr(packed)]
+#[derive(Copy, Clone)]
+struct Unaligned<T>(T);
+
+impl<T> Unaligned<T> {
+    fn get(self) -> T { self.0 }
+}
+
+fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
+    unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
 }
 
 fn words_to_bytes(w: &[u32]) -> &[u8] {