Skip to content

Commit ef2d442

Browse files
authored
Fix unsoundness in msys_tty_on (#183)
1 parent c17fda2 commit ef2d442

File tree

1 file changed

+25
-13
lines changed

1 file changed

+25
-13
lines changed

src/windows_term/mod.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ use std::mem;
88
use std::os::raw::c_void;
99
use std::os::windows::ffi::OsStrExt;
1010
use std::os::windows::io::AsRawHandle;
11-
use std::slice;
1211
use std::{char, mem::MaybeUninit};
1312

1413
use encode_unicode::error::InvalidUtf16Tuple;
1514
use encode_unicode::CharExt;
1615
use windows_sys::Win32::Foundation::{HANDLE, INVALID_HANDLE_VALUE, MAX_PATH};
17-
use windows_sys::Win32::Storage::FileSystem::{
18-
FileNameInfo, GetFileInformationByHandleEx, FILE_NAME_INFO,
19-
};
16+
use windows_sys::Win32::Storage::FileSystem::{FileNameInfo, GetFileInformationByHandleEx};
2017
use windows_sys::Win32::System::Console::{
2118
FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetConsoleCursorInfo, GetConsoleMode,
2219
GetConsoleScreenBufferInfo, GetNumberOfConsoleInputEvents, GetStdHandle, ReadConsoleInputW,
@@ -527,22 +524,37 @@ pub fn msys_tty_on(term: &Term) -> bool {
527524
}
528525
}
529526

530-
let size = mem::size_of::<FILE_NAME_INFO>();
531-
let mut name_info_bytes = vec![0u8; size + MAX_PATH as usize * mem::size_of::<u16>()];
527+
/// Mirrors windows_sys::Win32::Storage::FileSystem::FILE_NAME_INFO, giving
528+
/// it a fixed length that we can stack allocate
529+
#[repr(C)]
530+
#[allow(non_snake_case)]
531+
struct FILE_NAME_INFO {
532+
FileNameLength: u32,
533+
FileName: [u16; MAX_PATH as usize],
534+
}
535+
536+
let mut name_info = FILE_NAME_INFO {
537+
FileNameLength: 0,
538+
FileName: [0; MAX_PATH as usize],
539+
};
532540
let res = GetFileInformationByHandleEx(
533541
handle as HANDLE,
534542
FileNameInfo,
535-
&mut *name_info_bytes as *mut _ as *mut c_void,
536-
name_info_bytes.len() as u32,
543+
&mut name_info as *mut _ as *mut c_void,
544+
std::mem::size_of::<FILE_NAME_INFO>() as u32,
537545
);
538546
if res == 0 {
539547
return false;
540548
}
541-
let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO);
542-
let s = slice::from_raw_parts(
543-
name_info.FileName.as_ptr(),
544-
name_info.FileNameLength as usize / 2,
545-
);
549+
550+
// Use `get` because `FileNameLength` can be out of range.
551+
let s = match name_info
552+
.FileName
553+
.get(..name_info.FileNameLength as usize / 2)
554+
{
555+
Some(s) => s,
556+
None => return false,
557+
};
546558
let name = String::from_utf16_lossy(s);
547559
// This checks whether 'pty' exists in the file name, which indicates that
548560
// a pseudo-terminal is attached. To mitigate against false positives

0 commit comments

Comments
 (0)