You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think we should organize a kind of "canvas" to find examples of how unsafe code is used in the wild. To start, it'd be great to enumerate a list of interesting places to look.
Here is my start at a list. Further nominations welcome. I'll try to keep the list up to date. Moreover, if you feel you've examined the source, open any relate issues and we can check it off.
Well, I think pcb would be a nice place to start, it's very simple and has some unsafe code that would be seen as UB by the "correct lifetime" style. (example)
This discussion of how coroutines and scoped threads interact seems relevant, probably more as a negative case (i.e., enumerate where the coroutine abstractions goes wrong):
This discussion of how coroutines and scoped threads interact seems relevant, probably more as a negative case (i.e., enumerate where the coroutine abstractions goes wrong):
That is more of a soundness issue than a memory model issue. scoped assumes that stack frames never leak - that a lifetime parameter passed to a function must live until the function exits (through a return or resume), while coroutines flat out violates that assumption.
I don't entirely understand what is the criterion for listing pieces of the standard library. Certainly RefCell is a very interesting bit of unsafe code, showing how far interior mutability can go and playing games with lifetimes that I have not yet seen in any other piece of unsafe code.
The problem with RefCell is that we aren't sure that its implementation won't invoke Undefined Behavior in a future model for what defines undefined behavior in unsafe rust. The fact that it holds a &'a reference which isn't actually valid for all of &'a, but only for either the lifetime of the Ref or RefMut, or 'a, whichever is shorter. This could be considered UB under some models as the lifetimes are "incorrect".
We aren't suggesting removing RefCell, it's just a question of whether its current implementation should be UB.
@mystor@RalfJung I think the only reason I did not list RefCell is that we have #5 already. My goal with this issue is not for it to exist permanently, just to serve as a clearing house of work to be done in terms of researching and then opening issues.
Notice that the trouble I am having with RefCell in my semantic model is entirely unrelated to #5. However, I am not sure if the memory model would be affected by that...
Just stating the obvious : There are going to be many situations where the only unsafe code consists of calls to std::mem::transmute<X,Y> where X is a packed C struct and Y is [u8; std::mem::size_of<X>] or vice versa. It sounds unfortunate to disable optimizations for that if X does not contain pointers.
The get_unchecked examples at rust-lang/rust#36976 are convincing me that we do not want to UB on just creating a reference to an invalid value, or even returning such a reference from a function. This would naturally make references to Void be well-defined too (through horribly unsafe).
BTW, even if invalid values are ignored, my aliasing memory models could end up with the result of an out-of-range [T]::get_unchecked not having a capability to access the out-of-range memory (because they are limited to the capability of the &[T] - i.e. only to the length of it).
I implement struct RevSlice<T>([T]) which is a reversed view of a slice. I'm unsure what's needed to put it on sound ground, specifically the conversions:
bytecount (used by ripgrep&xi) has one line of unsafe to transmute aligned byte slices to usize/SIMD slices. This pattern might perhaps be factored out into its own crate, or perhaps even find a place in libstd.
I imagine that's something like split_aligned_for but even that formulation leaves much to be desired, slice iteratorish formulation seems to codegen much better (hence the other experiments there in the same junkyard and in rawslice).
I'm not sure what this issue is supposed to achieve that downloading and grepping crates.io or searching for "unsafe" in Rust code on Github would not. But here are some bugs in unsafe code found in the wild, w/ short analysis. More of them here: https://rustsec.org/advisories/
inflate crate: unsafe code due to missing safe abstraction (no way to append contents of vector to itself), I've opened an RFC to provide one. Vulnerable, simplified example here. This is actually a recurring bug in DEFLATE decoders, another one with a different implementation also has this exact bug (pending disclosure atm).
Activity
[-]Unsafe code in the wild[/-][+]Canvas unsafe code in the wild[/+]strega-nil commentedon Sep 2, 2016
Well, I think pcb would be a nice place to start, it's very simple and has some unsafe code that would be seen as UB by the "correct lifetime" style. (example)
nikomatsakis commentedon Sep 3, 2016
@ubsan do you think that the "interesting patterns" in pcb are thus summarized by #12? If not, maybe you can write-up an issue that covers them?
strega-nil commentedon Sep 3, 2016
I think they're well enough summarized. (see here) referencing pcb
eternaleye commentedon Sep 8, 2016
Another use of unsafe code, this one more type-focused than lifetime-focused: https://github.com/Diggsey/query_interface
Ericson2314 commentedon Sep 8, 2016
https://github.com/nathan7/libfringe is wildly unsafe.
nikomatsakis commentedon Sep 8, 2016
This discussion of how coroutines and scoped threads interact seems relevant, probably more as a negative case (i.e., enumerate where the coroutine abstractions goes wrong):
https://www.reddit.com/r/rust/comments/508pkb/unleakable_crate_safetysanityrefocus/d72703d
arielb1 commentedon Sep 8, 2016
That is more of a soundness issue than a memory model issue.
scopedassumes that stack frames never leak - that a lifetime parameter passed to a function must live until the function exits (through areturnorresume), whilecoroutinesflat out violates that assumption.RalfJung commentedon Sep 12, 2016
I don't entirely understand what is the criterion for listing pieces of the standard library. Certainly
RefCellis a very interesting bit of unsafe code, showing how far interior mutability can go and playing games with lifetimes that I have not yet seen in any other piece of unsafe code.mystor commentedon Sep 12, 2016
The problem with
RefCellis that we aren't sure that its implementation won't invoke Undefined Behavior in a future model for what defines undefined behavior in unsafe rust. The fact that it holds a &'a reference which isn't actually valid for all of &'a, but only for either the lifetime of theReforRefMut, or'a, whichever is shorter. This could be considered UB under some models as the lifetimes are "incorrect".We aren't suggesting removing
RefCell, it's just a question of whether its current implementation should be UB.RalfJung commentedon Sep 12, 2016
What I am asking is why
RefCellis not listed above as "how unsafe code is used in the wild".nikomatsakis commentedon Sep 12, 2016
@mystor @RalfJung I think the only reason I did not list RefCell is that we have #5 already. My goal with this issue is not for it to exist permanently, just to serve as a clearing house of work to be done in terms of researching and then opening issues.
RalfJung commentedon Sep 12, 2016
I see, that makes sense.
Notice that the trouble I am having with
RefCellin my semantic model is entirely unrelated to #5. However, I am not sure if the memory model would be affected by that...arielb1 commentedon Sep 12, 2016
What's the trouble again?
nikomatsakis commentedon Sep 12, 2016
@RalfJung if you see some other aspect of ref-cell that's not documented, please do open another issue...
14 remaining items
mystor commentedon Oct 5, 2016
@ubsan Yup, that's actually almost exactly what I'm doing.
And yes, I agree that it's a hack to get around
()not being C compatible. I think we should probably fix that.burdges commentedon Oct 5, 2016
Just stating the obvious : There are going to be many situations where the only unsafe code consists of calls to
std::mem::transmute<X,Y>whereXis a packed C struct andYis[u8; std::mem::size_of<X>]or vice versa. It sounds unfortunate to disable optimizations for that if X does not contain pointers.arielb1 commentedon Oct 5, 2016
The
get_uncheckedexamples at rust-lang/rust#36976 are convincing me that we do not want to UB on just creating a reference to an invalid value, or even returning such a reference from a function. This would naturally make references toVoidbe well-defined too (through horribly unsafe).arielb1 commentedon Oct 5, 2016
BTW, even if invalid values are ignored, my aliasing memory models could end up with the result of an out-of-range
[T]::get_uncheckednot having a capability to access the out-of-range memory (because they are limited to the capability of the&[T]- i.e. only to the length of it).bluss commentedon Jan 21, 2017
I implement
struct RevSlice<T>([T])which is a reversed view of a slice. I'm unsure what's needed to put it on sound ground, specifically the conversions:&[T] -> &RevSlice<T>&mut [T] -> &mut RevSlice<T>Box<[T]> -> Box<RevSlice<T>>Amanieu commentedon Jan 21, 2017
@bluss I think this is a good case for
#[repr(transparent)]bluss commentedon Jan 22, 2017
Another crate:
linked-hash-mapuses the same kind of reference to newtype wrapper.llogiq commentedon Mar 16, 2017
bytecount (used by ripgrep&xi) has one line of unsafe to transmute aligned byte slices to usize/SIMD slices. This pattern might perhaps be factored out into its own crate, or perhaps even find a place in libstd.
Manishearth commentedon Mar 16, 2017
Can't byteorder do that?
bluss commentedon Mar 17, 2017
byteorder does not deal with slice conversions.
I imagine that's something like split_aligned_for but even that formulation leaves much to be desired, slice iteratorish formulation seems to codegen much better (hence the other experiments there in the same junkyard and in rawslice).
Shnatsel commentedon Jun 23, 2019
I'm not sure what this issue is supposed to achieve that downloading and grepping crates.io or searching for "unsafe" in Rust code on Github would not. But here are some bugs in unsafe code found in the wild, w/ short analysis. More of them here: https://rustsec.org/advisories/
Interesting or Rust-specific bugs:
SmallVec::insert_manyis unsound smallvec/smallvec#96 - double free if iterator over non-Copy type panics. Fixed via "set length on drop" trick.inflatecrate: unsafe code due to missing safe abstraction (no way to append contents of vector to itself), I've opened an RFC to provide one. Vulnerable, simplified example here. This is actually a recurring bug in DEFLATE decoders, another one with a different implementation also has this exact bug (pending disclosure atm).Boring but serious bugs:
u64::to_le_bytesis stabilized theunsafeis no longer needed. There is also precedent for the reverse pattern withfrom_le_bytesandTryInto. Safe versions are exactly as fast as the unsafe ones.JakobDegen commentedon Apr 25, 2023
Discussed in backlog bonanza: Not so sure this issue is providing much value and the discussion here is quite old. Closing