Remove the integer conversion macros and instead make it into a function named 'validate_int' (and start work on safely mutable rectangles)

This commit is contained in:
Machtan
2016-02-09 19:34:55 +01:00
parent 99a216ef96
commit 7ab11c5f28
7 changed files with 82 additions and 53 deletions
+4 -4
View File
@@ -5,7 +5,7 @@ use GameControllerSubsystem;
use SdlResult;
use get_error;
use joystick;
use util::CStringExt;
use util::{CStringExt, validate_int};
use sys::controller as ll;
use sys::event::{SDL_QUERY, SDL_ENABLE};
@@ -25,7 +25,7 @@ impl GameControllerSubsystem {
/// Return true if the joystick at index `id` is a game controller.
#[inline]
pub fn is_game_controller(&self, id: u32) -> bool {
match u32_to_int!(id) {
match validate_int(id) {
Ok(id) => unsafe { ll::SDL_IsGameController(id) != 0 },
Err(..) => false
}
@@ -36,7 +36,7 @@ impl GameControllerSubsystem {
/// maximum number can be retreived using the `SDL_NumJoysticks`
/// function.
pub fn open(&self, id: u32) -> SdlResult<GameController> {
let id = try!(u32_to_int!(id));
let id = try!(validate_int(id));
let controller = unsafe { ll::SDL_GameControllerOpen(id) };
@@ -52,7 +52,7 @@ impl GameControllerSubsystem {
/// Return the name of the controller at index `id`
pub fn name_for_index(&self, id: u32) -> SdlResult<String> {
let id = try!(u32_to_int!(id));
let id = try!(validate_int(id));
let name = unsafe { ll::SDL_GameControllerNameForIndex(id) };
c_str_to_string_or_err(name)
+8 -7
View File
@@ -8,6 +8,7 @@ use sys::event::{SDL_QUERY, SDL_ENABLE};
use std::ffi::{CString, CStr, NulError};
use std::fmt::{Display, Formatter, Error};
use libc::c_char;
use util::validate_int;
impl JoystickSubsystem {
/// Retreive the total number of attached joysticks *and* controllers identified by SDL.
@@ -23,7 +24,7 @@ impl JoystickSubsystem {
/// Attempt to open the joystick at number `id` and return it.
pub fn open(&self, id: u32) -> SdlResult<Joystick> {
let id = try!(u32_to_int!(id));
let id = try!(validate_int(id));
let joystick = unsafe { ll::SDL_JoystickOpen(id) };
@@ -39,7 +40,7 @@ impl JoystickSubsystem {
/// Return the name of the joystick at index `id`
pub fn name_for_index(&self, id: u32) -> SdlResult<String> {
let id = try!(u32_to_int!(id));
let id = try!(validate_int(id));
let name = unsafe { ll::SDL_JoystickNameForIndex(id) };
c_str_to_string_or_err(name)
@@ -47,7 +48,7 @@ impl JoystickSubsystem {
/// Get the GUID for the joystick number `id`
pub fn device_guid(&self, id: u32) -> SdlResult<Guid> {
let id = try!(u32_to_int!(id));
let id = try!(validate_int(id));
let raw = unsafe { ll::SDL_JoystickGetDeviceGUID(id) };
@@ -151,7 +152,7 @@ impl Joystick {
// get_error() returns a non-empty string.
clear_error();
let axis = try!(u32_to_int!(axis));
let axis = try!(validate_int(axis));
let pos = unsafe { ll::SDL_JoystickGetAxis(self.raw, axis) };
if pos != 0 {
@@ -187,7 +188,7 @@ impl Joystick {
// error...
clear_error();
let button = try!(u32_to_int!(button));
let button = try!(validate_int(button));
let pressed = unsafe { ll::SDL_JoystickGetButton(self.raw, button) };
match pressed {
@@ -225,7 +226,7 @@ impl Joystick {
let mut dx = 0;
let mut dy = 0;
let ball = try!(u32_to_int!(ball));
let ball = try!(validate_int(ball));
let result = unsafe { ll::SDL_JoystickGetBall(self.raw, ball, &mut dx, &mut dy) };
if result == 0 {
@@ -254,7 +255,7 @@ impl Joystick {
// have to use the same hack as `axis`...
clear_error();
let hat = try!(u32_to_int!(hat));
let hat = try!(validate_int(hat));
let result = unsafe { ll::SDL_JoystickGetHat(self.raw, hat) };
let state = HatState::from_raw(result as u8);
-25
View File
@@ -21,28 +21,3 @@ macro_rules! impl_raw_constructor(
)+
)
);
/// Many SDL functions will accept `int` values, even if it doesn't make sense for the values to be negative.
/// In the cases that SDL doesn't check negativity, passing negative values could be unsafe.
/// For example, `SDL_JoystickGetButton` uses the index argument to access an array without checking if it's negative,
/// which could potentially lead to segmentation faults.
macro_rules! u32_to_int(
($value:expr) => (
if $value >= 1<<31 { Err(format!("`{}` is out of bounds.", stringify!($value))) }
else { Ok($value as ::libc::c_int) }
)
);
macro_rules! usize_to_int(
($value:expr) => (
if $value >= 1<<31 { Err(format!("`{}` is out of bounds.", stringify!($value))) }
else { Ok($value as ::libc::c_int) }
)
);
macro_rules! int_to_u32(
($value:expr) => (
if $value < 0 { Err(format!("`{}` is out of bounds.", stringify!($value))) }
else { Ok($value as u32) }
)
);
+3 -2
View File
@@ -2,6 +2,7 @@ use sys::rect as ll;
use std::mem;
use std::ptr;
use std::ops::{BitAnd, BitOr};
use util::validate_int;
use SdlResult;
use ErrorMessage;
@@ -121,8 +122,8 @@ impl Rect {
/// If `width` or `height` is zero, `Ok(None)` is returned.
/// If the arguments violate any of the other rectangle invariants, an error is returned.
pub fn new(x: i32, y: i32, width: u32, height: u32) -> SdlResult<Option<Rect>> {
let width = try!(u32_to_int!(width));
let height = try!(u32_to_int!(height));
let width = try!(validate_int(width));
let height = try!(validate_int(height));
if x.checked_add(width).is_none() {
Err(ErrorMessage("`x` + `width` overflows.".into()))
+12 -11
View File
@@ -46,6 +46,7 @@ use std::ffi::CStr;
use num::FromPrimitive;
use std::vec::Vec;
use std::rc::Rc;
use util::validate_int;
use sys::render as ll;
@@ -173,7 +174,7 @@ impl RendererBuilder {
pub fn build(self) -> SdlResult<Renderer<'static>> {
let index = match self.index {
None => -1,
Some(index) => try!(u32_to_int!(index))
Some(index) => try!(validate_int(index))
};
let raw = unsafe {
ll::SDL_CreateRenderer(self.window.raw(), index, self.renderer_flags)
@@ -332,8 +333,8 @@ impl<'a> Renderer<'a> {
///
/// `size` is the width and height of the texture.
pub fn create_texture(&self, format: pixels::PixelFormatEnum, access: TextureAccess, (width, height): (u32, u32)) -> SdlResult<Texture> {
let width = try!(u32_to_int!(width));
let height = try!(u32_to_int!(height));
let width = try!(validate_int(width));
let height = try!(validate_int(height));
// If the pixel format is YUV 4:2:0 and planar, the width and height must
// be multiples-of-two. See issue #334 for details.
@@ -478,8 +479,8 @@ impl<'a> Renderer<'a> {
/// Sets a device independent resolution for rendering.
pub fn set_logical_size(&mut self, width: u32, height: u32) -> SdlResult<()> {
let width = try!(u32_to_int!(width));
let height = try!(u32_to_int!(height));
let width = try!(validate_int(width));
let height = try!(validate_int(height));
let result = unsafe { ll::SDL_RenderSetLogicalSize(self.raw, width, height) };
match result {
0 => Ok(()),
@@ -837,8 +838,8 @@ impl<'renderer> RenderTarget<'renderer> {
///
/// The old render target is returned if the function is successful.
pub fn create_and_set(&mut self, format: pixels::PixelFormatEnum, (width, height): (u32, u32)) -> SdlResult<Option<Texture>> {
let width = try!(u32_to_int!(width));
let height = try!(u32_to_int!(height));
let width = try!(validate_int(width));
let height = try!(validate_int(height));
let new_texture_raw = unsafe {
let access = ll::SDL_TEXTUREACCESS_TARGET;
@@ -1043,7 +1044,7 @@ impl Texture {
}
}
let pitch = try!(usize_to_int!(pitch));
let pitch = try!(validate_int(pitch as u32));
ll::SDL_UpdateTexture(self.raw, rect_raw_ptr, pixel_data.as_ptr() as *const _, pitch)
};
@@ -1103,9 +1104,9 @@ impl Texture {
return Err(ErrorMessage("One or more of the plane lengths is not correct (should be pitch * height).".into()));
}
let y_pitch = try!(usize_to_int!(y_pitch));
let u_pitch = try!(usize_to_int!(u_pitch));
let v_pitch = try!(usize_to_int!(v_pitch));
let y_pitch = try!(validate_int(y_pitch as u32));
let u_pitch = try!(validate_int(u_pitch as u32));
let v_pitch = try!(validate_int(v_pitch as u32));
unsafe {
let result = ll::SDL_UpdateYUVTexture(
+51
View File
@@ -1,8 +1,59 @@
use std::ffi::{CString, NulError};
use std::ops::Add;
use SdlResult;
use ErrorMessage;
/// Validates and converts the given u32 to a positive C integer.
pub fn validate_int(value: u32) -> Result<::libc::c_int, String> {
// Many SDL functions will accept `int` values, even if it doesn't make sense
// for the values to be negative.
// In the cases that SDL doesn't check negativity, passing negative values
// could be unsafe.
// For example, `SDL_JoystickGetButton` uses the index argument to access an
// array without checking if it's negative, which could potentially lead to
// segmentation faults.
if value >= 1 << 31 {
Err(format!("`{}` is out of bounds.", value))
} else {
Ok(value as ::libc::c_int)
}
}
pub struct CheckedInteger {
value: u32,
}
impl CheckedInteger {
pub fn new(value: u32) -> Result<CheckedInteger, String> {
if value >= 1 << 31 {
Err(format!("The value '{}' is too big for a C int.", value))
} else {
Ok(CheckedInteger { value: value } )
}
}
pub fn add(&self, value: u32) -> Result<CheckedInteger, String> {
if let Some(new) = self.value.checked_add(value) {
CheckedInteger::new(new)
} else {
Err("The combined value overflowed".to_owned())
}
}
pub fn sub(&self, value: u32) -> Result<CheckedInteger, String> {
if let Some(new) = self.value.checked_add(value) {
CheckedInteger::new(new)
} else {
Err("The combined value underflowed".to_owned())
}
}
pub fn value(&self) -> u32 {
self.value
}
}
pub trait CStringExt {
/// Returns an SDL error if the string contains a nul byte.
fn unwrap_or_sdlresult(self) -> SdlResult<CString>;
+4 -4
View File
@@ -14,7 +14,7 @@ use EventPump;
use SdlResult;
use ErrorMessage;
use num::FromPrimitive;
use util::CStringExt;
use util::{CStringExt, validate_int};
use get_error;
@@ -972,7 +972,7 @@ impl WindowRef {
}
pub fn set_size(&mut self, w: u32, h: u32) {
match (u32_to_int!(w), u32_to_int!(h)) {
match (validate_int(w), validate_int(h)) {
(Ok(w), Ok(h)) => unsafe { ll::SDL_SetWindowSize(self.raw(), w, h) },
_ => () // silently fail (`SDL_SetWindowSize` returns void)
}
@@ -993,7 +993,7 @@ impl WindowRef {
}
pub fn set_minimum_size(&mut self, w: u32, h: u32) {
match (u32_to_int!(w), u32_to_int!(h)) {
match (validate_int(w), validate_int(h)) {
(Ok(w), Ok(h)) => unsafe { ll::SDL_SetWindowMinimumSize(self.raw(), w, h) },
_ => () // silently fail (`SDL_SetWindowMinimumSize` returns void)
}
@@ -1007,7 +1007,7 @@ impl WindowRef {
}
pub fn set_maximum_size(&mut self, w: u32, h: u32) {
match (u32_to_int!(w), u32_to_int!(h)) {
match (validate_int(w), validate_int(h)) {
(Ok(w), Ok(h)) => unsafe { ll::SDL_SetWindowMaximumSize(self.raw(), w, h) },
_ => () // silently fail (`SDL_SetWindowMaximumSize` returns void)
}