From 22ac515502e60e895e57a08db8eb1ab4e7fe9cb3 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 12 Nov 2021 15:14:45 +0000 Subject: [PATCH 1/2] Ensure stdio handles are never null when converting to `HandleRef` --- Cargo.toml | 1 + src/win.rs | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e1fb776..5a3a171 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ features = [ "consoleapi", "errhandlingapi", "fileapi", + "handleapi", "minwindef", "processenv", "winbase", diff --git a/src/win.rs b/src/win.rs index 9c77c0d..57f6dbd 100644 --- a/src/win.rs +++ b/src/win.rs @@ -5,6 +5,7 @@ use std::os::windows::io::{ }; use std::path::Path; use std::process; +use winapi::um::handleapi::INVALID_HANDLE_VALUE; /// A handle represents an owned and valid Windows handle to a file-like /// object. @@ -117,26 +118,37 @@ impl Clone for HandleRef { } } +/// Ensures the handle is never null by converting null values to the +/// pseudo-handle `INVALID_HANDLE_VALUE`. +fn nonnull_handle(stdio: T) -> RawHandle { + let handle = stdio.as_raw_handle(); + if handle.is_null() { + INVALID_HANDLE_VALUE + } else { + handle + } +} + impl HandleRef { /// Create a borrowed handle to stdin. /// /// When the returned handle is dropped, stdin is not closed. pub fn stdin() -> HandleRef { - unsafe { HandleRef::from_raw_handle(io::stdin().as_raw_handle()) } + unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stdin())) } } /// Create a handle to stdout. /// /// When the returned handle is dropped, stdout is not closed. pub fn stdout() -> HandleRef { - unsafe { HandleRef::from_raw_handle(io::stdout().as_raw_handle()) } + unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stdout())) } } /// Create a handle to stderr. /// /// When the returned handle is dropped, stderr is not closed. pub fn stderr() -> HandleRef { - unsafe { HandleRef::from_raw_handle(io::stderr().as_raw_handle()) } + unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stderr())) } } /// Create a borrowed handle to the given file. From df842059c973244ff964e9e5a9d3a8c6208be7db Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 12 Nov 2021 16:02:25 +0000 Subject: [PATCH 2/2] Document behaviour when an stdio handle is missing --- src/win.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/win.rs b/src/win.rs index 57f6dbd..a809b78 100644 --- a/src/win.rs +++ b/src/win.rs @@ -133,6 +133,15 @@ impl HandleRef { /// Create a borrowed handle to stdin. /// /// When the returned handle is dropped, stdin is not closed. + /// + /// If there is no stdin handle then `INVALID_HANDLE_VALUE` will be used + /// as the underlying file handle. This is likely to cause any use of the + /// handle to fail. + /// + /// The handle will most commonly be missing in GUI applications using the + /// ["windows" subsystem][subsystem]. + /// + /// [subsystem]: https://doc.rust-lang.org/reference/runtime.html?#the-windows_subsystem-attribute pub fn stdin() -> HandleRef { unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stdin())) } } @@ -140,6 +149,15 @@ impl HandleRef { /// Create a handle to stdout. /// /// When the returned handle is dropped, stdout is not closed. + /// + /// If there is no stdout handle then `INVALID_HANDLE_VALUE` will be used + /// as the underlying file handle. This is likely to cause any use of the + /// handle to fail. + /// + /// The handle will most commonly be missing in GUI applications using the + /// ["windows" subsystem][subsystem]. + /// + /// [subsystem]: https://doc.rust-lang.org/reference/runtime.html?#the-windows_subsystem-attribute pub fn stdout() -> HandleRef { unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stdout())) } } @@ -147,6 +165,15 @@ impl HandleRef { /// Create a handle to stderr. /// /// When the returned handle is dropped, stderr is not closed. + /// + /// If there is no stderr handle then `INVALID_HANDLE_VALUE` will be used + /// as the underlying file handle. This is likely to cause any use of the + /// handle to fail. + /// + /// The handle will most commonly be missing in GUI applications using the + /// ["windows" subsystem][subsystem]. + /// + /// [subsystem]: https://doc.rust-lang.org/reference/runtime.html?#the-windows_subsystem-attribute pub fn stderr() -> HandleRef { unsafe { HandleRef::from_raw_handle(nonnull_handle(io::stderr())) } }