AtomStoreCell can create aliasing mutable references · Issue #8362 · swc-project/swc (original) (raw)

Describe the bug

The swc_atoms::AtomStoreCell::atom() function creates a &mut reference from *self.0.get(). The safety comment notes that "We can skip the borrow check of RefCell because this API enforces a safe contract." However, this is incorrect, since the function reenters user code to call .into(), and reenters it more times to allocate memory, and these can potentially call back into .atom(), creating a second &mut reference.

Input code

use std::borrow::Cow; use swc_atoms::AtomStoreCell;

struct EvilStr<'a>(&'a AtomStoreCell);

impl<'a> From<EvilStr<'a>> for Cow<'a, str> { fn from(value: EvilStr<'a>) -> Self { value.0.atom(Cow::Borrowed("reentered!")); Cow::Borrowed("evil") } }

fn main() { let cell = AtomStoreCell::default(); cell.atom(EvilStr(&cell)); }

Config

No response

https://play.swc.rs/?version=1.3.100&code=H4sIAAAAAAAAA12Pz26DMAyH73kKj0ObVP2zc9ohtWh9AR5gysCRkAKZjCmHinefQ5nUzpco9pd8Px82augReq6t%2FY5EcbS2iOPx0R2rL8ex7a09y1FyJCwwhKNSPdNQMXzemlAyndYu16u1gxfMCNe0PyFN4UqxPT3hOfhIICq5bMVPOdwVSPkOvLD65sKA9tlgYJdDicEvZKqZ2r%2FvU0xdpPSXeQusdUaIHSNh%2FZYZyfL35B%2BFIsjMPJ3UpJT4W9d02iyWgAyVbAMfr9tZW6N3Q2C9%2FJ2gR44ls16lVlJPanP4BaeOXFBqAQAA&config=H4sIAAAAAAAAA1WPSw7DIAwF9zkF8rrbdtE79BAWdSIifrKJVBTl7iUE0maH3xsz8jooBbNoeKq1PMsQkYX4nEsi2Sf8lARIOxTNJia49XaWvRrRCtVoOxpIyBOluiX3hoMNQajjLXPGmzH%2FC3VwkUnkCu4o%2BsnSVTc0JbjwXmrZDkk50qF%2FwA%2FqsvNjMPLqm4kXGrYvhlQioBQBAAA%3D

SWC Info output

No response

Expected behavior

The function should detect that it has been reentered and panic.

Actual behavior

The function creates aliasing &mut references when reentered. Miri reports the following error:

error: Undefined Behavior: not granting access to tag <1849> because that would remove [Unique for <1822>] which is strongly protected because it is an argument of call 791 --> /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/swc_atoms-0.6.4/src/lib.rs:229:21 | 229 | pub fn atom<'a>(&mut self, s: impl Into<Cow<'a, str>>) -> Atom { | ^^^^^^^^^ not granting access to tag <1849> because that would remove [Unique for <1822>] which is strongly protected because it is an argument of call 791 | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: <1849> was created by a SharedReadWrite retag at offsets [0x0..0x28] --> src/main.rs:8:9 | 8 | value.0.atom(Cow::Borrowed("reentered!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: <1822> is this argument --> src/main.rs:15:5 | 15 | cell.atom(EvilStr(&cell)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside swc_atoms::AtomStore::atom::<'_, std::borrow::Cow<'_, str>> at /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/swc_atoms-0.6.4/src/lib.rs:229:21: 229:30 = note: inside swc_atoms::AtomStoreCell::atom::<'_, std::borrow::Cow<'_, str>> at /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/swc_atoms-0.6.4/src/lib.rs:245:18: 245:41 note: inside <impl std::convert::From<EvilStr<'_>> for std::borrow::Cow<'_, str>>::from --> src/main.rs:8:9 | 8 | value.0.atom(Cow::Borrowed("reentered!")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: inside <EvilStr<'_> as std::convert::Into<std::borrow::Cow<'_, str>>>::into at /home/lm978/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:757:9: 757:22 = note: inside swc_atoms::hstr::AtomStore::atom::<'_, EvilStr<'_>> at /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/hstr-0.2.6/src/dynamic.rs:82:24: 82:35 = note: inside swc_atoms::AtomStore::atom::<'_, EvilStr<'_>> at /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/swc_atoms-0.6.4/src/lib.rs:230:14: 230:28 = note: inside swc_atoms::AtomStoreCell::atom::<'_, EvilStr<'_>> at /home/lm978/.cargo/registry/src/index.crates.io-6f17d22bba15001f/swc_atoms-0.6.4/src/lib.rs:245:18: 245:41 note: inside main --> src/main.rs:15:5 | 15 | cell.atom(EvilStr(&cell)); | ^^^^^^^^^^^^^^^^^^^^^^^^^

note: some details are omitted, run with MIRIFLAGS=-Zmiri-backtrace=full for a verbose backtrace

Version

swc_atoms 0.6.4

Additional context

My last issue, #8361, was automatically rejected for linking to the Rust Playground instead of the SWC Playground; it would be helpful if there were some upfront indication about the requirements for the provided link.