Skip to content

Commit

Permalink
Fix unsoundness in msys_tty_on (#183)
Browse files Browse the repository at this point in the history
  • Loading branch information
LingMan authored Jan 9, 2024
1 parent c17fda2 commit ef2d442
Showing 1 changed file with 25 additions and 13 deletions.
38 changes: 25 additions & 13 deletions src/windows_term/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -527,22 +524,37 @@ pub fn msys_tty_on(term: &Term) -> bool {
}
}

let size = mem::size_of::<FILE_NAME_INFO>();
let mut name_info_bytes = vec![0u8; size + MAX_PATH as usize * mem::size_of::<u16>()];
/// 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::<FILE_NAME_INFO>() 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
Expand Down

0 comments on commit ef2d442

Please sign in to comment.