diff --git a/changelog.md b/changelog.md index 10565424f1e..8763ecb87bf 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,8 @@ when upgrading from a version of rust-sdl2 to another. ### Unreleased +[PR #1389](https://github.com/Rust-SDL2/rust-sdl2/pull/1389) Fix some undefined behavior. + [PR #1378](https://github.com/Rust-SDL2/rust-sdl2/pull/1378) **BREAKING CHANGE** Change `Keycode` to be a struct rather than an enum. Fix `Keycode::from_scancode` for non-QWERTY keyboard layouts. [PR #1368](https://github.com/Rust-SDL2/rust-sdl2/pull/1368) Remove unnecessary unsafe in Window interface. Make Window `Clone`. diff --git a/sdl2-sys/examples/no_std.rs b/sdl2-sys/examples/no_std.rs index f0acfdf1035..16fedb751ed 100644 --- a/sdl2-sys/examples/no_std.rs +++ b/sdl2-sys/examples/no_std.rs @@ -11,7 +11,9 @@ fn main() { panic!("failed to initialize sdl2 with video"); }; _window = SDL_CreateWindow( - b"hello_sdl2" as *const _ as *const i8, + // If you use Rust 1.77 or newer, you can also use a C string literal + // c"hello_sdl2".as_ptr(), + b"hello_sdl2\0".as_ptr() as *const i8, SDL_WINDOWPOS_UNDEFINED_MASK as i32, SDL_WINDOWPOS_UNDEFINED_MASK as i32, 640, diff --git a/src/sdl2/log.rs b/src/sdl2/log.rs index 2303d89a38b..6e62d8de03a 100644 --- a/src/sdl2/log.rs +++ b/src/sdl2/log.rs @@ -101,6 +101,6 @@ pub fn log(message: &str) { let message = message.replace('%', "%%"); let message = CString::new(message).unwrap(); unsafe { - crate::sys::SDL_Log(message.into_raw()); + crate::sys::SDL_Log(message.as_ptr()); } } diff --git a/src/sdl2/pixels.rs b/src/sdl2/pixels.rs index 5cca5a0e509..ee08cf20118 100644 --- a/src/sdl2/pixels.rs +++ b/src/sdl2/pixels.rs @@ -49,14 +49,9 @@ impl Palette { // Already validated, so don't check again let ncolors = colors.len() as ::libc::c_int; - let result = unsafe { - let mut raw_colors: Vec = - colors.iter().map(|color| color.raw()).collect(); - - let pal_ptr = (&mut raw_colors[0]) as *mut sys::SDL_Color; + let colors = colors.iter().map(|color| color.raw()).collect::>(); - sys::SDL_SetPaletteColors(pal.raw, pal_ptr, 0, ncolors) - }; + let result = unsafe { sys::SDL_SetPaletteColors(pal.raw, colors.as_ptr(), 0, ncolors) }; if result < 0 { Err(get_error()) diff --git a/src/sdl2/rect.rs b/src/sdl2/rect.rs index aa3a9bf1835..87428654fc3 100644 --- a/src/sdl2/rect.rs +++ b/src/sdl2/rect.rs @@ -75,6 +75,9 @@ fn clamp_f32_size(val: f32) -> f32 { /// recommended to use `Option`, with `None` representing an empty /// rectangle (see, for example, the output of the /// [`intersection`](#method.intersection) method). +// Uses repr(transparent) to allow pointer casting between Rect and SDL_Rect (see +// `Rect::raw_slice`) +#[repr(transparent)] #[derive(Clone, Copy)] pub struct Rect { raw: sys::SDL_Rect, @@ -490,7 +493,7 @@ impl Rect { } pub fn raw_mut(&mut self) -> *mut sys::SDL_Rect { - self.raw() as *mut _ + &mut self.raw } #[doc(alias = "SDL_Rect")] @@ -736,6 +739,9 @@ impl BitOr for Rect { } /// Immutable point type, consisting of x and y. +// Uses repr(transparent) to allow pointer casting between Point and SDL_Point (see +// `Point::raw_slice`) +#[repr(transparent)] #[derive(Copy, Clone)] pub struct Point { raw: sys::SDL_Point, diff --git a/src/sdl2/render.rs b/src/sdl2/render.rs index 96abd52422d..ab54da0e205 100644 --- a/src/sdl2/render.rs +++ b/src/sdl2/render.rs @@ -1693,37 +1693,35 @@ impl Canvas { rect: R, format: pixels::PixelFormatEnum, ) -> Result, String> { - unsafe { - let rect = rect.into(); - let (actual_rect, w, h) = match rect { - Some(ref rect) => (rect.raw(), rect.width() as usize, rect.height() as usize), - None => { - let (w, h) = self.output_size()?; - (ptr::null(), w as usize, h as usize) - } - }; + let rect = rect.into(); + let (actual_rect, w, h) = match rect { + Some(ref rect) => (rect.raw(), rect.width() as usize, rect.height() as usize), + None => { + let (w, h) = self.output_size()?; + (ptr::null(), w as usize, h as usize) + } + }; - let pitch = w * format.byte_size_per_pixel(); // calculated pitch - let size = format.byte_size_of_pixels(w * h); - let mut pixels = Vec::with_capacity(size); - pixels.set_len(size); - - // Pass the interior of `pixels: Vec` to SDL - let ret = { - sys::SDL_RenderReadPixels( - self.context.raw, - actual_rect, - format as u32, - pixels.as_mut_ptr() as *mut c_void, - pitch as c_int, - ) - }; + let pitch = w * format.byte_size_per_pixel(); // calculated pitch + let size = format.byte_size_of_pixels(w * h); + let mut pixels = Vec::with_capacity(size); - if ret == 0 { - Ok(pixels) - } else { - Err(get_error()) - } + // Pass the interior of `pixels: Vec` to SDL + let ret = unsafe { + sys::SDL_RenderReadPixels( + self.context.raw, + actual_rect, + format as u32, + pixels.as_mut_ptr() as *mut c_void, + pitch as c_int, + ) + }; + + if ret == 0 { + unsafe { pixels.set_len(size) }; + Ok(pixels) + } else { + Err(get_error()) } } diff --git a/src/sdl2/rwops.rs b/src/sdl2/rwops.rs index 33478137f89..717df5cf4ef 100644 --- a/src/sdl2/rwops.rs +++ b/src/sdl2/rwops.rs @@ -4,7 +4,6 @@ use libc::{c_char, c_int, size_t}; use std::ffi::CString; use std::io; use std::marker::PhantomData; -use std::mem::transmute; use std::path::Path; use crate::sys; @@ -179,7 +178,7 @@ impl<'a> io::Seek for RWops<'a> { io::SeekFrom::End(pos) => (sys::RW_SEEK_END, pos), io::SeekFrom::Current(pos) => (sys::RW_SEEK_CUR, pos), }; - let ret = unsafe { ((*self.raw).seek.unwrap())(self.raw, offset, transmute(whence)) }; + let ret = unsafe { ((*self.raw).seek.unwrap())(self.raw, offset, whence as i32) }; if ret == -1 { Err(io::Error::last_os_error()) } else { diff --git a/src/sdl2/ttf/font.rs b/src/sdl2/ttf/font.rs index d99686b912a..9f000752ba8 100644 --- a/src/sdl2/ttf/font.rs +++ b/src/sdl2/ttf/font.rs @@ -361,18 +361,12 @@ impl<'ttf, 'r> Font<'ttf, 'r> { /// Returns the width and height of the given text when rendered using this /// font. - #[allow(unused_mut)] pub fn size_of_latin1(&self, text: &[u8]) -> FontResult<(u32, u32)> { let c_string = RenderableText::Latin1(text).convert()?; let (res, size) = unsafe { - let mut w: i32 = 0; // mutated by C code - let mut h: i32 = 0; // mutated by C code - let ret = ttf::TTF_SizeText( - self.raw, - c_string.as_ptr(), - &w as *const _ as *mut i32, - &h as *const _ as *mut i32, - ); + let mut w: i32 = 0; + let mut h: i32 = 0; + let ret = ttf::TTF_SizeText(self.raw, c_string.as_ptr(), &mut w, &mut h); (ret, (w as u32, h as u32)) }; if res == 0 { @@ -510,20 +504,21 @@ impl<'ttf, 'r> Font<'ttf, 'r> { /// Returns the glyph metrics of the given character in this font face. pub fn find_glyph_metrics(&self, ch: char) -> Option { - let minx = 0; - let maxx = 0; - let miny = 0; - let maxy = 0; - let advance = 0; + let mut minx = 0; + let mut maxx = 0; + let mut miny = 0; + let mut maxy = 0; + let mut advance = 0; + let ret = unsafe { ttf::TTF_GlyphMetrics( self.raw, ch as u16, - &minx as *const _ as *mut _, - &maxx as *const _ as *mut _, - &miny as *const _ as *mut _, - &maxy as *const _ as *mut _, - &advance as *const _ as *mut _, + &mut minx, + &mut maxx, + &mut miny, + &mut maxy, + &mut advance, ) }; if ret == 0 {