# Unsoundess overview In this doc I (@oli-obk) am analyzing all the soundness bugs that are open as of February 2022 and figuring out categories for them. ## Categories The categories that were found. The numbers behind them say how many issues are in each category. * MIR opts (2) * only on nightly, won't stabilize opts without fixing them * LLVM * miscompiles (12) :frowning: * AVR (4) low priority * Type System * general (11) * Stack (3) * Specialization (5) * Variance (4) * impl Trait (3) * Pin (3) * lifetimes (2) * libstd (7) not very abusable * FFI (9) ## Labels Explanations for some labels I added to the detailed categorization below. * needs-nightly :night_with_stars: * we can be as very breaking-changy as we want * not a high priority, blockers for stabilization of relevant feature * :warning: :rotating_light: :warning: * if the bug can occur easily * :warning: * if the bug is only exploitable if you want to exploit it * fixed by chalk :hammer: * some bugs can be solved by moving to chalk :hammer: * label is likely missing in some places ## All the bugs This section categorizes the bugs into broad categories and labels them with criticalities. https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-unsound * https://github.com/rust-lang/rust/issues/47949 * not even unsound? * just arbitrary value leaking when the user would expect a drop at the end of the scope * could cause library unsoundness ### MIR opts * https://github.com/rust-lang/rust/issues/79191 * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/77359 * needs nightly :night_with_stars: ### LLVM * https://github.com/rust-lang/rust/issues/52304 * fixed, needs test * https://github.com/rust-lang/rust/issues/92869 * LLVM patch merged upstream, waiting for integration into rustc * https://github.com/rust-lang/rust/issues/81408 * atomics in statics are miscompiled * :warning: :rotating_light: :warning: can potentially just happen by accident * not reported to LLVM yet, but a good minimal reproducer exists * https://github.com/rust-lang/rust/issues/80309 * fixed, just needs a test * https://github.com/rust-lang/rust/issues/79865 * fixed upstream, LLVM 14 * https://github.com/rust-lang/rust/issues/74551 * probably fixed, at least doesn't repro anymore, but need confirmation from firefox * https://github.com/rust-lang/rust/issues/72327 * floating point math is unsound with infinity * https://github.com/rust-lang/rust/issues/70143 * requires very large alignment types * https://github.com/rust-lang/rust/issues/70022 * requires very large alignment types (larger than page size) * https://github.com/rust-lang/rust/issues/67497 * optimizing for size on 32 bit windows * https://github.com/rust-lang/rust/issues/64609 * SIMD ABI is unsound with target-feature optimizations * https://github.com/rust-lang/rust/issues/55976 * unclear how to fix it #### AVR Not a Tier-1 target and very experimental anyway * https://github.com/rust-lang/rust/issues/79889 * LLVM fix merged, not in rustc yet * https://github.com/rust-lang/rust/issues/78260 * no fix suggested yet * https://github.com/rust-lang/rust/issues/78022 * has FIX PR, waiting on author * https://github.com/rust-lang/rust/issues/77541 * no fix suggested yet * https://github.com/rust-lang/rust/issues/74743 * no fix suggested yet ### Type system * [type_id collisions](https://github.com/rust-lang/rust/issues/10389) * basically hash collisions * solutions exist, need to try them out * weaponizeable * :warning: :rotating_light: :warning: just happens by accident, even if rarely * [`fn() -> Out` is a valid type for unsized types `Out`, and it implements `FnOnce<(), Output = Out>`](https://github.com/rust-lang/rust/issues/82633) * weaponization available * basically calls nonexistant method * PRs with fixes exist, not merged yet * [Accessing DST field of packed struct calculates the wrong field address](https://github.com/rust-lang/rust/issues/80925) * obvious bug, no way to use this feature sanely, so backwards compat breakage is not an issue * :warning: can potentially just happen by accident, but it's not usable sanely, so users will notice * [`negative_impls` and `optin_builtin_traits` nightly-features allow trait impls to overlap](https://github.com/rust-lang/rust/issues/74629) * needs nightly :night_with_stars: * [Coherence can be bypassed by an indirect impl for a trait object](https://github.com/rust-lang/rust/issues/57893) * weaponizeable * :warning: :rotating_light: :warning: can potentially just happen by accident * [Trait objects can call nonexistent concrete methods](https://github.com/rust-lang/rust/issues/50781) * fixed by chalk :hammer: * :warning: can potentially just happen by accident, but it's never going to work accidentally in any way that the user expected, so they'll notice * [Constants can contain references that are not Sync](https://github.com/rust-lang/rust/issues/49206) * can only cause library UB * requires user to understand said UB in order to abuse it * [unsoundness relating to WF requirements on trait object types](https://github.com/rust-lang/rust/issues/44454) * has fix PR with single-digit crater "regressions" * fixed by chalk :hammer: , too * [repr(packed) allows invalid unaligned loads](https://github.com/rust-lang/rust/issues/27060) * is now linted by a future incompat lint (very noisy), so considering this essentially fixed * [auto trait candidate selection is unsound](https://github.com/rust-lang/rust/issues/84857) * :white_frowning_face: requires breaking change to fix * very weaponizeable * :warning: can potentially just happen by accident in complex trait impls, but has a future incompat lint * [unsized_locals fails to uphold alignment requirements](https://github.com/rust-lang/rust/issues/71416) * needs nightly :night_with_stars: #### Large things on the stack * [Regressions with large (2-4GB) stack arrays on large stacks](https://github.com/rust-lang/rust/issues/83060) * large thread + fitting array does not work * works on stable * :warning: :rotating_light: :warning: can potentially just happen by accident * mitigation: prevent very large things on the stack * [Extend stack probe support to non-tier-1 platforms, and clarify policy for mitigating LLVM-dependent unsafety](https://github.com/rust-lang/rust/issues/43241) * tracking issue for fixing this for at least all tier 1 targets * [Investigate how LLVM deals with huge stack frames](https://github.com/rust-lang/rust/issues/18072) * LLVM is not good with large stacks * remedy: don't create large stacks (could lint non-statically known thread stack sizes or add some targetted asserts to libstd?) #### Specialization related * https://github.com/rust-lang/rust/issues/89948 * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/88901 * exploitable on stable * :warning: weaponizeable only by someone who understands invariance of mutable references enough to base the soundness of their library code on it. * https://github.com/rust-lang/rust/issues/79457 * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/45982 * specialization tracking issue * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/40582 * needs nightly :night_with_stars: #### Variance * https://github.com/rust-lang/rust/issues/84591 * probably duplicate of https://github.com/rust-lang/rust/issues/25860 * horribly horribly unsound and been around forever * :warning: :rotating_light: :warning: can potentially just happen by accident * https://github.com/rust-lang/rust/issues/84533 * probably dupe of 25860, too * https://github.com/rust-lang/rust/issues/80176 * probably duplicate of https://github.com/rust-lang/rust/issues/25860 * :warning: :rotating_light: :warning: can potentially just happen by accident * https://github.com/rust-lang/rust/issues/25860 * root issue of most variance issues * :warning: :rotating_light: :warning: can potentially just happen by accident #### impl trait * [Incoherent impls are still allowed on opaque types](https://github.com/rust-lang/rust/issues/86411) * need to forbid some syntax (probably should just write this as a WF-check for impl items?) * needs nightly :night_with_stars: * duplicate of https://github.com/rust-lang/rust/issues/84660 * [Type alias impl trait doesn’t properly enforce outlives relations.](https://github.com/rust-lang/rust/issues/84657) * defining use lifetimes can have constraints on them that the opaque does not have * needs nightly :night_with_stars: * [Opaque impl Trait return types unsoundly ignoring lifetime constraints](https://github.com/rust-lang/rust/issues/84305) * also exists for RPIT * possible avenues for fixing outlined in issue * fix is probably a breaking change * :warning: :rotating_light: :warning: can potentially just happen by accident #### Pin * [A `Pin` unsoundness involving an `impl DerefMut for Pin<&dyn LocalTrait>`](https://github.com/rust-lang/rust/issues/85099) * libstd workaround suggested * very weaponizeable * :warning: :rotating_light: :warning: can potentially just happen by accident in complex async code * [ `Pin` is unsound due to transitive effects of `CoerceUnsized`](https://github.com/rust-lang/rust/issues/68015) * requires nightly :night_with_stars: * [Resolve unsound interaction between noalias and self-referential data (incl. generators, async fn)](https://github.com/rust-lang/rust/issues/63818) * :warning: can potentially just happen by accident with `async`, but unclear how to exploit * miri detects it, so it isn't purely an LLVM issue #### Lifetimes * ['static closures with non-'static return type are unsound](https://github.com/rust-lang/rust/issues/84366) * has a [partial FIX PR](https://github.com/rust-lang/rust/pull/84385), but no changes since May 2021 * seems fixable, but may be a breaking change * :warning: :rotating_light: :warning: can potentially just happen by accident * [Keeping references to #[thread_local] statics is allowed across yields.](https://github.com/rust-lang/rust/issues/49682) * thread locals borrows live across generator yields * requires nightly :night_with_stars: ### libstd * https://github.com/rust-lang/rust/issues/64718 * libstd bug around unix locks * https://github.com/rust-lang/rust/issues/63787 * refcell should use pointers internally instead of references * miri detects this * https://github.com/rust-lang/rust/issues/60076 * miri detects this * https://github.com/rust-lang/rust/issues/55005 * Arc drop code, potentially LLVM bug? * only hypothetical problem in practice, no weaponization found * https://github.com/rust-lang/rust/issues/85434 * T-libs is removing all POSIX synchronization primitives from libstd and moving to something that matches Rust's soundness rules * https://github.com/rust-lang/rust/issues/27970 * accessing environment variables is unsound if C code on another thread also accesses it * https://github.com/rust-lang/rust/issues/81357 * windows `File` can be used unsoundly from safe code * T-libs accepted fix a year ago, but no impl since * https://github.com/rust-lang/rust/issues/95269 * found by miri * vec vs allocator APIs ### FFI * https://github.com/rust-lang/rust/issues/83994 * many C++ libraries incorrectly use `atexit` and can thus not be used from Rust soundly at all. * mitigation strategy: make sure all threads but the current one are joined before calling `exit`. * https://github.com/rust-lang/rust/issues/83116 * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/81996 * only on msvc * people have strong conflicting opinions on thread * needs analysis of real world use cases, probably just change things and crater them? * crater needs windows/msvc * https://github.com/rust-lang/rust/issues/80127 * C FFI with #[align(16)] structs * fix PR is not sufficient and has no activity, needs someone knowledgeable about ABIs to work on it * :warning: :rotating_light: :warning: can just happen by accident * https://github.com/rust-lang/rust/issues/53346 * repr simd is unsound * needs nightly :night_with_stars: * https://github.com/rust-lang/rust/issues/52652 * unwinding across FFI is unsound * can easily happen to devs that don't take care * The mitigation for this issue is to create a lint that triggers when you call Rust code that can possibly panic without catching it. This is a very expensive computation-wise, but straight forward to implement lint. Basically we create a queue of `ty::Instance`s and insert the current function into it. Until the queue is empty: take an element out, check if its MIR has any panics, if so, lint and stop. Otherwise, grab the instance of all function calls in the MIR and add them to the queue. * https://github.com/rust-lang/rust/issues/46188 * possibly LLVM miscompile * workaround: "don't manually bind to extern C functions and muck up the argument types" * https://github.com/rust-lang/rust/issues/28179 * `no_mangle` should be unsafe * remedy: include `no_mangle` in any `unsafe` reviews * already mentioned by the unsafe_code lint * https://github.com/rust-lang/rust/issues/76507 * link_section attribute is unsound on some targets * solution: make link_section unsafe to use, seems hard otherwise ## Proposals ### automatically track unsound issues We should probably have something that notifies a team when an issue is tagged with I-unsound so we can add it to our overview here and potentially perform or deploy remidies. ### chalk and Polonius Various issues here seem nearly impossible to fix without chalk or at least significantly easier to fix. Polonius will make it easier for us to reason about lifetimes. Instead of complicating the current system with complex fixes, migration to polonius is likely cheaper. Especially if we're going to migrate to polonius at some point *anyway* ### lint unsoundness hazards Instead of hard erroring (breaking change, possibly with false positives) on things that are potentially unsound, we could add new lints that users can opt-into. For things that polonius and chalk would catch we can add a (stable) way to opt-in to running chalk & polonius in *addition* to the current systems. Something like `-Wextra` :rolling_on_the_floor_laughing: that turns on chalk & polonius (opt in due to the slowdown) and then reports lints instead of errors on the things chalk & polonius find. This is forward compatible with merging chalk & polonius at some point, as the lint can stay and do nothing until we come up with the next migration or additional (possibly expensive) checks. ### LLVM LLVM is the largest offender here. Considering the amount of work necessary and the fact that new LLVM bugs pop up regularly, it seems best to have someone just working on these full time. As for detecting them without waiting for people to report crashes: * miri-like tool that interprets LLVM IR and does lots of runtime checks, then run on all tests on crater * fuzz our codegen backend by generating and executing programs that only use safe code (using our test suite as fuzzer starting points, as these tests are small) ### FFI * more clippy lints requiring the user to dismiss the clippy lint by forcing them to leave a comment * move away from inherently broken C++ libraries (they often don't even follow the C++ standard, it just works by accident if no Rust is involved) ### miri miri seems to detect a not-insignificant amount of these unsoundness issues, but only if they show up in tests. We should consider creating a symbolic executor that can evaluate functions without knowing their arguments (and run it on all public functions of crates we want to check). Instead we'll generate SAT solver expressions and give them to a SAT solver to munch on. It is unclear how much code such a symbolic executor could share with miri. ### type-system fuzzer Generate "obviously wrong" programs and see if they compile. This basically means that we try to make a safe `fn transmute<T, U>(t: T) -> U` compile by fuzzing its body. As a proof of concept we can see if we can make it generate the equivalent of the known weaponizations of this kind. ### very magical far future * formally verify the Rust compiler (not practical) * rewrite the Rust compiler in coq * move to a much stricter but simpler language that was designed from the start for formal verification and writing compilers * wait for the singularity :laughing: and let someone objectively smarter than all of us (true AI) write all code and hope we treated them well enough so they don't turn us into batteries (transmute::<:person_frowning:, :battery:>).