about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-12-13 17:34:40 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-12-14 00:59:59 +0100
commit7bc10545d635bc1f4a5632703823a6f18113df9c (patch)
tree0a8cdb698bbc9434cf60aca56c7786444125ae20
parent0d1b9f4614a086e92a81f45b46c73d5e4b6ad94d (diff)
downloadrust-7bc10545d635bc1f4a5632703823a6f18113df9c.tar.gz
rust-7bc10545d635bc1f4a5632703823a6f18113df9c.zip
rustc_metadata: Fix unaligned loads
Creating a `&[u32]` from a `&[u8]` was not valid; the data is not
necessarily well aligned.
-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] {