# Writing through a pointer derived from a shared reference, after that reference is dead

**URL:** <https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078>\
**Category:** Unsafe Code Guidelines\
**Created:** [December 21, 2018, 3:43pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078 "2018-12-21T15:43:17Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [December 21, 2018, 3:43pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/1 "2018-12-21T15:43:17Z")

</div>

Using Miri, I found an interesting violation of my latest Stacked Borrows rules in the `bytes` crate:

```rust
impl Inner {
    /// Pointer to the start of the inline buffer
    unsafe fn inline_ptr(&self) -> *mut u8 {
        (self as *const Inner as *mut Inner as *mut u8)
            .offset(INLINE_DATA_OFFSET)
    }

    /// Return a mutable slice for the handle's view into the shared buffer
    /// including potentially uninitialized bytes.    
    unsafe fn as_raw(&mut self) -> &mut [u8] {
        debug_assert!(!self.is_static());
        if self.is_inline() {
            slice::from_raw_parts_mut(self.inline_ptr(), INLINE_CAP)
        } else {
            slice::from_raw_parts_mut(self.ptr, self.cap)
        }
    }
}

// Elsewhere
                let mut inner: Inner = mem::uninitialized();
                // Set inline mask
                inner.arc = AtomicPtr::new(KIND_INLINE as *mut Shared);
                inner.set_inline_len(len);
                inner.as_raw()[0..len].copy_from_slice(src);

```

What happens here is that `Inner::inline_ptr` takes a shared reference. It turns that into a `*mut`, which then is then returned to `Inner::as_raw`. That one creates an `&mut`, and then writes into it using `copy_from_slice`.

IOW, this function writes into a pointer that was created from a shared reference. Miri flags this as violation of the aliasing rules. The fix is to make `inline_ptr` take `&mut`.

What makes this interesting is that my usual answer for “what is interior mutability” has been “writing to a location where a live shared reference to the same location exists”, but that is not the case here: The `&self` is long dead by the time the write happens. What happens here, instead, is that creating a raw pointer from a shared reference makes the location _readable_ but not _writeable_ with raw pointers.

What do y’all think, who is right – Miri or the code? I think what Miri does makes sense here, but I could also imagine tweaks to the model that allow this code. But do we want to allow it?

Cc @carllerche

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [December 21, 2018, 4:36pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/2 "2018-12-21T16:36:10Z")

</div>

In fact, this is just another instance of the `NonNull` issue that I [worked around](https://github.com/rust-lang/rust/pull/56161), but that is really a deeper [issue with our coercions](https://github.com/rust-lang/rust/issues/56604).

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [December 22, 2018, 7:09pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/3 "2018-12-22T19:09:24Z")

</div>

Hmm, that’s a tough one. One one hand I’d prefer analysis that’s closer to checking whether it’s _actually_ unsafe, rather than theoretically unsafe.

OTOH that unsafe function uses a “safe” Rust type, so it’s not too weird to require sticking to safe Rust semantics for “safe” types.

What would the fix look like if `&mut self` wasn’t possible? (e.g. because it was in a `&self`-taking function, similar to `RefCell::borrow_mut()`) Should it take `*const Self`?

---

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [December 23, 2018, 3:55am UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/4 "2018-12-23T03:55:23Z")

</div>

I think miri is actually correct here. If user want to write bytes through this pointer, i think it’s reasonable for asking the code to prove that it “has the write permission for writing” at one point. Providing a `inline_ptr` returning `* const` and an `inline_ptr_mut` taking `&mut` seems reasonable.

However i think we’ve not raised this requirement (formally) before.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [December 26, 2018, 3:38pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/5 "2018-12-26T15:38:29Z")

</div>

> [@kornel](#):
>
> One one hand I’d prefer analysis that’s closer to checking whether it’s _actually_ unsafe, rather than theoretically unsafe.

I don't understand the distinction you are making here. This effort is about _defining_ what is actually unsafe and what is not.

> [@kornel](#):
>
> What would the fix look like if `&mut self` wasn’t possible? (e.g. because it was in a `&self` -taking function, similar to `RefCell::borrow_mut()` ) Should it take `*const Self` ?

In that case you'd have to use `UnsafeCell`, which is what `RefCell` does.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [December 26, 2018, 4:34pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/6 "2018-12-26T16:34:40Z")

</div>

> [@RalfJung](#):
>
> I don’t understand the distinction you are making here.

By "actually safe" (which now I see is a poor wording) I've meant when a piece of code happens to give the expected result on my machine with my particular version of the compiler, regardless of what theoretically could happen with other compiler, other optimizations, on other machine.

As a programmer, for my piece of mind, I'd prefer rules to be as close as possible to behavior of a simple, naive, non-optimizing implementation.

The gap of understanding between "pointer type casts do nothing, because they're all just the same integer" and "pointer casts have subtle implications for aliasing rules that affect surrounding code and can cause UB which allows the compiler to replace the whole code with nasal demons" is scary.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [December 27, 2018, 3:19pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/7 "2018-12-27T15:19:42Z")

</div>

> [@kornel](#):
>
> As a programmer, for my piece of mind, I’d prefer rules to be as close as possible to behavior of a simple, naive, non-optimizing implementation.

That's fair. However, unfortunately, the only way I know to make that true is to actually use a simple, naive, non-optimizing compiler. To realize the performance goals Rust is aspiring to hit, we need optimizations, and many of the interesting ones are inherently incompatible with a naive model.

> “pointer type casts do nothing, because they’re all just the same integer”

Note that [pointers are far from being just integers even if you ignore Stacked Borrows, and even in C](https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html).

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [March 27, 2019, 3:19pm UTC](https://internals.rust-lang.org/t/writing-through-a-pointer-derived-from-a-shared-reference-after-that-reference-is-dead/9078/8 "2019-03-27T15:19:44Z")

</div>

Closed on March 27, 2019, 3:19pm UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
