Skip to content

Commit 93bdb87

Browse files
committed
Snapshot/write-back the entire region between offset and end of original alloc
1 parent b79bf93 commit 93bdb87

1 file changed

Lines changed: 29 additions & 14 deletions

File tree

libcc2rs/src/rc.rs

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,27 @@ pub enum StrongPtr<T> {
4343
byte_offset: usize,
4444
// Local buffer for deref(). None until first access.
4545
// Read-through: refreshed from alloc on every deref() call.
46-
cell: RefCell<Option<T>>,
46+
cell: RefCell<Option<Vec<T>>>,
4747
},
4848
}
4949

50+
fn read_reinterpreted_region<T: ByteRepr>(
51+
data: &dyn OriginalAlloc,
52+
offset: usize,
53+
) -> (Vec<u8>, Vec<T>) {
54+
let elem_size = std::mem::size_of::<T>();
55+
let num_elems = data
56+
.total_byte_len()
57+
.saturating_sub(offset)
58+
.checked_div(elem_size)
59+
.unwrap_or(0);
60+
assert!(num_elems > 0, "ub: dereference out of bounds");
61+
let mut buf = vec![0u8; num_elems * elem_size];
62+
data.read_bytes(offset, &mut buf);
63+
let vals = buf.chunks_exact(elem_size).map(T::from_bytes).collect();
64+
(buf, vals)
65+
}
66+
5067
impl<T: ByteRepr> StrongPtr<T> {
5168
pub fn deref(&self) -> Ref<'_, T> {
5269
match self {
@@ -59,10 +76,9 @@ impl<T: ByteRepr> StrongPtr<T> {
5976
cell,
6077
} => {
6178
// Read-through: always re-read from the original allocation.
62-
let mut buf = vec![0u8; std::mem::size_of::<T>()];
63-
alloc.read_bytes(*byte_offset, &mut buf);
64-
*cell.borrow_mut() = Some(T::from_bytes(&buf));
65-
Ref::map(cell.borrow(), |opt| opt.as_ref().unwrap())
79+
let (_, vals) = read_reinterpreted_region::<T>(&**alloc, *byte_offset);
80+
*cell.borrow_mut() = Some(vals);
81+
Ref::map(cell.borrow(), |opt| &opt.as_ref().unwrap()[0])
6682
}
6783
}
6884
}
@@ -442,11 +458,12 @@ impl<T> Ptr<T> {
442458
f(&mut borrow[self.offset])
443459
}
444460
PtrKind::Reinterpreted(data) => {
445-
let mut buf = vec![0u8; std::mem::size_of::<T>()];
446-
data.read_bytes(self.offset, &mut buf);
447-
let mut val = T::from_bytes(&buf);
448-
let ret = f(&mut val);
449-
val.to_bytes(&mut buf);
461+
let (mut buf, mut vals) = read_reinterpreted_region::<T>(&**data, self.offset);
462+
let elem_size = std::mem::size_of::<T>();
463+
let ret = f(&mut vals[0]);
464+
for (i, val) in vals.iter().enumerate() {
465+
val.to_bytes(&mut buf[i * elem_size..(i + 1) * elem_size]);
466+
}
450467
data.write_bytes(self.offset, &buf);
451468
ret
452469
}
@@ -475,10 +492,8 @@ impl<T> Ptr<T> {
475492
f(&borrow[self.offset])
476493
}
477494
PtrKind::Reinterpreted(data) => {
478-
let mut buf = vec![0u8; std::mem::size_of::<T>()];
479-
data.read_bytes(self.offset, &mut buf);
480-
let val = T::from_bytes(&buf);
481-
f(&val)
495+
let (_, vals) = read_reinterpreted_region::<T>(&**data, self.offset);
496+
f(&vals[0])
482497
}
483498
}
484499
}

0 commit comments

Comments
 (0)