{"id":"GHSA-p75v-367r-2v23","summary":"`cell-project` used incorrect variance when projecting through `&Cell\u003cT\u003e`","details":"## Overview\n\nThe issue lies in the implementation of the `cell_project` macro which used `field as *const _` instead of `field as *mut _`.\nThe problem being that `*const T` is covariant in `T` while `*mut T` is invariant in `T`. Keep in mind that `&Cell\u003cT\u003e` is invariant in `T`,\nso casting to `*const T` relaxed the variance, and lead to unsoundness, as shown in the example below.\n\n```rs\nuse std::cell::Cell;\nuse cell_project::cell_project as cp;\n\nstruct Foo\u003c'a\u003e {\n    x: Option\u003c&'a Cell\u003cFoo\u003c'a\u003e\u003e\u003e,\n}\n\nimpl\u003c'a\u003e Drop for Foo\u003c'a\u003e {\n    fn drop(&mut self) {\n        // `ourselves` is an &Cell\u003cSelf\u003e.\n        // NB: `Drop` is unsound.\n        if let Some(ourselves) = self.x.as_ref() {\n            // replace `self` (but this doesn't actually replace `self`)\n            let is_x_none = ourselves.replace(Foo {\n                x: None,\n            }).x.as_ref().is_none();\n            // if we just moved out of `self`, and we had a `Some` originally,\n            // how come this is a `None`?\n            if is_x_none {\n                println!(\"how did we get a None?\");\n            }\n        }\n    }\n}\n\nfn main() {\n    let foo = Cell::new(Foo {\n        x: None,\n    });\n    let x = cp!(Foo\u003c'_\u003e, foo.x);\n    x.set(Some(&foo));\n}\n```\n\n### MIRI error\n\n```rs\n$ cargo +nightly miri run\n    Finished dev [unoptimized + debuginfo] target(s) in 0.01s\n     Running `\u003csnip\u003e`\nerror: Undefined Behavior: not granting access to tag \u003cuntagged\u003e because incompatible item is protected: [Unique for \u003c2472\u003e (call 796)]\n   --\u003e $RUST_STD_PATH/src/rust/library/core/src/cell.rs:404:31\n    |\n404 |         mem::replace(unsafe { &mut *self.value.get() }, val)\n    |                               ^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag \u003cuntagged\u003e because incompatible item is protected: [Unique for \u003c2472\u003e (call 796)]\n    |\n    = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental\n    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information\n\n    = note: inside `std::cell::Cell::\u003cFoo\u003e::replace` at $RUST_STD_PATH/src/rust/library/core/src/cell.rs:404:31\nnote: inside `\u003cFoo as std::ops::Drop\u003e::drop` at src/main.rs:14:29\n   --\u003e src/main.rs:14:29\n    |\n14  |               let is_x_none = ourselves.replace(Foo {\n    |  _____________________________^\n15  | |                 x: None,\n16  | |             }).x.as_ref().is_none();\n    | |______________^\n    = note: inside `std::ptr::drop_in_place::\u003cFoo\u003e - shim(Some(Foo))` at $RUST_STD_PATH/src/rust/library/core/src/ptr/mod.rs:486:1\n    = note: inside `std::ptr::drop_in_place::\u003cstd::cell::UnsafeCell\u003cFoo\u003e\u003e - shim(Some(std::cell::UnsafeCell\u003cFoo\u003e))` at $RUST_STD_PATH/src/rust/library/core/src/ptr/mod.rs:486:1\n    = note: inside `std::ptr::drop_in_place::\u003cstd::cell::Cell\u003cFoo\u003e\u003e - shim(Some(std::cell::Cell\u003cFoo\u003e))` at $RUST_STD_PATH/src/rust/library/core/src/ptr/mod.rs:486:1\nnote: inside `main` at src/main.rs:32:1\n   --\u003e src/main.rs:32:1\n    |\n32  | }\n    | ^\n\nnote: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace\n\nerror: aborting due to previous error\n```\n\n## Affected Versions\n\nAll versions of the cell-project crate before `0.1.4` are affected.\n\n## Mitigation\n\nThis was fixed in [Issues/4], and released as version `0.1.4`.\nSo just updating to the latest version will include the fix (which may result in a compile error on unsound usage).\n\n## Acknowledgements\n\nThis was discovered and fixed by @SoniEx2 in cell-project: [Issues/3] and [Issues/4]\n\n[issues/3]: https://github.com/RustyYato/cell-project/issues/3\n[issues/4]: https://github.com/RustyYato/cell-project/issues/4\n","aliases":["RUSTSEC-2020-0164"],"modified":"2023-11-08T04:21:30.551400Z","published":"2022-09-16T21:08:19Z","database_specific":{"cwe_ids":[],"github_reviewed":true,"nvd_published_at":null,"github_reviewed_at":"2022-09-16T21:08:19Z","severity":"MODERATE"},"references":[{"type":"WEB","url":"https://github.com/RustyYato/cell-project/issues/3"},{"type":"WEB","url":"https://github.com/RustyYato/cell-project/pull/4"},{"type":"PACKAGE","url":"https://github.com/RustyYato/cell-project"},{"type":"WEB","url":"https://rustsec.org/advisories/RUSTSEC-2020-0164.html"}],"affected":[{"package":{"name":"cell-project","ecosystem":"crates.io","purl":"pkg:cargo/cell-project"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.1.4"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2022/09/GHSA-p75v-367r-2v23/GHSA-p75v-367r-2v23.json"}}],"schema_version":"1.7.3"}