Skip to content

Commit f1079b2

Browse files
committed
rustc_metadata: safely read/write the index positions.
1 parent 0085672 commit f1079b2

File tree

1 file changed

+23
-41
lines changed

1 file changed

+23
-41
lines changed

src/librustc_metadata/index.rs

Lines changed: 23 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use crate::schema::*;
22

33
use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
44
use rustc_serialize::opaque::Encoder;
5-
use std::slice;
65
use std::u32;
76
use log::debug;
87

@@ -14,14 +13,14 @@ use log::debug;
1413
/// appropriate spot by calling `record_position`. We should never
1514
/// visit the same index twice.
1615
pub struct Index {
17-
positions: [Vec<u32>; 2]
16+
positions: [Vec<u8>; 2]
1817
}
1918

2019
impl Index {
2120
pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index {
2221
Index {
23-
positions: [vec![u32::MAX; max_index_lo],
24-
vec![u32::MAX; max_index_hi]],
22+
positions: [vec![0xff; max_index_lo * 4],
23+
vec![0xff; max_index_hi * 4]],
2524
}
2625
}
2726

@@ -36,26 +35,27 @@ impl Index {
3635
let space_index = item.address_space().index();
3736
let array_index = item.as_array_index();
3837

39-
assert!(self.positions[space_index][array_index] == u32::MAX,
38+
let destination = &mut self.positions[space_index][array_index * 4..];
39+
assert!(read_le_u32(destination) == u32::MAX,
4040
"recorded position for item {:?} twice, first at {:?} and now at {:?}",
4141
item,
42-
self.positions[space_index][array_index],
42+
read_le_u32(destination),
4343
position);
4444

45-
self.positions[space_index][array_index] = position.to_le();
45+
write_le_u32(destination, position);
4646
}
4747

4848
pub fn write_index(&self, buf: &mut Encoder) -> LazySeq<Index> {
4949
let pos = buf.position();
5050

5151
// First we write the length of the lower range ...
52-
buf.emit_raw_bytes(words_to_bytes(&[(self.positions[0].len() as u32).to_le()]));
52+
buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes());
5353
// ... then the values in the lower range ...
54-
buf.emit_raw_bytes(words_to_bytes(&self.positions[0][..]));
54+
buf.emit_raw_bytes(&self.positions[0]);
5555
// ... then the values in the higher range.
56-
buf.emit_raw_bytes(words_to_bytes(&self.positions[1][..]));
56+
buf.emit_raw_bytes(&self.positions[1]);
5757
LazySeq::with_position_and_length(pos as usize,
58-
self.positions[0].len() + self.positions[1].len() + 1)
58+
(self.positions[0].len() + self.positions[1].len()) / 4 + 1)
5959
}
6060
}
6161

@@ -64,24 +64,20 @@ impl<'tcx> LazySeq<Index> {
6464
/// DefIndex (if any).
6565
#[inline(never)]
6666
pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
67-
let words = &bytes_to_words(&bytes[self.position..])[..self.len];
68-
69-
debug!("Index::lookup: index={:?} words.len={:?}",
67+
debug!("Index::lookup: index={:?} len={:?}",
7068
def_index,
71-
words.len());
69+
self.len);
7270

73-
let positions = match def_index.address_space() {
74-
DefIndexAddressSpace::Low => &words[1..],
71+
let i = def_index.as_array_index() + match def_index.address_space() {
72+
DefIndexAddressSpace::Low => 0,
7573
DefIndexAddressSpace::High => {
7674
// This is a DefIndex in the higher range, so find out where
7775
// that starts:
78-
let lo_count = u32::from_le(words[0].get()) as usize;
79-
&words[lo_count + 1 .. ]
76+
read_le_u32(&bytes[self.position..]) as usize
8077
}
8178
};
8279

83-
let array_index = def_index.as_array_index();
84-
let position = u32::from_le(positions[array_index].get());
80+
let position = read_le_u32(&bytes[self.position + (1 + i) * 4..]);
8581
if position == u32::MAX {
8682
debug!("Index::lookup: position=u32::MAX");
8783
None
@@ -92,26 +88,12 @@ impl<'tcx> LazySeq<Index> {
9288
}
9389
}
9490

95-
#[repr(packed)]
96-
#[derive(Copy)]
97-
struct Unaligned<T>(T);
98-
99-
// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
100-
// the field to `T::clone`, but this reference may not be properly aligned.
101-
impl<T: Copy> Clone for Unaligned<T> {
102-
fn clone(&self) -> Self {
103-
*self
104-
}
105-
}
106-
107-
impl<T> Unaligned<T> {
108-
fn get(self) -> T { self.0 }
109-
}
110-
111-
fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
112-
unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
91+
fn read_le_u32(b: &[u8]) -> u32 {
92+
let mut bytes = [0; 4];
93+
bytes.copy_from_slice(&b[..4]);
94+
u32::from_le_bytes(bytes)
11395
}
11496

115-
fn words_to_bytes(w: &[u32]) -> &[u8] {
116-
unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
97+
fn write_le_u32(b: &mut [u8], x: u32) {
98+
b[..4].copy_from_slice(&x.to_le_bytes());
11799
}

0 commit comments

Comments
 (0)