From ef2d4428d63cc45ef0099916af0082d28a58ada1 Mon Sep 17 00:00:00 2001 From: LingMan Date: Tue, 9 Jan 2024 16:29:50 +0100 Subject: [PATCH] Fix unsoundness in `msys_tty_on` (#183) --- src/windows_term/mod.rs | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/windows_term/mod.rs b/src/windows_term/mod.rs index 4d9ded03..173f3ef5 100644 --- a/src/windows_term/mod.rs +++ b/src/windows_term/mod.rs @@ -8,15 +8,12 @@ use std::mem; use std::os::raw::c_void; use std::os::windows::ffi::OsStrExt; use std::os::windows::io::AsRawHandle; -use std::slice; use std::{char, mem::MaybeUninit}; use encode_unicode::error::InvalidUtf16Tuple; use encode_unicode::CharExt; use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE, MAX_PATH}; -use windows_sys::Win32::Storage::FileSystem::{ - FileNameInfo, GetFileInformationByHandleEx, FILE_NAME_INFO, -}; +use windows_sys::Win32::Storage::FileSystem::{FileNameInfo, GetFileInformationByHandleEx}; use windows_sys::Win32::System::Console::{ FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetConsoleCursorInfo, GetConsoleMode, GetConsoleScreenBufferInfo, GetNumberOfConsoleInputEvents, GetStdHandle, ReadConsoleInputW, @@ -527,22 +524,37 @@ pub fn msys_tty_on(term: &Term) -> bool { } } - let size = mem::size_of::(); - let mut name_info_bytes = vec![0u8; size + MAX_PATH as usize * mem::size_of::()]; + /// Mirrors windows_sys::Win32::Storage::FileSystem::FILE_NAME_INFO, giving + /// it a fixed length that we can stack allocate + #[repr(C)] + #[allow(non_snake_case)] + struct FILE_NAME_INFO { + FileNameLength: u32, + FileName: [u16; MAX_PATH as usize], + } + + let mut name_info = FILE_NAME_INFO { + FileNameLength: 0, + FileName: [0; MAX_PATH as usize], + }; let res = GetFileInformationByHandleEx( handle as HANDLE, FileNameInfo, - &mut *name_info_bytes as *mut _ as *mut c_void, - name_info_bytes.len() as u32, + &mut name_info as *mut _ as *mut c_void, + std::mem::size_of::() as u32, ); if res == 0 { return false; } - let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO); - let s = slice::from_raw_parts( - name_info.FileName.as_ptr(), - name_info.FileNameLength as usize / 2, - ); + + // Use `get` because `FileNameLength` can be out of range. + let s = match name_info + .FileName + .get(..name_info.FileNameLength as usize / 2) + { + Some(s) => s, + None => return false, + }; let name = String::from_utf16_lossy(s); // This checks whether 'pty' exists in the file name, which indicates that // a pseudo-terminal is attached. To mitigate against false positives