Skip to content

Commit 7112951

Browse files
authored
Rollup merge of #138303 - DiuDiu777:rc-fix, r=Mark-Simulacrum
Fix Ptr inconsistency in {Rc,Arc} ### PR Description This pr aims to address the problem discussed on [zulip](https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/Inconsistency.20in.20.7BRc.2CArc.7D's.20ptr.20requirements/with/504259637). ### Problem Clarification As this post presents, the `{Rc, Arc}::{in/de-crement_strong_count_/in}` do not limit the layout of the memory that `ptr` points to, while internally `Rc::from_raw_in` is called directly. UB doesn't just appear when the strong count is decremented to zero. Miri also detects the UB of `out-of-bounds pointer use` when increment strong count is called on a pointer with an incorrect layout(shown as below). ```rust use std::rc::Rc; #[repr(align(8))] struct Aligned8(u64); #[repr(align(16))] struct Aligned16(u64); fn main() { let rc: Rc<Aligned8> = Rc::new(Aligned8(42)); let raw_ptr = Rc::into_raw(rc); unsafe { Rc::increment_strong_count(raw_ptr as *const Aligned16); } } ``` Miri output: ``` error: Undefined Behavior: out-of-bounds pointer use: expected a pointer to 32 bytes of memory, but got alloc954 which is only 24 bytes from the end of the allocation ```
2 parents 8210b84 + fa183ad commit 7112951

File tree

2 files changed

+44
-20
lines changed

2 files changed

+44
-20
lines changed

library/alloc/src/rc.rs

+23-11
Original file line numberDiff line numberDiff line change
@@ -1327,11 +1327,14 @@ impl<T: ?Sized> Rc<T> {
13271327
///
13281328
/// # Safety
13291329
///
1330-
/// The pointer must have been obtained through `Rc::into_raw`, the
1331-
/// associated `Rc` instance must be valid (i.e. the strong count must be at
1330+
/// The pointer must have been obtained through `Rc::into_raw` and must satisfy the
1331+
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
1332+
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
13321333
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
13331334
/// allocated by the global allocator.
13341335
///
1336+
/// [from_raw_in]: Rc::from_raw_in
1337+
///
13351338
/// # Examples
13361339
///
13371340
/// ```
@@ -1360,12 +1363,15 @@ impl<T: ?Sized> Rc<T> {
13601363
///
13611364
/// # Safety
13621365
///
1363-
/// The pointer must have been obtained through `Rc::into_raw`, the
1364-
/// associated `Rc` instance must be valid (i.e. the strong count must be at
1366+
/// The pointer must have been obtained through `Rc::into_raw`and must satisfy the
1367+
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
1368+
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
13651369
/// least 1) when invoking this method, and `ptr` must point to a block of memory
13661370
/// allocated by the global allocator. This method can be used to release the final `Rc` and
13671371
/// backing storage, but **should not** be called after the final `Rc` has been released.
13681372
///
1373+
/// [from_raw_in]: Rc::from_raw_in
1374+
///
13691375
/// # Examples
13701376
///
13711377
/// ```
@@ -1623,10 +1629,13 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
16231629
///
16241630
/// # Safety
16251631
///
1626-
/// The pointer must have been obtained through `Rc::into_raw`, the
1627-
/// associated `Rc` instance must be valid (i.e. the strong count must be at
1632+
/// The pointer must have been obtained through `Rc::into_raw` and must satisfy the
1633+
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
1634+
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
16281635
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
1629-
/// allocated by `alloc`
1636+
/// allocated by `alloc`.
1637+
///
1638+
/// [from_raw_in]: Rc::from_raw_in
16301639
///
16311640
/// # Examples
16321641
///
@@ -1665,11 +1674,14 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
16651674
///
16661675
/// # Safety
16671676
///
1668-
/// The pointer must have been obtained through `Rc::into_raw`, the
1669-
/// associated `Rc` instance must be valid (i.e. the strong count must be at
1677+
/// The pointer must have been obtained through `Rc::into_raw`and must satisfy the
1678+
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
1679+
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
16701680
/// least 1) when invoking this method, and `ptr` must point to a block of memory
1671-
/// allocated by `alloc`. This method can be used to release the final `Rc` and backing storage,
1672-
/// but **should not** be called after the final `Rc` has been released.
1681+
/// allocated by `alloc`. This method can be used to release the final `Rc` and
1682+
/// backing storage, but **should not** be called after the final `Rc` has been released.
1683+
///
1684+
/// [from_raw_in]: Rc::from_raw_in
16731685
///
16741686
/// # Examples
16751687
///

library/alloc/src/sync.rs

+21-9
Original file line numberDiff line numberDiff line change
@@ -1453,11 +1453,14 @@ impl<T: ?Sized> Arc<T> {
14531453
///
14541454
/// # Safety
14551455
///
1456-
/// The pointer must have been obtained through `Arc::into_raw`, and the
1457-
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1456+
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
1457+
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
1458+
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
14581459
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
14591460
/// allocated by the global allocator.
14601461
///
1462+
/// [from_raw_in]: Arc::from_raw_in
1463+
///
14611464
/// # Examples
14621465
///
14631466
/// ```
@@ -1488,13 +1491,16 @@ impl<T: ?Sized> Arc<T> {
14881491
///
14891492
/// # Safety
14901493
///
1491-
/// The pointer must have been obtained through `Arc::into_raw`, and the
1492-
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1494+
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
1495+
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
1496+
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
14931497
/// least 1) when invoking this method, and `ptr` must point to a block of memory
14941498
/// allocated by the global allocator. This method can be used to release the final
14951499
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
14961500
/// released.
14971501
///
1502+
/// [from_raw_in]: Arc::from_raw_in
1503+
///
14981504
/// # Examples
14991505
///
15001506
/// ```
@@ -1806,11 +1812,14 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
18061812
///
18071813
/// # Safety
18081814
///
1809-
/// The pointer must have been obtained through `Arc::into_raw`, and the
1810-
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1811-
/// least 1) for the duration of this method,, and `ptr` must point to a block of memory
1815+
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
1816+
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
1817+
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
1818+
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
18121819
/// allocated by `alloc`.
18131820
///
1821+
/// [from_raw_in]: Arc::from_raw_in
1822+
///
18141823
/// # Examples
18151824
///
18161825
/// ```
@@ -1850,13 +1859,16 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
18501859
///
18511860
/// # Safety
18521861
///
1853-
/// The pointer must have been obtained through `Arc::into_raw`, the
1854-
/// associated `Arc` instance must be valid (i.e. the strong count must be at
1862+
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
1863+
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
1864+
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
18551865
/// least 1) when invoking this method, and `ptr` must point to a block of memory
18561866
/// allocated by `alloc`. This method can be used to release the final
18571867
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
18581868
/// released.
18591869
///
1870+
/// [from_raw_in]: Arc::from_raw_in
1871+
///
18601872
/// # Examples
18611873
///
18621874
/// ```

0 commit comments

Comments
 (0)