From 04c68b6790f017d2368e34014b1eb38f92406fa6 Mon Sep 17 00:00:00 2001 From: nickbeth Date: Sun, 10 Nov 2024 17:47:52 +0100 Subject: [PATCH] Replace transmuted references with explicit pointer type casts This commit replaces almost all usages of `std::mem::transmute` on references in the codebase with explicit pointer type casts. This is done to prevent undefined behavior caused by transmuting integer types to references, and subsequently dereferencing them. --- .../src/controls/date_picker.rs | 15 ++++---- .../src/controls/extern_canvas.rs | 7 ++-- native-windows-gui/src/controls/list_box.rs | 34 ++++++------------- native-windows-gui/src/controls/tabs.rs | 11 +++--- native-windows-gui/src/controls/window.rs | 7 ++-- .../src/resources/file_dialog.rs | 4 +-- native-windows-gui/src/win32/menu.rs | 5 +-- .../src/win32/resources_helper.rs | 10 +++--- native-windows-gui/src/win32/window.rs | 29 ++++++++++++---- native-windows-gui/src/win32/window_helper.rs | 7 ++-- 10 files changed, 67 insertions(+), 62 deletions(-) diff --git a/native-windows-gui/src/controls/date_picker.rs b/native-windows-gui/src/controls/date_picker.rs index 9b328718..b4fe3ca6 100644 --- a/native-windows-gui/src/controls/date_picker.rs +++ b/native-windows-gui/src/controls/date_picker.rs @@ -162,7 +162,7 @@ impl DatePicker { let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE); - let info = unsafe{ get_dtp_info(handle) }; + let info = get_dtp_info(handle); match info.stateCheck { STATE_SYSTEM_CHECKED => true, @@ -185,13 +185,15 @@ impl DatePicker { pub fn value(&self) -> Option { use winapi::um::commctrl::{GDT_VALID, DTM_GETSYSTEMTIME}; use winapi::um::minwinbase::SYSTEMTIME; + use winapi::shared::minwindef::LPARAM; use std::mem; let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE); let mut syst: SYSTEMTIME = unsafe{ mem::zeroed() }; + let syst_ptr = &mut syst as *mut _; - let r = unsafe{ wh::send_message(handle, DTM_GETSYSTEMTIME, 0, mem::transmute(&mut syst)) }; + let r = wh::send_message(handle, DTM_GETSYSTEMTIME, 0, syst_ptr as LPARAM); match r { GDT_VALID => Some(DatePickerValue { year: syst.wYear, @@ -488,14 +490,15 @@ impl<'a> DatePickerBuilder<'a> { use winapi::um::commctrl::DATETIMEPICKERINFO; use winapi::shared::windef::HWND; -unsafe fn get_dtp_info(handle: HWND) -> DATETIMEPICKERINFO { +fn get_dtp_info(handle: HWND) -> DATETIMEPICKERINFO { use winapi::um::commctrl::DTM_GETDATETIMEPICKERINFO; - use winapi::shared::minwindef::DWORD; + use winapi::shared::minwindef::{DWORD, LPARAM}; use std::mem; - let mut dtp_info: DATETIMEPICKERINFO = mem::zeroed(); + let mut dtp_info: DATETIMEPICKERINFO = unsafe { mem::zeroed() }; dtp_info.cbSize = mem::size_of::() as DWORD; - wh::send_message(handle, DTM_GETDATETIMEPICKERINFO, 0, mem::transmute(&mut dtp_info)); + let dtp_info_ptr = &mut dtp_info as *mut _; + wh::send_message(handle, DTM_GETDATETIMEPICKERINFO, 0, dtp_info_ptr as LPARAM); dtp_info } diff --git a/native-windows-gui/src/controls/extern_canvas.rs b/native-windows-gui/src/controls/extern_canvas.rs index 17bd5663..6ee15649 100644 --- a/native-windows-gui/src/controls/extern_canvas.rs +++ b/native-windows-gui/src/controls/extern_canvas.rs @@ -130,14 +130,13 @@ impl ExternCanvas { /// - icon: The new icon. If None, the icon is removed pub fn set_icon(&self, icon: Option<&Icon>) { use winapi::um::winuser::WM_SETICON; - use std::{mem, ptr}; + use winapi::shared::minwindef::LPARAM; + use std::ptr; let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE); let image_handle = icon.map(|i| i.handle).unwrap_or(ptr::null_mut()); - unsafe { - wh::send_message(handle, WM_SETICON, 0, mem::transmute(image_handle)); - } + wh::send_message(handle, WM_SETICON, 0, image_handle as LPARAM); } /// Return true if the control currently has the keyboard focus diff --git a/native-windows-gui/src/controls/list_box.rs b/native-windows-gui/src/controls/list_box.rs index 42fc17be..a9502081 100644 --- a/native-windows-gui/src/controls/list_box.rs +++ b/native-windows-gui/src/controls/list_box.rs @@ -106,9 +106,7 @@ impl ListBox { let display = format!("{}", item); let display_os = to_utf16(&display); - unsafe { - wh::send_message(handle, LB_ADDSTRING, 0, mem::transmute(display_os.as_ptr())); - } + wh::send_message(handle, LB_ADDSTRING, 0, display_os.as_ptr() as LPARAM); self.collection.borrow_mut().push(item); } @@ -131,9 +129,7 @@ impl ListBox { col.insert(index, item); } - unsafe { - wh::send_message(handle, LB_INSERTSTRING, index, mem::transmute(display_os.as_ptr())); - } + wh::send_message(handle, LB_INSERTSTRING, index, display_os.as_ptr() as LPARAM); } @@ -215,10 +211,8 @@ impl ListBox { let index = index as usize; let length = (wh::send_message(handle, LB_GETTEXTLEN, index, 0) as usize) + 1; // +1 for the terminating null character let mut buffer: Vec = Vec::with_capacity(length); - unsafe { - buffer.set_len(length); - wh::send_message(handle, LB_GETTEXT, index, mem::transmute(buffer.as_ptr())); - } + unsafe { buffer.set_len(length); } + wh::send_message(handle, LB_GETTEXT, index, buffer.as_ptr() as LPARAM); Some(from_utf16(&buffer)) } @@ -292,13 +286,11 @@ impl ListBox { let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE); let os_string = to_utf16(value); - unsafe { - let index = wh::send_message(handle, LB_SELECTSTRING, 0, mem::transmute(os_string.as_ptr())); - if index == LB_ERR { - None - } else { - Some(index as usize) - } + let index = wh::send_message(handle, LB_SELECTSTRING, 0, os_string.as_ptr() as LPARAM); + if index == LB_ERR { + None + } else { + Some(index as usize) } } @@ -327,9 +319,7 @@ impl ListBox { let display = format!("{}", item); let display_os = to_utf16(&display); - unsafe { - wh::send_message(handle, LB_ADDSTRING, 0, mem::transmute(display_os.as_ptr())); - } + wh::send_message(handle, LB_ADDSTRING, 0, display_os.as_ptr() as LPARAM); } } @@ -345,9 +335,7 @@ impl ListBox { let display = format!("{}", item); let display_os = to_utf16(&display); - unsafe { - wh::send_message(handle, LB_ADDSTRING, 0, mem::transmute(display_os.as_ptr())); - } + wh::send_message(handle, LB_ADDSTRING, 0, display_os.as_ptr() as LPARAM); } let mut col_ref = self.collection.borrow_mut(); diff --git a/native-windows-gui/src/controls/tabs.rs b/native-windows-gui/src/controls/tabs.rs index feafa8cf..b09246a9 100644 --- a/native-windows-gui/src/controls/tabs.rs +++ b/native-windows-gui/src/controls/tabs.rs @@ -5,6 +5,7 @@ use winapi::um::winuser::{EnumChildWindows, WS_VISIBLE, WS_DISABLED, WS_EX_CONTR use crate::win32::{base_helper::{to_utf16, check_hwnd}, window_helper as wh}; use crate::{NwgError, Font, RawEventHandler, unbind_raw_event_handler}; use super::{ControlBase, ControlHandle}; +use std::intrinsics::saturating_add; use std::{mem, cell::RefCell}; #[cfg(feature="image-list")] @@ -265,7 +266,7 @@ impl TabsContainer { let handler0 = bind_raw_event_handler_inner(&parent_handle, handle as usize, move |_hwnd, msg, _w, l| { unsafe { match msg { WM_NOTIFY => { - let nmhdr: &NMHDR = mem::transmute(l); + let nmhdr = &*(l as *const NMHDR); if nmhdr.code == TCN_SELCHANGE { let index = SendMessageW(handle, TCM_GETCURSEL, 0, 0) as i32; let data: (HWND, i32) = (handle, index); @@ -318,7 +319,7 @@ impl TabsContainer { data.tab_offset_y = tab_height; let data_ptr = &data as *const ResizeDirectChildrenParams; - EnumChildWindows(hwnd, Some(resize_direct_children), mem::transmute(data_ptr)); + EnumChildWindows(hwnd, Some(resize_direct_children), data_ptr as LPARAM); }, _ => {} } @@ -612,7 +613,7 @@ impl Tab { let count_ptr = &mut count as *mut usize; unsafe { - EnumChildWindows(tab_view_handle, Some(count_children), mem::transmute(count_ptr)); + EnumChildWindows(tab_view_handle, Some(count_children), count_ptr as LPARAM); } count @@ -757,7 +758,7 @@ unsafe extern "system" fn count_children(handle: HWND, params: LPARAM) -> BOOL { if &wh::get_window_class_name(handle) == "NWG_TAB" { let tab_index = (wh::get_window_long(handle, GWL_USERDATA)) as WPARAM; - let count: &mut usize = ::std::mem::transmute(params); + let count = params as *mut usize; *count = usize::max(tab_index+1, *count); } @@ -768,7 +769,7 @@ unsafe extern "system" fn count_children(handle: HWND, params: LPARAM) -> BOOL { unsafe extern "system" fn toggle_children_tabs(handle: HWND, params: LPARAM) -> BOOL { use winapi::um::winuser::GWL_USERDATA; - let &(parent, index): &(HWND, i32) = mem::transmute(params); + let (parent, index) = *(params as *const (HWND, i32)); if wh::get_window_parent(handle) == parent { let tab_index = wh::get_window_long(handle, GWL_USERDATA) as i32; let visible = tab_index == index + 1; diff --git a/native-windows-gui/src/controls/window.rs b/native-windows-gui/src/controls/window.rs index f653b2f2..a2622546 100644 --- a/native-windows-gui/src/controls/window.rs +++ b/native-windows-gui/src/controls/window.rs @@ -158,14 +158,13 @@ impl Window { /// - icon: The new icon. If None, the icon is removed pub fn set_icon(&self, icon: Option<&Icon>) { use winapi::um::winuser::WM_SETICON; - use std::{mem, ptr}; + use winapi::shared::minwindef::LPARAM; + use std::ptr; let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE); let image_handle = icon.map(|i| i.handle).unwrap_or(ptr::null_mut()); - unsafe { - wh::send_message(handle, WM_SETICON, 0, mem::transmute(image_handle)); - } + wh::send_message(handle, WM_SETICON, 0, image_handle as LPARAM); } /// Return true if the control currently has the keyboard focus diff --git a/native-windows-gui/src/resources/file_dialog.rs b/native-windows-gui/src/resources/file_dialog.rs index 95ccb74d..ef89e866 100644 --- a/native-windows-gui/src/resources/file_dialog.rs +++ b/native-windows-gui/src/resources/file_dialog.rs @@ -1,4 +1,4 @@ -use winapi::um::shobjidl::IFileDialog; +use winapi::um::shobjidl::{IFileDialog, IFileOpenDialog}; use crate::win32::resources_helper as rh; use crate::win32::base_helper::to_utf16; @@ -115,7 +115,7 @@ impl FileDialog { } unsafe { - rh::filedialog_get_items(mem::transmute(&mut *self.handle)) + rh::filedialog_get_items(&mut *(self.handle as *mut IFileOpenDialog)) } } diff --git a/native-windows-gui/src/win32/menu.rs b/native-windows-gui/src/win32/menu.rs index fb60e309..40b35041 100644 --- a/native-windows-gui/src/win32/menu.rs +++ b/native-windows-gui/src/win32/menu.rs @@ -1,6 +1,7 @@ /*! Native Windows GUI menu base. */ +use winapi::shared::basetsd::UINT_PTR; use winapi::shared::windef::{HMENU, HWND}; use winapi::shared::minwindef::UINT; use super::base_helper::{CUSTOM_ID_BEGIN, to_utf16}; @@ -70,7 +71,7 @@ pub unsafe fn build_hmenu_control(text: Option, item: bool, separator: b return Err(NwgError::menu_create("Menu without parent")); } use_menu_command(menu); - AppendMenuW(menubar, flags, mem::transmute(menu), text.as_ptr()); + AppendMenuW(menubar, flags, menu as UINT_PTR, text.as_ptr()); } // Draw the menu bar to make sure the changes are visible @@ -89,7 +90,7 @@ pub unsafe fn build_hmenu_control(text: Option, item: bool, separator: b return Err(NwgError::menu_create("Menu without parent")); } use_menu_command(menu); - AppendMenuW(parent, flags, mem::transmute(menu), text.as_ptr()); + AppendMenuW(parent, flags, menu as UINT_PTR, text.as_ptr()); } } diff --git a/native-windows-gui/src/win32/resources_helper.rs b/native-windows-gui/src/win32/resources_helper.rs index 027ef802..b8580454 100644 --- a/native-windows-gui/src/win32/resources_helper.rs +++ b/native-windows-gui/src/win32/resources_helper.rs @@ -349,6 +349,7 @@ pub unsafe fn create_file_dialog<'a, 'b>( use winapi::um::shobjidl::{FOS_PICKFOLDERS, FOS_ALLOWMULTISELECT, FOS_FORCEFILESYSTEM}; use winapi::um::combaseapi::CoCreateInstance; use winapi::shared::{wtypesbase::CLSCTX_INPROC_SERVER, winerror::S_OK}; + use winapi::shared::minwindef::LPVOID; let (clsid, uuid) = match action { FileDialogAction::Save => (CLSID_FileSaveDialog, IFileDialog::uuidof()), @@ -356,7 +357,7 @@ pub unsafe fn create_file_dialog<'a, 'b>( }; let mut handle: *mut IFileDialog = ptr::null_mut(); - let r = CoCreateInstance(&clsid, ptr::null_mut(), CLSCTX_INPROC_SERVER, &uuid, mem::transmute(&mut handle) ); + let r = CoCreateInstance(&clsid, ptr::null_mut(), CLSCTX_INPROC_SERVER, &uuid, &mut handle as *mut _ as *mut LPVOID); if r != S_OK { return Err(NwgError::file_dialog("Filedialog creation failed")); } @@ -418,7 +419,7 @@ pub unsafe fn file_dialog_set_default_folder<'a>(dialog: &mut IFileDialog, folde let mut shellitem: *mut IShellItem = ptr::null_mut(); let path = to_utf16(&folder_name); - if SHCreateItemFromParsingName(path.as_ptr(), ptr::null_mut(), &IShellItem::uuidof(), mem::transmute(&mut shellitem) ) != S_OK { + if SHCreateItemFromParsingName(path.as_ptr(), ptr::null_mut(), &IShellItem::uuidof(), &mut shellitem as *mut _ as *mut *mut c_void) != S_OK { return Err(NwgError::file_dialog("Failed to set default folder")); } @@ -504,7 +505,7 @@ pub unsafe fn filedialog_get_items(dialog: &mut IFileOpenDialog) -> Result Result Result { use winapi::um::shobjidl_core::SIGDN_FILESYSPATH; use winapi::shared::{ntdef::PWSTR, winerror::S_OK}; + use winapi::shared::minwindef::LPVOID; use winapi::um::combaseapi::CoTaskMemFree; use super::base_helper::os_string_from_wide_ptr; @@ -540,7 +542,7 @@ unsafe fn get_ishellitem_path(item: &mut IShellItem) -> Result { let code = { - let notif_ptr: *mut NMHDR = mem::transmute(l); + let notif_ptr = l as *mut NMHDR; (&*notif_ptr).code }; match code { - TTN_GETDISPINFOW => handle_tooltip_callback(mem::transmute::<_, *mut NMTTDISPINFOW>(l), callback), - _ => handle_default_notify_callback(mem::transmute::<_, *const NMHDR>(l), callback) + TTN_GETDISPINFOW => handle_tooltip_callback(l as *mut NMTTDISPINFOW, callback), + _ => handle_default_notify_callback(l as *const NMHDR, callback) } }, WM_MENUCOMMAND => { - let parent_handle: HMENU = mem::transmute(l); + let parent_handle = l as HMENU; let item_id = GetMenuItemID(parent_handle, w as i32); let handle = ControlHandle::MenuItem(parent_handle, item_id); callback(Event::OnMenuItemSelected, NO_DATA, handle); @@ -1074,7 +1074,12 @@ unsafe fn GetWindowSubclass(hwnd: HWND, proc: SUBCLASSPROC, uid: UINT_PTR, data: SUBCLASS_COLLECTION = Some(Mutex::new(HashMap::new())); } - let id = (hwnd as usize, mem::transmute(proc), uid); + let proc_id = match proc { + Some(p) => p as usize, + None => 0 + }; + + let id = (hwnd as usize, proc_id, uid); match SUBCLASS_COLLECTION.as_ref() { Some(collection_mutex) => { let collection = collection_mutex.lock().unwrap(); @@ -1096,7 +1101,12 @@ unsafe fn SetWindowSubclass(hwnd: HWND, proc: SUBCLASSPROC, uid: UINT_PTR, data: SUBCLASS_COLLECTION = Some(Mutex::new(HashMap::new())); } - let id = (hwnd as usize, mem::transmute(proc), uid); + let proc_id = match proc { + Some(p) => p as usize, + None => 0 + }; + + let id = (hwnd as usize, proc_id, uid); match SUBCLASS_COLLECTION.as_ref() { Some(collection_mutex) => { let mut collection = collection_mutex.lock().unwrap(); @@ -1119,7 +1129,12 @@ unsafe fn RemoveWindowSubclass(hwnd: HWND, proc: SUBCLASSPROC, uid: UINT_PTR) -> SUBCLASS_COLLECTION = Some(Mutex::new(HashMap::new())); } - let id = (hwnd as usize, mem::transmute(proc), uid); + let proc_id = match proc { + Some(p) => p as usize, + None => 0 + }; + + let id = (hwnd as usize, proc_id, uid); match SUBCLASS_COLLECTION.as_ref() { Some(collection_mutex) => { let mut collection = collection_mutex.lock().unwrap(); diff --git a/native-windows-gui/src/win32/window_helper.rs b/native-windows-gui/src/win32/window_helper.rs index 59ad057a..1f186607 100644 --- a/native-windows-gui/src/win32/window_helper.rs +++ b/native-windows-gui/src/win32/window_helper.rs @@ -169,10 +169,7 @@ pub fn get_window_parent(hwnd: HWND) -> HWND { pub fn get_window_font(handle: HWND) -> HFONT { use winapi::um::winuser::{ WM_GETFONT }; - unsafe { - let h = send_message(handle, WM_GETFONT, 0, 0); - mem::transmute(h) - } + send_message(handle, WM_GETFONT, 0, 0) as HFONT } pub fn maximize_window(handle: HWND) { @@ -203,7 +200,7 @@ pub unsafe fn set_window_font(handle: HWND, font_handle: Option, redraw: let font_handle = font_handle.unwrap_or(ptr::null_mut()); - SendMessageW(handle, WM_SETFONT, mem::transmute(font_handle), redraw as LPARAM); + SendMessageW(handle, WM_SETFONT, font_handle as WPARAM, redraw as LPARAM); }