diff options
| author | bors <bors@rust-lang.org> | 2022-07-16 08:48:36 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-07-16 08:48:36 +0000 |
| commit | e092d0b6b43f2de967af0887873151bb1c0b18d3 (patch) | |
| tree | 3c0903d6cb6800cbf43017141fc38b669a360386 /library/std/src/sys/windows | |
| parent | a8314ef7d0ec7b75c336af2c9857bfaf43002bfc (diff) | |
| parent | 647922f9d8a6f1fa639ab206e60a76d43cc9d3dd (diff) | |
| download | rust-1.62.1.tar.gz rust-1.62.1.zip | |
Auto merge of #99299 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum 1.62.1
[stable] 1.62.1 release This bundles: * Windows: Fallback for overlapped I/O #98950 * don't succeed evaluate_obligation query if new opaque types were registered #98614 * Mitigate MMIO stale data vulnerability #98126 * Return a FxIndexSet in is_late_bound query. #99219 Also bumps the version number to 1.62.1 and includes a short release notes section for the release. r? `@Mark-Simulacrum`
Diffstat (limited to 'library/std/src/sys/windows')
| -rw-r--r-- | library/std/src/sys/windows/c.rs | 14 | ||||
| -rw-r--r-- | library/std/src/sys/windows/handle.rs | 25 | ||||
| -rw-r--r-- | library/std/src/sys/windows/handle/tests.rs | 22 |
3 files changed, 53 insertions, 8 deletions
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index 5f14edaf067..b92aa420177 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -325,7 +325,9 @@ union IO_STATUS_BLOCK_union { } impl Default for IO_STATUS_BLOCK_union { fn default() -> Self { - Self { Pointer: ptr::null_mut() } + let mut this = Self { Pointer: ptr::null_mut() }; + this.Status = STATUS_PENDING; + this } } #[repr(C)] @@ -334,6 +336,16 @@ pub struct IO_STATUS_BLOCK { u: IO_STATUS_BLOCK_union, pub Information: usize, } +impl IO_STATUS_BLOCK { + pub fn status(&self) -> NTSTATUS { + // SAFETY: If `self.u.Status` was set then this is obviously safe. + // If `self.u.Pointer` was set then this is the equivalent to converting + // the pointer to an integer, which is also safe. + // Currently the only safe way to construct `IO_STATUS_BLOCK` outside of + // this module is to call the `default` method, which sets the `Status`. + unsafe { self.u.Status } + } +} pub type LPOVERLAPPED_COMPLETION_ROUTINE = unsafe extern "system" fn( dwErrorCode: DWORD, diff --git a/library/std/src/sys/windows/handle.rs b/library/std/src/sys/windows/handle.rs index ef9a8bd6900..6398c445633 100644 --- a/library/std/src/sys/windows/handle.rs +++ b/library/std/src/sys/windows/handle.rs @@ -1,5 +1,8 @@ #![unstable(issue = "none", feature = "windows_handle")] +#[cfg(test)] +mod tests; + use crate::cmp; use crate::io::{self, ErrorKind, IoSlice, IoSliceMut, Read, ReadBuf}; use crate::mem; @@ -248,14 +251,18 @@ impl Handle { offset.map(|n| n as _).as_ref(), None, ); + + let status = if status == c::STATUS_PENDING { + c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE); + io_status.status() + } else { + status + }; match status { // If the operation has not completed then abort the process. // Doing otherwise means that the buffer and stack may be written to // after this function returns. - c::STATUS_PENDING => { - eprintln!("I/O error: operation failed to complete synchronously"); - crate::process::abort(); - } + c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"), // Return `Ok(0)` when there's nothing more to read. c::STATUS_END_OF_FILE => Ok(0), @@ -294,13 +301,17 @@ impl Handle { None, ) }; + let status = if status == c::STATUS_PENDING { + unsafe { c::WaitForSingleObject(self.as_raw_handle(), c::INFINITE) }; + io_status.status() + } else { + status + }; match status { // If the operation has not completed then abort the process. // Doing otherwise means that the buffer may be read and the stack // written to after this function returns. - c::STATUS_PENDING => { - rtabort!("I/O error: operation failed to complete synchronously"); - } + c::STATUS_PENDING => rtabort!("I/O error: operation failed to complete synchronously"), // Success! status if c::nt_success(status) => Ok(io_status.Information), diff --git a/library/std/src/sys/windows/handle/tests.rs b/library/std/src/sys/windows/handle/tests.rs new file mode 100644 index 00000000000..d836dae4c30 --- /dev/null +++ b/library/std/src/sys/windows/handle/tests.rs @@ -0,0 +1,22 @@ +use crate::sys::pipe::{anon_pipe, Pipes}; +use crate::{thread, time}; + +/// Test the synchronous fallback for overlapped I/O. +#[test] +fn overlapped_handle_fallback() { + // Create some pipes. `ours` will be asynchronous. + let Pipes { ours, theirs } = anon_pipe(true, false).unwrap(); + + let async_readable = ours.into_handle(); + let sync_writeable = theirs.into_handle(); + + thread::scope(|_| { + thread::sleep(time::Duration::from_millis(100)); + sync_writeable.write(b"hello world!").unwrap(); + }); + + // The pipe buffer starts empty so reading won't complete synchronously unless + // our fallback path works. + let mut buffer = [0u8; 1024]; + async_readable.read(&mut buffer).unwrap(); +} |
