diff options
| author | Alex Crichton <alex@alexcrichton.com> | 2015-12-08 07:23:37 -0800 |
|---|---|---|
| committer | Alex Crichton <alex@alexcrichton.com> | 2015-12-08 12:23:22 -0800 |
| commit | 9e0ff773ad5840af78ef0deeebb7da2f503eca32 (patch) | |
| tree | a8e6e7f86a160227754bb9d16db59b998560675f /src/libstd/thread | |
| parent | 8864f2c83ac800881da34c3e835c931c081a8785 (diff) | |
| download | rust-9e0ff773ad5840af78ef0deeebb7da2f503eca32.tar.gz rust-9e0ff773ad5840af78ef0deeebb7da2f503eca32.zip | |
std: Use mem::replace in TLS initialization
Due to #30228 it's not currently sound to do `*ptr = Some(value)`, so instead use `mem::replace` which fixes the soundness hole for now.
Diffstat (limited to 'src/libstd/thread')
| -rw-r--r-- | src/libstd/thread/local.rs | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs index 119429cc584..870247f7e82 100644 --- a/src/libstd/thread/local.rs +++ b/src/libstd/thread/local.rs @@ -13,6 +13,7 @@ #![unstable(feature = "thread_local_internals", issue = "0")] use cell::UnsafeCell; +use mem; // Sure wish we had macro hygiene, no? #[doc(hidden)] @@ -226,7 +227,21 @@ impl<T: 'static> LocalKey<T> { // just in case initialization fails. let value = (self.init)(); let ptr = slot.get(); - *ptr = Some(value); + + // note that this can in theory just be `*ptr = Some(value)`, but due to + // the compiler will currently codegen that pattern with something like: + // + // ptr::drop_in_place(ptr) + // ptr::write(ptr, Some(value)) + // + // Due to this pattern it's possible for the destructor of the value in + // `ptr` (e.g. if this is being recursively initialized) to re-access + // TLS, in which case there will be a `&` and `&mut` pointer to the same + // value (an aliasing violation). To avoid setting the "I'm running a + // destructor" flag we just use `mem::replace` which should sequence the + // operations a little differently and make this safe to call. + mem::replace(&mut *ptr, Some(value)); + (*ptr).as_ref().unwrap() } |
