]> git.lizzy.rs Git - rust.git/blobdiff - src/shims/windows/foreign_items.rs
some clippy-induced cleanup
[rust.git] / src / shims / windows / foreign_items.rs
index 82ac5c5d75c43c87278bd7d2c84dd2bfef285876..08a319159bc590c9827428b20f73604724bc5e65 100644 (file)
@@ -8,6 +8,7 @@
 use crate::*;
 use shims::foreign_items::EmulateByNameResult;
 use shims::windows::sync::EvalContextExt as _;
+use smallvec::SmallVec;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
@@ -23,93 +24,51 @@ fn emulate_foreign_item_by_name(
 
         // Windows API stubs.
         // HANDLE = isize
+        // NTSTATUS = LONH = i32
         // DWORD = ULONG = u32
         // BOOL = i32
         // BOOLEAN = u8
-        match &*link_name.as_str() {
+        match link_name.as_str() {
             // Environment related shims
             "GetEnvironmentVariableW" => {
-                let &[ref name, ref buf, ref size] =
+                let [name, buf, size] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.GetEnvironmentVariableW(name, buf, size)?;
                 this.write_scalar(Scalar::from_u32(result), dest)?;
             }
             "SetEnvironmentVariableW" => {
-                let &[ref name, ref value] =
+                let [name, value] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.SetEnvironmentVariableW(name, value)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
             "GetEnvironmentStringsW" => {
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.GetEnvironmentStringsW()?;
                 this.write_pointer(result, dest)?;
             }
             "FreeEnvironmentStringsW" => {
-                let &[ref env_block] =
+                let [env_block] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.FreeEnvironmentStringsW(env_block)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
             "GetCurrentDirectoryW" => {
-                let &[ref size, ref buf] =
+                let [size, buf] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.GetCurrentDirectoryW(size, buf)?;
                 this.write_scalar(Scalar::from_u32(result), dest)?;
             }
             "SetCurrentDirectoryW" => {
-                let &[ref path] =
+                let [path] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.SetCurrentDirectoryW(path)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
 
-            // File related shims
-            "GetStdHandle" => {
-                let &[ref which] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                let which = this.read_scalar(which)?.to_i32()?;
-                // We just make this the identity function, so we know later in `WriteFile`
-                // which one it is.
-                this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
-            }
-            "WriteFile" => {
-                let &[ref handle, ref buf, ref n, ref written_ptr, ref overlapped] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore
-                let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
-                let buf = this.read_pointer(buf)?;
-                let n = this.read_scalar(n)?.to_u32()?;
-                let written_place = this.deref_operand(written_ptr)?;
-                // Spec says to always write `0` first.
-                this.write_null(&written_place.into())?;
-                let written = if handle == -11 || handle == -12 {
-                    // stdout/stderr
-                    use std::io::{self, Write};
-
-                    let buf_cont = this.read_bytes_ptr(buf, Size::from_bytes(u64::from(n)))?;
-                    let res = if handle == -11 {
-                        io::stdout().write(buf_cont)
-                    } else {
-                        io::stderr().write(buf_cont)
-                    };
-                    res.ok().map(|n| n as u32)
-                } else {
-                    throw_unsup_format!(
-                        "on Windows, writing to anything except stdout/stderr is not supported"
-                    )
-                };
-                // If there was no error, write back how much was written.
-                if let Some(n) = written {
-                    this.write_scalar(Scalar::from_u32(n), &written_place.into())?;
-                }
-                // Return whether this was a success.
-                this.write_scalar(Scalar::from_i32(if written.is_some() { 1 } else { 0 }), dest)?;
-            }
-
             // Allocation
             "HeapAlloc" => {
-                let &[ref handle, ref flags, ref size] =
+                let [handle, flags, size] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(handle)?.to_machine_isize(this)?;
                 let flags = this.read_scalar(flags)?.to_u32()?;
@@ -119,7 +78,7 @@ fn emulate_foreign_item_by_name(
                 this.write_pointer(res, dest)?;
             }
             "HeapFree" => {
-                let &[ref handle, ref flags, ref ptr] =
+                let [handle, flags, ptr] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(handle)?.to_machine_isize(this)?;
                 this.read_scalar(flags)?.to_u32()?;
@@ -128,7 +87,7 @@ fn emulate_foreign_item_by_name(
                 this.write_scalar(Scalar::from_i32(1), dest)?;
             }
             "HeapReAlloc" => {
-                let &[ref handle, ref flags, ref ptr, ref size] =
+                let [handle, flags, ptr, size] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(handle)?.to_machine_isize(this)?;
                 this.read_scalar(flags)?.to_u32()?;
@@ -140,20 +99,20 @@ fn emulate_foreign_item_by_name(
 
             // errno
             "SetLastError" => {
-                let &[ref error] =
+                let [error] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let error = this.read_scalar(error)?.check_init()?;
                 this.set_last_error(error)?;
             }
             "GetLastError" => {
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let last_error = this.get_last_error()?;
                 this.write_scalar(last_error, dest)?;
             }
 
             // Querying system information
             "GetSystemInfo" => {
-                let &[ref system_info] =
+                let [system_info] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let system_info = this.deref_operand(system_info)?;
                 // Initialize with `0`.
@@ -161,10 +120,56 @@ fn emulate_foreign_item_by_name(
                     system_info.ptr,
                     iter::repeat(0u8).take(system_info.layout.size.bytes() as usize),
                 )?;
+                // Set selected fields.
+                let word_layout = this.machine.layouts.u16;
+                let dword_layout = this.machine.layouts.u32;
+                let usize_layout = this.machine.layouts.usize;
+
+                // Using `mplace_field` is error-prone, see: https://github.com/rust-lang/miri/issues/2136.
+                // Pointer fields have different sizes on different targets.
+                // To avoid all these issue we calculate the offsets ourselves.
+                let field_sizes = [
+                    word_layout.size,  // 0,  wProcessorArchitecture      : WORD
+                    word_layout.size,  // 1,  wReserved                   : WORD
+                    dword_layout.size, // 2,  dwPageSize                  : DWORD
+                    usize_layout.size, // 3,  lpMinimumApplicationAddress : LPVOID
+                    usize_layout.size, // 4,  lpMaximumApplicationAddress : LPVOID
+                    usize_layout.size, // 5,  dwActiveProcessorMask       : DWORD_PTR
+                    dword_layout.size, // 6,  dwNumberOfProcessors        : DWORD
+                    dword_layout.size, // 7,  dwProcessorType             : DWORD
+                    dword_layout.size, // 8,  dwAllocationGranularity     : DWORD
+                    word_layout.size,  // 9,  wProcessorLevel             : WORD
+                    word_layout.size,  // 10, wProcessorRevision          : WORD
+                ];
+                let field_offsets: SmallVec<[Size; 11]> = field_sizes
+                    .iter()
+                    .copied()
+                    .scan(Size::ZERO, |a, x| {
+                        let res = Some(*a);
+                        *a += x;
+                        res
+                    })
+                    .collect();
+
+                // Set page size.
+                let page_size = system_info.offset(
+                    field_offsets[2],
+                    MemPlaceMeta::None,
+                    dword_layout,
+                    &this.tcx,
+                )?;
+                this.write_scalar(
+                    Scalar::from_int(PAGE_SIZE, dword_layout.size),
+                    &page_size.into(),
+                )?;
                 // Set number of processors.
-                let dword_size = Size::from_bytes(4);
-                let num_cpus = this.mplace_field(&system_info, 6)?;
-                this.write_scalar(Scalar::from_int(NUM_CPUS, dword_size), &num_cpus.into())?;
+                let num_cpus = system_info.offset(
+                    field_offsets[6],
+                    MemPlaceMeta::None,
+                    dword_layout,
+                    &this.tcx,
+                )?;
+                this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?;
             }
 
             // Thread-local storage
@@ -172,20 +177,19 @@ fn emulate_foreign_item_by_name(
                 // This just creates a key; Windows does not natively support TLS destructors.
 
                 // Create key and return it.
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
                 this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
             }
             "TlsGetValue" => {
-                let &[ref key] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [key] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let key = u128::from(this.read_scalar(key)?.to_u32()?);
                 let active_thread = this.get_active_thread();
                 let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
                 this.write_scalar(ptr, dest)?;
             }
             "TlsSetValue" => {
-                let &[ref key, ref new_ptr] =
+                let [key, new_ptr] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let key = u128::from(this.read_scalar(key)?.to_u32()?);
                 let active_thread = this.get_active_thread();
@@ -198,7 +202,7 @@ fn emulate_foreign_item_by_name(
 
             // Access to command-line arguments
             "GetCommandLineW" => {
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.write_pointer(
                     this.machine.cmd_line.expect("machine must be initialized").ptr,
                     dest,
@@ -208,20 +212,20 @@ fn emulate_foreign_item_by_name(
             // Time related shims
             "GetSystemTimeAsFileTime" => {
                 #[allow(non_snake_case)]
-                let &[ref LPFILETIME] =
+                let [LPFILETIME] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.GetSystemTimeAsFileTime(LPFILETIME)?;
             }
             "QueryPerformanceCounter" => {
                 #[allow(non_snake_case)]
-                let &[ref lpPerformanceCount] =
+                let [lpPerformanceCount] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.QueryPerformanceCounter(lpPerformanceCount)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
             }
             "QueryPerformanceFrequency" => {
                 #[allow(non_snake_case)]
-                let &[ref lpFrequency] =
+                let [lpFrequency] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let result = this.QueryPerformanceFrequency(lpFrequency)?;
                 this.write_scalar(Scalar::from_i32(result), dest)?;
@@ -229,34 +233,28 @@ fn emulate_foreign_item_by_name(
 
             // Synchronization primitives
             "AcquireSRWLockExclusive" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.AcquireSRWLockExclusive(ptr)?;
             }
             "ReleaseSRWLockExclusive" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.ReleaseSRWLockExclusive(ptr)?;
             }
             "TryAcquireSRWLockExclusive" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let ret = this.TryAcquireSRWLockExclusive(ptr)?;
                 this.write_scalar(Scalar::from_u8(ret), dest)?;
             }
             "AcquireSRWLockShared" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.AcquireSRWLockShared(ptr)?;
             }
             "ReleaseSRWLockShared" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.ReleaseSRWLockShared(ptr)?;
             }
             "TryAcquireSRWLockShared" => {
-                let &[ref ptr] =
-                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [ptr] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let ret = this.TryAcquireSRWLockShared(ptr)?;
                 this.write_scalar(Scalar::from_u8(ret), dest)?;
             }
@@ -264,7 +262,7 @@ fn emulate_foreign_item_by_name(
             // Dynamic symbol loading
             "GetProcAddress" => {
                 #[allow(non_snake_case)]
-                let &[ref hModule, ref lpProcName] =
+                let [hModule, lpProcName] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(hModule)?.to_machine_isize(this)?;
                 let name = this.read_c_str(this.read_pointer(lpProcName)?)?;
@@ -279,7 +277,7 @@ fn emulate_foreign_item_by_name(
             // Miscellaneous
             "SystemFunction036" => {
                 // This is really 'RtlGenRandom'.
-                let &[ref ptr, ref len] =
+                let [ptr, len] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
                 let len = this.read_scalar(len)?.to_u32()?;
@@ -287,7 +285,7 @@ fn emulate_foreign_item_by_name(
                 this.write_scalar(Scalar::from_bool(true), dest)?;
             }
             "BCryptGenRandom" => {
-                let &[ref algorithm, ref ptr, ref len, ref flags] =
+                let [algorithm, ptr, len, flags] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 let algorithm = this.read_scalar(algorithm)?;
                 let ptr = this.read_pointer(ptr)?;
@@ -309,7 +307,7 @@ fn emulate_foreign_item_by_name(
             }
             "GetConsoleScreenBufferInfo" => {
                 // `term` needs this, so we fake it.
-                let &[ref console, ref buffer_info] =
+                let [console, buffer_info] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(console)?.to_machine_isize(this)?;
                 this.deref_operand(buffer_info)?;
@@ -319,7 +317,7 @@ fn emulate_foreign_item_by_name(
             }
             "GetConsoleMode" => {
                 // Windows "isatty" (in libtest) needs this, so we fake it.
-                let &[ref console, ref mode] =
+                let [console, mode] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 this.read_scalar(console)?.to_machine_isize(this)?;
                 this.deref_operand(mode)?;
@@ -328,15 +326,24 @@ fn emulate_foreign_item_by_name(
                 this.write_null(dest)?;
             }
             "SwitchToThread" => {
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 // Note that once Miri supports concurrency, this will need to return a nonzero
                 // value if this call does result in switching to another thread.
                 this.write_null(dest)?;
             }
+            "GetStdHandle" => {
+                let [which] =
+                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let which = this.read_scalar(which)?.to_i32()?;
+                // We just make this the identity function, so we know later in `NtWriteFile` which
+                // one it is. This is very fake, but libtest needs it so we cannot make it a
+                // std-only shim.
+                this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
+            }
 
             // Better error for attempts to create a thread
             "CreateThread" => {
-                let &[_, _, _, _, _, _] =
+                let [_, _, _, _, _, _] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
 
                 this.handle_unsupported("can't create threads on Windows")?;
@@ -346,27 +353,34 @@ fn emulate_foreign_item_by_name(
             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
             // These shims are enabled only when the caller is in the standard library.
             "GetProcessHeap" if this.frame_in_std() => {
-                let &[] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 // Just fake a HANDLE
                 this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
             }
+            "GetModuleHandleA" if this.frame_in_std() => {
+                #[allow(non_snake_case)]
+                let [_lpModuleName] =
+                    this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                // We need to return something non-null here to make `compat_fn!` work.
+                this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
+            }
             "SetConsoleTextAttribute" if this.frame_in_std() => {
                 #[allow(non_snake_case)]
-                let &[ref _hConsoleOutput, ref _wAttribute] =
+                let [_hConsoleOutput, _wAttribute] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 // Pretend these does not exist / nothing happened, by returning zero.
                 this.write_null(dest)?;
             }
             "AddVectoredExceptionHandler" if this.frame_in_std() => {
                 #[allow(non_snake_case)]
-                let &[ref _First, ref _Handler] =
+                let [_First, _Handler] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
                 this.write_scalar(Scalar::from_machine_usize(1, this), dest)?;
             }
             "SetThreadStackGuarantee" if this.frame_in_std() => {
                 #[allow(non_snake_case)]
-                let &[_StackSizeInBytes] =
+                let [_StackSizeInBytes] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 // Any non zero value works for the stdlib. This is just used for stack overflows anyway.
                 this.write_scalar(Scalar::from_u32(1), dest)?;
@@ -378,7 +392,7 @@ fn emulate_foreign_item_by_name(
                 if this.frame_in_std() =>
             {
                 #[allow(non_snake_case)]
-                let &[ref _lpCriticalSection] =
+                let [_lpCriticalSection] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 assert_eq!(
                     this.get_total_thread_count(),
@@ -391,7 +405,7 @@ fn emulate_foreign_item_by_name(
             }
             "TryEnterCriticalSection" if this.frame_in_std() => {
                 #[allow(non_snake_case)]
-                let &[ref _lpCriticalSection] =
+                let [_lpCriticalSection] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
                 assert_eq!(
                     this.get_total_thread_count(),
@@ -401,6 +415,10 @@ fn emulate_foreign_item_by_name(
                 // There is only one thread, so this always succeeds and returns TRUE.
                 this.write_scalar(Scalar::from_i32(1), dest)?;
             }
+            "GetCurrentThread" if this.frame_in_std() => {
+                let [] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
+                this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
+            }
 
             _ => return Ok(EmulateByNameResult::NotSupported),
         }