Skip to content

Commit c34451f

Browse files
committed
fix aliasing violation in align_to_mut
1 parent 04e7f96 commit c34451f

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

src/libcore/slice/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2571,11 +2571,13 @@ impl<T> [T] {
25712571
let (left, rest) = self.split_at_mut(offset);
25722572
// now `rest` is definitely aligned, so `from_raw_parts_mut` below is okay
25732573
let (us_len, ts_len) = rest.align_to_offsets::<U>();
2574+
let rest_len = rest.len();
25742575
let mut_ptr = rest.as_mut_ptr();
2576+
// We can't use `rest` again after this, that would invalidate its alias `mut_ptr`!
25752577
(
25762578
left,
25772579
from_raw_parts_mut(mut_ptr as *mut U, us_len),
2578-
from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len),
2580+
from_raw_parts_mut(mut_ptr.add(rest_len - ts_len), ts_len),
25792581
)
25802582
}
25812583
}

src/libcore/tests/slice.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,18 @@ fn test_align_to_empty_mid() {
15701570
}
15711571
}
15721572

1573+
#[test]
1574+
fn test_align_to_mut_aliasing() {
1575+
let mut val = [1u8, 2, 3, 4, 5];
1576+
// `align_to_mut` used to create `mid` in a way that there was some intermediate
1577+
// incorrect aliasing, invalidating the resulting `mid` slice.
1578+
let (begin, mid, end) = unsafe { val.align_to_mut::<[u8; 2]>() };
1579+
assert!(begin.len() == 0);
1580+
assert!(end.len() == 1);
1581+
mid[0] = mid[1];
1582+
assert_eq!(val, [3, 4, 3, 4, 5])
1583+
}
1584+
15731585
#[test]
15741586
fn test_slice_partition_dedup_by() {
15751587
let mut slice: [i32; 9] = [1, -1, 2, 3, 1, -5, 5, -2, 2];

0 commit comments

Comments
 (0)