Rollup merge of #103360 - ChrisDenton:isterm-filetype, r=thomcc

Reduce false positives in msys2 detection

Currently msys2 will be detected by getting the file path and looking to see if it contains the substrings "msys-" and "-ptr" (or "cygwin-" and "-pty"). This risks false positives, especially with filesystem files and if `GetFileInformationByHandleEx` returns a [full path](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntqueryinformationfile#remarks).

This PR adds a check to see if the handle is a pipe before doing the substring search. Additionally, for "msys2-" or "cygwin-" it only checks if the file name starts with the substring rather than looking at the whole path.
This commit is contained in:
Dylan DPC 2022-10-22 16:28:09 +05:30 committed by GitHub
commit b4536943e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 2 deletions

View File

@ -129,6 +129,8 @@ pub const FIONBIO: c_ulong = 0x8004667e;
pub const MAX_PATH: usize = 260;
pub const FILE_TYPE_PIPE: u32 = 3;
#[repr(C)]
#[derive(Copy)]
pub struct WIN32_FIND_DATAW {
@ -1114,6 +1116,7 @@ extern "system" {
lpFileInformation: LPVOID,
dwBufferSize: DWORD,
) -> BOOL;
pub fn GetFileType(hfile: HANDLE) -> DWORD;
pub fn SleepConditionVariableSRW(
ConditionVariable: PCONDITION_VARIABLE,
SRWLock: PSRWLOCK,

View File

@ -120,6 +120,11 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
}
unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
// Early return if the handle is not a pipe.
if c::GetFileType(handle) != c::FILE_TYPE_PIPE {
return false;
}
const SIZE: usize = size_of::<c::FILE_NAME_INFO>() + c::MAX_PATH * size_of::<c::WCHAR>();
let mut name_info_bytes = Align8([0u8; SIZE]);
let res = c::GetFileInformationByHandleEx(
@ -137,11 +142,13 @@ unsafe fn msys_tty_on(handle: c::HANDLE) -> bool {
let name_ptr = name_info_bytes.0.as_ptr().offset(size_of::<c::DWORD>() as isize).cast::<u16>();
let s = core::slice::from_raw_parts(name_ptr, name_len);
let name = String::from_utf16_lossy(s);
// Get the file name only.
let name = name.rsplit('\\').next().unwrap_or(&name);
// This checks whether 'pty' exists in the file name, which indicates that
// a pseudo-terminal is attached. To mitigate against false positives
// (e.g., an actual file name that contains 'pty'), we also require that
// either the strings 'msys-' or 'cygwin-' are in the file name as well.)
let is_msys = name.contains("msys-") || name.contains("cygwin-");
// the file name begins with either the strings 'msys-' or 'cygwin-'.)
let is_msys = name.starts_with("msys-") || name.starts_with("cygwin-");
let is_pty = name.contains("-pty");
is_msys && is_pty
}