Closed eddyb closed 6 years ago
Hmm, this is pretty subtle...
I'd be suspicious of any case that uses Lazy
directly since it's really meant to be an implementation detail that's only leaked out of necessity.
Still, I think we should patch out the soundness hole if we can.
A crater run is possible for this. Is #103 the branch with the change?
@pietroalbini Sounds good! We haven't got a branch with the change just yet, should we give you a ping when there is one ready?
@KodrAus yes, thanks!
@KodrAus Are you working on this, or should I open a PR?
I'll work on this and include it with #103.
@pietroalbini Alrighty, we've got a patch ready now in https://github.com/rust-lang-nursery/lazy-static.rs/commit/0463a90b433d12db6a0e8f2087b2bd9d1afe9c48
Friendly ping @pietroalbini Do you think the release team will have some bandwidth for a crater run on our lazy_static
patch?
Uh, woops! Totally forgot about this!
Crater run started, it should be finished in a bit more than a day.
No worries :) Thanks again @pietroalbini
Hi @KodrAus (crater requester)! Crater results are at: https://cargobomb-reports.s3.amazonaws.com/lazy_static-1/index.html. 'Blacklisted' crates (spurious failures etc) can be found here. If you see any spurious failures not on the list, please make a PR against that file.
(interested observers: Crater is a tool for testing the impact of changes on parts of the Rust ecosystem. You can find out more at the repo if you're curious)
In other news, no regressions :tada::tada:
Thanks @pietroalbini! I appreciate your effort executing and examining the crater run :heart:
Can we close this? #103 made the fields of Lazy
private for both the inline & heap impls. The core/no_std impl already made use of const_fn to avoid having public fields, so there's no soundness issue to resolve there.
While normally only used within the
lazy_static
macro, the type and its fields need to be public, at least for the oldmacro_rules
macros. This poses both a safety (the fields are used in unsafe ways) and stability hazard (changing implementation details is technically breaking).Because
Lazy::get
takes&'static mut self
, it's hard to abuse (static mut
itself is unsafe, so it doesn't really count here), butBox::leak
does let you create a&'static mut
at runtime, so you could, in theory, leak aLazy<T>
, trigger thecall_once
manually, then callLazy::get
, which will return an invalid reference to aT
(since no actual initialization occurred).To construct a
Lazy<T>
to initialize the static in the macro, you can use associated consts (since 1.20):This way, the fields can be made private (we should try a crater run if possible - cc @kennytm @Mark-Simulacrum - just to make sure nobody was using the
Lazy
type themselves).