Skip to content

Commit aeae332

Browse files
authored
Rollup merge of rust-lang#127763 - ChrisDenton:safe-unsafe-unsafe, r=tgross35
Make more Windows functions `#![deny(unsafe_op_in_unsafe_fn)]` As part of rust-lang#127747, I've evaluated some more Windows functions and added `unsafe` blocks where necessary. Some are just trivial wrappers that "inherit" the full unsafety of their function, but for others I've added some safety comments. A few functions weren't actually unsafe at all. I think they were just using `unsafe fn` to avoid an `unsafe {}` block. I'm not touching `c.rs` yet because that is partially being addressed by another PR and also I have plans to further reduce the number of wrapper functions we have in there. r? libs
2 parents f431b51 + 417b61f commit aeae332

File tree

10 files changed

+111
-90
lines changed

10 files changed

+111
-90
lines changed

std/src/sys/os_str/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#![forbid(unsafe_op_in_unsafe_fn)]
2+
13
cfg_if::cfg_if! {
24
if #[cfg(any(
35
target_os = "windows",

std/src/sys/os_str/wtf8.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
//! The underlying OsString/OsStr implementation on Windows is a
22
//! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
3-
43
use crate::borrow::Cow;
54
use crate::collections::TryReserveError;
65
use crate::fmt;
@@ -71,7 +70,7 @@ impl Buf {
7170

7271
#[inline]
7372
pub unsafe fn from_encoded_bytes_unchecked(s: Vec<u8>) -> Self {
74-
Self { inner: Wtf8Buf::from_bytes_unchecked(s) }
73+
unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
7574
}
7675

7776
pub fn with_capacity(capacity: usize) -> Buf {
@@ -190,7 +189,7 @@ impl Slice {
190189

191190
#[inline]
192191
pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &Slice {
193-
mem::transmute(Wtf8::from_bytes_unchecked(s))
192+
unsafe { mem::transmute(Wtf8::from_bytes_unchecked(s)) }
194193
}
195194

196195
#[track_caller]

std/src/sys/pal/windows/alloc.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![deny(unsafe_op_in_unsafe_fn)]
2-
31
use crate::alloc::{GlobalAlloc, Layout, System};
42
use crate::ffi::c_void;
53
use crate::ptr;

std/src/sys/pal/windows/fs.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![allow(unsafe_op_in_unsafe_fn)]
21
use core::ptr::addr_of;
32

43
use crate::os::windows::prelude::*;
@@ -795,10 +794,12 @@ impl<'a> Iterator for DirBuffIter<'a> {
795794
}
796795

797796
unsafe fn from_maybe_unaligned<'a>(p: *const u16, len: usize) -> Cow<'a, [u16]> {
798-
if p.is_aligned() {
799-
Cow::Borrowed(crate::slice::from_raw_parts(p, len))
800-
} else {
801-
Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect())
797+
unsafe {
798+
if p.is_aligned() {
799+
Cow::Borrowed(crate::slice::from_raw_parts(p, len))
800+
} else {
801+
Cow::Owned((0..len).map(|i| p.add(i).read_unaligned()).collect())
802+
}
802803
}
803804
}
804805

@@ -897,7 +898,9 @@ impl IntoRawHandle for File {
897898

898899
impl FromRawHandle for File {
899900
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
900-
Self { handle: FromInner::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
901+
unsafe {
902+
Self { handle: FromInner::from_inner(FromRawHandle::from_raw_handle(raw_handle)) }
903+
}
901904
}
902905
}
903906

@@ -1427,10 +1430,12 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
14271430
_hDestinationFile: c::HANDLE,
14281431
lpData: *const c_void,
14291432
) -> u32 {
1430-
if dwStreamNumber == 1 {
1431-
*(lpData as *mut i64) = StreamBytesTransferred;
1433+
unsafe {
1434+
if dwStreamNumber == 1 {
1435+
*(lpData as *mut i64) = StreamBytesTransferred;
1436+
}
1437+
c::PROGRESS_CONTINUE
14321438
}
1433-
c::PROGRESS_CONTINUE
14341439
}
14351440
let pfrom = maybe_verbatim(from)?;
14361441
let pto = maybe_verbatim(to)?;

std/src/sys/pal/windows/handle.rs

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#![unstable(issue = "none", feature = "windows_handle")]
2-
#![allow(unsafe_op_in_unsafe_fn)]
32

43
#[cfg(test)]
54
mod tests;
@@ -73,7 +72,7 @@ impl IntoRawHandle for Handle {
7372

7473
impl FromRawHandle for Handle {
7574
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
76-
Self(FromRawHandle::from_raw_handle(raw_handle))
75+
unsafe { Self(FromRawHandle::from_raw_handle(raw_handle)) }
7776
}
7877
}
7978

@@ -139,13 +138,23 @@ impl Handle {
139138

140139
pub unsafe fn read_overlapped(
141140
&self,
142-
buf: &mut [u8],
141+
buf: &mut [mem::MaybeUninit<u8>],
143142
overlapped: *mut c::OVERLAPPED,
144143
) -> io::Result<Option<usize>> {
145-
let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
146-
let mut amt = 0;
147-
let res =
148-
cvt(c::ReadFile(self.as_raw_handle(), buf.as_mut_ptr(), len, &mut amt, overlapped));
144+
// SAFETY: We have exclusive access to the buffer and it's up to the caller to
145+
// ensure the OVERLAPPED pointer is valid for the lifetime of this function.
146+
let (res, amt) = unsafe {
147+
let len = cmp::min(buf.len(), u32::MAX as usize) as u32;
148+
let mut amt = 0;
149+
let res = cvt(c::ReadFile(
150+
self.as_raw_handle(),
151+
buf.as_mut_ptr().cast::<u8>(),
152+
len,
153+
&mut amt,
154+
overlapped,
155+
));
156+
(res, amt)
157+
};
149158
match res {
150159
Ok(_) => Ok(Some(amt as usize)),
151160
Err(e) => {
@@ -230,20 +239,24 @@ impl Handle {
230239

231240
// The length is clamped at u32::MAX.
232241
let len = cmp::min(len, u32::MAX as usize) as u32;
233-
let status = c::NtReadFile(
234-
self.as_handle(),
235-
ptr::null_mut(),
236-
None,
237-
ptr::null_mut(),
238-
&mut io_status,
239-
buf,
240-
len,
241-
offset.map(|n| n as _).as_ref(),
242-
None,
243-
);
242+
// SAFETY: It's up to the caller to ensure `buf` is writeable up to
243+
// the provided `len`.
244+
let status = unsafe {
245+
c::NtReadFile(
246+
self.as_handle(),
247+
ptr::null_mut(),
248+
None,
249+
ptr::null_mut(),
250+
&mut io_status,
251+
buf,
252+
len,
253+
offset.map(|n| n as _).as_ref(),
254+
None,
255+
)
256+
};
244257

245258
let status = if status == c::STATUS_PENDING {
246-
c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE);
259+
unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) };
247260
io_status.status()
248261
} else {
249262
status
@@ -261,7 +274,7 @@ impl Handle {
261274
status if c::nt_success(status) => Ok(io_status.Information),
262275

263276
status => {
264-
let error = c::RtlNtStatusToDosError(status);
277+
let error = unsafe { c::RtlNtStatusToDosError(status) };
265278
Err(io::Error::from_raw_os_error(error as _))
266279
}
267280
}

std/src/sys/pal/windows/io.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#![allow(unsafe_op_in_unsafe_fn)]
21
use crate::marker::PhantomData;
32
use crate::mem::size_of;
43
use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle};
@@ -81,19 +80,17 @@ impl<'a> IoSliceMut<'a> {
8180
}
8281

8382
pub fn is_terminal(h: &impl AsHandle) -> bool {
84-
unsafe { handle_is_console(h.as_handle()) }
83+
handle_is_console(h.as_handle())
8584
}
8685

87-
unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
88-
let handle = handle.as_raw_handle();
89-
86+
fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
9087
// A null handle means the process has no console.
91-
if handle.is_null() {
88+
if handle.as_raw_handle().is_null() {
9289
return false;
9390
}
9491

9592
let mut out = 0;
96-
if c::GetConsoleMode(handle, &mut out) != 0 {
93+
if unsafe { c::GetConsoleMode(handle.as_raw_handle(), &mut out) != 0 } {
9794
// False positives aren't possible. If we got a console then we definitely have a console.
9895
return true;
9996
}
@@ -102,9 +99,9 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
10299
msys_tty_on(handle)
103100
}
104101

105-
unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
102+
fn msys_tty_on(handle: BorrowedHandle<'_>) -> bool {
106103
// Early return if the handle is not a pipe.
107-
if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
104+
if unsafe { c::GetFileType(handle.as_raw_handle()) != c::FILE_TYPE_PIPE } {
108105
return false;
109106
}
110107

@@ -120,12 +117,14 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
120117
}
121118
let mut name_info = FILE_NAME_INFO { FileNameLength: 0, FileName: [0; c::MAX_PATH as usize] };
122119
// Safety: buffer length is fixed.
123-
let res = c::GetFileInformationByHandleEx(
124-
handle,
125-
c::FileNameInfo,
126-
core::ptr::addr_of_mut!(name_info) as *mut c_void,
127-
size_of::<FILE_NAME_INFO>() as u32,
128-
);
120+
let res = unsafe {
121+
c::GetFileInformationByHandleEx(
122+
handle.as_raw_handle(),
123+
c::FileNameInfo,
124+
core::ptr::addr_of_mut!(name_info) as *mut c_void,
125+
size_of::<FILE_NAME_INFO>() as u32,
126+
)
127+
};
129128
if res == 0 {
130129
return false;
131130
}

std/src/sys/pal/windows/os.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
//! Implementation of `std::os` functionality for Windows.
22
33
#![allow(nonstandard_style)]
4-
#![allow(unsafe_op_in_unsafe_fn)]
54

65
#[cfg(test)]
76
mod tests;
@@ -305,15 +304,21 @@ pub fn getenv(k: &OsStr) -> Option<OsString> {
305304
}
306305

307306
pub unsafe fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
308-
let k = to_u16s(k)?;
309-
let v = to_u16s(v)?;
307+
// SAFETY: We ensure that k and v are null-terminated wide strings.
308+
unsafe {
309+
let k = to_u16s(k)?;
310+
let v = to_u16s(v)?;
310311

311-
cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
312+
cvt(c::SetEnvironmentVariableW(k.as_ptr(), v.as_ptr())).map(drop)
313+
}
312314
}
313315

314316
pub unsafe fn unsetenv(n: &OsStr) -> io::Result<()> {
315-
let v = to_u16s(n)?;
316-
cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
317+
// SAFETY: We ensure that v is a null-terminated wide strings.
318+
unsafe {
319+
let v = to_u16s(n)?;
320+
cvt(c::SetEnvironmentVariableW(v.as_ptr(), ptr::null())).map(drop)
321+
}
317322
}
318323

319324
pub fn temp_dir() -> PathBuf {

std/src/sys/pal/windows/pipe.rs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
#![allow(unsafe_op_in_unsafe_fn)]
21
use crate::os::windows::prelude::*;
32

43
use crate::ffi::OsStr;
54
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
65
use crate::mem;
76
use crate::path::Path;
87
use crate::ptr;
9-
use crate::slice;
108
use crate::sync::atomic::AtomicUsize;
119
use crate::sync::atomic::Ordering::Relaxed;
1210
use crate::sys::c;
@@ -325,6 +323,7 @@ impl AnonPipe {
325323
/// [`ReadFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfileex
326324
/// [`WriteFileEx`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefileex
327325
/// [Asynchronous Procedure Call]: https://docs.microsoft.com/en-us/windows/win32/sync/asynchronous-procedure-calls
326+
#[allow(unsafe_op_in_unsafe_fn)]
328327
unsafe fn alertable_io_internal(
329328
&self,
330329
io: AlertableIoFn,
@@ -479,8 +478,11 @@ impl<'a> AsyncPipe<'a> {
479478
fn schedule_read(&mut self) -> io::Result<bool> {
480479
assert_eq!(self.state, State::NotReading);
481480
let amt = unsafe {
482-
let slice = slice_to_end(self.dst);
483-
self.pipe.read_overlapped(slice, &mut *self.overlapped)?
481+
if self.dst.capacity() == self.dst.len() {
482+
let additional = if self.dst.capacity() == 0 { 16 } else { 1 };
483+
self.dst.reserve(additional);
484+
}
485+
self.pipe.read_overlapped(self.dst.spare_capacity_mut(), &mut *self.overlapped)?
484486
};
485487

486488
// If this read finished immediately then our overlapped event will
@@ -560,13 +562,3 @@ impl<'a> Drop for AsyncPipe<'a> {
560562
}
561563
}
562564
}
563-
564-
unsafe fn slice_to_end(v: &mut Vec<u8>) -> &mut [u8] {
565-
if v.capacity() == 0 {
566-
v.reserve(16);
567-
}
568-
if v.capacity() == v.len() {
569-
v.reserve(1);
570-
}
571-
slice::from_raw_parts_mut(v.as_mut_ptr().add(v.len()), v.capacity() - v.len())
572-
}
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
#![cfg_attr(test, allow(dead_code))]
2-
#![allow(unsafe_op_in_unsafe_fn)]
32

43
use crate::sys::c;
54
use crate::thread;
65

76
/// Reserve stack space for use in stack overflow exceptions.
8-
pub unsafe fn reserve_stack() {
9-
let result = c::SetThreadStackGuarantee(&mut 0x5000);
7+
pub fn reserve_stack() {
8+
let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) };
109
// Reserving stack space is not critical so we allow it to fail in the released build of libstd.
1110
// We still use debug assert here so that CI will test that we haven't made a mistake calling the function.
1211
debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling");
1312
}
1413

1514
unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 {
15+
// SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid.
1616
unsafe {
1717
let rec = &(*(*ExceptionInfo).ExceptionRecord);
1818
let code = rec.ExceptionCode;
@@ -27,11 +27,14 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN
2727
}
2828
}
2929

30-
pub unsafe fn init() {
31-
let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
32-
// Similar to the above, adding the stack overflow handler is allowed to fail
33-
// but a debug assert is used so CI will still test that it normally works.
34-
debug_assert!(!result.is_null(), "failed to install exception handler");
30+
pub fn init() {
31+
// SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling.
32+
unsafe {
33+
let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
34+
// Similar to the above, adding the stack overflow handler is allowed to fail
35+
// but a debug assert is used so CI will still test that it normally works.
36+
debug_assert!(!result.is_null(), "failed to install exception handler");
37+
}
3538
// Set the thread stack guarantee for the main thread.
3639
reserve_stack();
3740
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy