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
```
This commit is contained in:
commit
7112951caa
2 changed files with 44 additions and 20 deletions
|
|
@ -1327,11 +1327,14 @@ impl<T: ?Sized> Rc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Rc::into_raw`, the
|
||||
/// associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Rc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
|
||||
/// allocated by the global allocator.
|
||||
///
|
||||
/// [from_raw_in]: Rc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1360,12 +1363,15 @@ impl<T: ?Sized> Rc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Rc::into_raw`, the
|
||||
/// associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Rc::into_raw`and must satisfy the
|
||||
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) when invoking this method, and `ptr` must point to a block of memory
|
||||
/// allocated by the global allocator. This method can be used to release the final `Rc` and
|
||||
/// backing storage, but **should not** be called after the final `Rc` has been released.
|
||||
///
|
||||
/// [from_raw_in]: Rc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1623,10 +1629,13 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Rc::into_raw`, the
|
||||
/// associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Rc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
|
||||
/// allocated by `alloc`
|
||||
/// allocated by `alloc`.
|
||||
///
|
||||
/// [from_raw_in]: Rc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1665,11 +1674,14 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Rc::into_raw`, the
|
||||
/// associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Rc::into_raw`and must satisfy the
|
||||
/// same layout requirements specified in [`Rc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Rc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) when invoking this method, and `ptr` must point to a block of memory
|
||||
/// allocated by `alloc`. This method can be used to release the final `Rc` and backing storage,
|
||||
/// but **should not** be called after the final `Rc` has been released.
|
||||
/// allocated by `alloc`. This method can be used to release the final `Rc` and
|
||||
/// backing storage, but **should not** be called after the final `Rc` has been released.
|
||||
///
|
||||
/// [from_raw_in]: Rc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
|
|||
|
|
@ -1453,11 +1453,14 @@ impl<T: ?Sized> Arc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Arc::into_raw`, and the
|
||||
/// associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
|
||||
/// allocated by the global allocator.
|
||||
///
|
||||
/// [from_raw_in]: Arc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1488,13 +1491,16 @@ impl<T: ?Sized> Arc<T> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Arc::into_raw`, and the
|
||||
/// associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) when invoking this method, and `ptr` must point to a block of memory
|
||||
/// allocated by the global allocator. This method can be used to release the final
|
||||
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
|
||||
/// released.
|
||||
///
|
||||
/// [from_raw_in]: Arc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1806,11 +1812,14 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Arc::into_raw`, and the
|
||||
/// associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) for the duration of this method,, and `ptr` must point to a block of memory
|
||||
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) for the duration of this method, and `ptr` must point to a block of memory
|
||||
/// allocated by `alloc`.
|
||||
///
|
||||
/// [from_raw_in]: Arc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
@ -1850,13 +1859,16 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
|
|||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The pointer must have been obtained through `Arc::into_raw`, the
|
||||
/// associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// The pointer must have been obtained through `Arc::into_raw` and must satisfy the
|
||||
/// same layout requirements specified in [`Arc::from_raw_in`][from_raw_in].
|
||||
/// The associated `Arc` instance must be valid (i.e. the strong count must be at
|
||||
/// least 1) when invoking this method, and `ptr` must point to a block of memory
|
||||
/// allocated by `alloc`. This method can be used to release the final
|
||||
/// `Arc` and backing storage, but **should not** be called after the final `Arc` has been
|
||||
/// released.
|
||||
///
|
||||
/// [from_raw_in]: Arc::from_raw_in
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue