Skip to content

Commit 7244769

Browse files
authored
Fix aliasing in Clone by using a raw pointer (#523)
Previously, this code produced a &mut[u8] and a Box<[u8]> to the shared allocation upon cloning it. If the underlying allocation were actually shared, such as through a &[u8] from the Deref impl, creating either of these types incorrectly asserted uniqueness of the allocation. This fixes the example in #522, but Miri still does not pass on this test suite with -Zmiri-tag-raw-pointers because Miri does not currently understand int to pointer casts.
1 parent 9e6edd1 commit 7244769

File tree

1 file changed

+18
-5
lines changed

1 file changed

+18
-5
lines changed

src/bytes.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@ use core::iter::FromIterator;
22
use core::ops::{Deref, RangeBounds};
33
use core::{cmp, fmt, hash, mem, ptr, slice, usize};
44

5-
use alloc::{borrow::Borrow, boxed::Box, string::String, vec::Vec};
5+
use alloc::{
6+
alloc::{dealloc, Layout},
7+
borrow::Borrow,
8+
boxed::Box,
9+
string::String,
10+
vec::Vec,
11+
};
612

713
use crate::buf::IntoIter;
814
#[allow(unused)]
@@ -941,11 +947,18 @@ unsafe fn rebuild_boxed_slice(buf: *mut u8, offset: *const u8, len: usize) -> Bo
941947
// ===== impl SharedVtable =====
942948

943949
struct Shared {
944-
// holds vec for drop, but otherwise doesnt access it
945-
_vec: Vec<u8>,
950+
// Holds arguments to dealloc upon Drop, but otherwise doesn't use them
951+
buf: *mut u8,
952+
cap: usize,
946953
ref_cnt: AtomicUsize,
947954
}
948955

956+
impl Drop for Shared {
957+
fn drop(&mut self) {
958+
unsafe { dealloc(self.buf, Layout::from_size_align(self.cap, 1).unwrap()) }
959+
}
960+
}
961+
949962
// Assert that the alignment of `Shared` is divisible by 2.
950963
// This is a necessary invariant since we depend on allocating `Shared` a
951964
// shared object to implicitly carry the `KIND_ARC` flag in its pointer.
@@ -1006,9 +1019,9 @@ unsafe fn shallow_clone_vec(
10061019
// updated and since the buffer hasn't been promoted to an
10071020
// `Arc`, those three fields still are the components of the
10081021
// vector.
1009-
let vec = rebuild_boxed_slice(buf, offset, len).into_vec();
10101022
let shared = Box::new(Shared {
1011-
_vec: vec,
1023+
buf,
1024+
cap: (offset as usize - buf as usize) + len,
10121025
// Initialize refcount to 2. One for this reference, and one
10131026
// for the new clone that will be returned from
10141027
// `shallow_clone`.

0 commit comments

Comments
 (0)