about summary refs log tree commit diff
diff options
context:
space:
mode:
authorjoboet <jonasboettiger@icloud.com>2024-11-25 16:27:17 +0100
committerjoboet <jonasboettiger@icloud.com>2024-11-25 16:27:17 +0100
commit77fccf59e3838473e234bdb970e7100ba5c361f8 (patch)
tree6f025b3b49f76331db3a4cb42a8636cc6255edec
parent7db7489f9bc274cb60c4956bfa56de0185eb1b9b (diff)
downloadrust-77fccf59e3838473e234bdb970e7100ba5c361f8.tar.gz
rust-77fccf59e3838473e234bdb970e7100ba5c361f8.zip
miri: implement `TlsFree`
If the variable does not need a destructor, `std` uses racy initialization for creating TLS keys on Windows. With just the right timing, this can lead to `TlsFree` being called. Unfortunately, with #132654 this is hit quite often, so miri should definitely support `TlsFree` ([documentation](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsfree)).

I'm filing this here instead of in the miri repo so that #132654 isn't blocked for so long.
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs8
-rw-r--r--src/tools/miri/tests/pass/tls/windows-tls.rs18
2 files changed, 26 insertions, 0 deletions
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index c145cf3ceb8..a1fad6f9af4 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -382,6 +382,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 // Return success (`1`).
                 this.write_int(1, dest)?;
             }
+            "TlsFree" => {
+                let [key] = this.check_shim(abi, ExternAbi::System { unwind: false }, link_name, args)?;
+                let key = u128::from(this.read_scalar(key)?.to_u32()?);
+                this.machine.tls.delete_tls_key(key)?;
+
+                // Return success (`1`).
+                this.write_int(1, dest)?;
+            }
 
             // Access to command-line arguments
             "GetCommandLineW" => {
diff --git a/src/tools/miri/tests/pass/tls/windows-tls.rs b/src/tools/miri/tests/pass/tls/windows-tls.rs
new file mode 100644
index 00000000000..58131be1903
--- /dev/null
+++ b/src/tools/miri/tests/pass/tls/windows-tls.rs
@@ -0,0 +1,18 @@
+//@only-target: windows # this directly tests windows-only functions
+
+use std::ffi::c_void;
+use std::ptr;
+
+extern "system" {
+    fn TlsAlloc() -> u32;
+    fn TlsSetValue(key: u32, val: *mut c_void) -> bool;
+    fn TlsGetValue(key: u32) -> *mut c_void;
+    fn TlsFree(key: u32) -> bool;
+}
+
+fn main() {
+    let key = unsafe { TlsAlloc() };
+    assert!(unsafe { TlsSetValue(key, ptr::without_provenance_mut(1)) });
+    assert_eq!(unsafe { TlsGetValue(key).addr() }, 1);
+    assert!(unsafe { TlsFree(key) });
+}