Implemented bounds checking for update_with_buffer

This commit is contained in:
Daniel Collin 2017-08-11 12:41:24 +02:00
parent 6db90d717f
commit 900deba9a7
13 changed files with 84 additions and 16 deletions

View file

@ -1,6 +1,6 @@
[package] [package]
name = "minifb" name = "minifb"
version = "0.9.2" version = "0.10.0"
license = "MIT/Apache-2.0" license = "MIT/Apache-2.0"
authors = ["Daniel Collin <daniel@collin.com>"] authors = ["Daniel Collin <daniel@collin.com>"]
description = "Cross-platform window setup with optional bitmap rendering" description = "Cross-platform window setup with optional bitmap rendering"

View file

@ -43,7 +43,8 @@ fn main() {
*i = 0; // write something more funny here! *i = 0; // write something more funny here!
} }
window.update_with_buffer(&buffer); // We unwrap here as we want this code to exit if it fails. Real applications may want to handle this in a different way
window.update_with_buffer(&buffer).unwrap();
} }
} }
``` ```

View file

@ -26,7 +26,7 @@ fn main() {
let mut window = Window::new("Menu Test - Press ESC to exit", let mut window = Window::new("Menu Test - Press ESC to exit",
WIDTH, WIDTH,
HEIGHT, HEIGHT + 2,
WindowOptions { WindowOptions {
resize: true, resize: true,
scale: Scale::X2, scale: Scale::X2,
@ -98,6 +98,7 @@ fn main() {
} }
}); });
window.update_with_buffer(&buffer); // We unwrap here as we want this code to exit if it fails
window.update_with_buffer(&buffer).unwrap();
} }
} }

View file

@ -38,6 +38,7 @@ fn main() {
println!("Scrolling {} - {}", scroll.0, scroll.1); println!("Scrolling {} - {}", scroll.0, scroll.1);
}); });
window.update_with_buffer(&buffer); // We unwrap here as we want this code to exit if it fails
window.update_with_buffer(&buffer).unwrap();
} }
} }

View file

@ -48,6 +48,7 @@ fn main() {
} }
}); });
window.update_with_buffer(&buffer); // We unwrap here as we want this code to exit if it fails
window.update_with_buffer(&buffer).unwrap();
} }
} }

View file

@ -73,7 +73,8 @@ fn main() {
} }
} }
window.update_with_buffer(&buffer); // We unwrap here as we want this code to exit if it fails
window.update_with_buffer(&buffer).unwrap();
} }
} }

15
src/buffer_helper.rs Normal file
View file

@ -0,0 +1,15 @@
use error::Error;
use Result;
pub fn check_buffer_size(window_width: usize, window_height: usize, scale: usize, buffer: &[u32]) -> Result<()> {
let buffer_size = buffer.len() * 4; // len is the number of entries so * 4 as we want bytes
let required_buffer_size = (window_width / scale) * (window_height / scale) * 4; // * 4 for 32-bit buffer
if buffer_size < required_buffer_size {
let err = format!("Update failed because input buffer is too small. Required size for {} x {} window ({}x scale) is {} bytes but the size of the input buffer has the size {} bytes",
window_width, window_height, scale, required_buffer_size, buffer_size);
Err(Error::UpdateFailed(err))
} else {
Ok(())
}
}

View file

@ -11,6 +11,8 @@ pub enum Error {
MenuExists(String), MenuExists(String),
/// Menu already exists /// Menu already exists
WindowCreate(String), WindowCreate(String),
/// Unable to Update
UpdateFailed(String),
} }
impl StdError for Error { impl StdError for Error {
@ -18,7 +20,8 @@ impl StdError for Error {
match *self { match *self {
Error::MenusNotSupported => "Menus not supported", Error::MenusNotSupported => "Menus not supported",
Error::MenuExists(_) => "Menu already exists", Error::MenuExists(_) => "Menu already exists",
Error::WindowCreate(_) => "Failed to create Window", Error::WindowCreate(_) => "Failed to create window",
Error::UpdateFailed(_) => "Failed to Update",
} }
} }
@ -27,6 +30,7 @@ impl StdError for Error {
Error::MenusNotSupported => None, Error::MenusNotSupported => None,
Error::MenuExists(_) => None, Error::MenuExists(_) => None,
Error::WindowCreate(_) => None, Error::WindowCreate(_) => None,
Error::UpdateFailed(_) => None,
} }
} }
} }
@ -43,6 +47,9 @@ impl fmt::Display for Error {
Error::WindowCreate(ref e) => { Error::WindowCreate(ref e) => {
write!(fmt, "{} {:?}", self.description(), e) write!(fmt, "{} {:?}", self.description(), e)
} }
Error::UpdateFailed(ref e) => {
write!(fmt, "{} {:?}", self.description(), e)
}
} }
} }
} }

View file

@ -100,6 +100,7 @@ pub use key::Key as Key;
#[doc(hidden)] #[doc(hidden)]
pub mod os; pub mod os;
mod mouse_handler; mod mouse_handler;
mod buffer_helper;
mod key_handler; mod key_handler;
mod window_flags; mod window_flags;
//mod menu; //mod menu;
@ -222,10 +223,10 @@ impl Window {
/// ///
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap(); /// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
/// ///
/// window.update_with_buffer(&buffer); /// window.update_with_buffer(&buffer).unwrap();
/// ``` /// ```
#[inline] #[inline]
pub fn update_with_buffer(&mut self, buffer: &[u32]) { pub fn update_with_buffer(&mut self, buffer: &[u32]) -> Result<()> {
self.0.update_with_buffer(buffer) self.0.update_with_buffer(buffer)
} }

View file

@ -7,6 +7,7 @@ use Result;
// use MenuItem; // use MenuItem;
use InputCallback; use InputCallback;
use mouse_handler; use mouse_handler;
use buffer_helper;
use window_flags; use window_flags;
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle}; use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
// use menu::Menu; // use menu::Menu;
@ -291,9 +292,17 @@ impl Window {
mfb_set_mouse_data(self.window_handle, &mut self.shared_data); mfb_set_mouse_data(self.window_handle, &mut self.shared_data);
} }
pub fn update_with_buffer(&mut self, buffer: &[u32]) { pub fn update_with_buffer(&mut self, buffer: &[u32]) -> Result<()> {
self.key_handler.update(); self.key_handler.update();
let check_res = buffer_helper::check_buffer_size(self.shared_data.width as usize,
self.shared_data.height as usize,
self.scale_factor as usize,
buffer);
if check_res.is_err() {
return check_res;
}
unsafe { unsafe {
mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8); mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8);
Self::set_mouse_data(self); Self::set_mouse_data(self);
@ -302,6 +311,8 @@ impl Window {
key_callback, key_callback,
char_callback); char_callback);
} }
Ok(())
} }
pub fn update(&mut self) { pub fn update(&mut self) {

View file

@ -6,6 +6,7 @@ use os::redox::orbclient::Renderer;
use error::Error; use error::Error;
use Result; use Result;
use mouse_handler; use mouse_handler;
use buffer_height;
use key_handler::KeyHandler; use key_handler::KeyHandler;
use InputCallback; use InputCallback;
use {CursorStyle, MouseButton, MouseMode}; use {CursorStyle, MouseButton, MouseMode};
@ -100,11 +101,19 @@ impl Window {
0 as *mut raw::c_void 0 as *mut raw::c_void
} }
pub fn update_with_buffer(&mut self, buffer: &[u32]) { pub fn update_with_buffer(&mut self, buffer: &[u32]) -> Result<()> {
self.process_events(); self.process_events();
self.key_handler.update(); self.key_handler.update();
let check_res = buffer_helper::check_buffer_size(self.buffer_width, self.buffer_height, self.window_scale, buffer);
if check_res.is_err() {
return check_res;
}
self.render_buffer(buffer); self.render_buffer(buffer);
self.window.sync(); self.window.sync();
Ok(())
} }
pub fn update(&mut self) { pub fn update(&mut self) {

View file

@ -19,6 +19,7 @@ use std::ptr;
use std::mem; use std::mem;
use std::os::raw; use std::os::raw;
use mouse_handler; use mouse_handler;
use buffer_helper;
use window_flags; use window_flags;
#[link(name = "X11")] #[link(name = "X11")]
@ -235,6 +236,14 @@ impl Window {
pub fn update_with_buffer(&mut self, buffer: &[u32]) { pub fn update_with_buffer(&mut self, buffer: &[u32]) {
self.key_handler.update(); self.key_handler.update();
let check_res = buffer_helper::check_buffer_size(self.shared_data.width as usize,
self.shared_data.height as usize,
self.scale_factor as usize,
buffer);
if check_res.is_err() {
return check_res;
}
unsafe { unsafe {
Self::set_shared_data(self); Self::set_shared_data(self);
mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8); mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8);

View file

@ -21,6 +21,7 @@ use std::ffi::OsStr;
use std::mem; use std::mem;
use std::os::raw; use std::os::raw;
use mouse_handler; use mouse_handler;
use buffer_helper;
//use self::winapi::windef::HWND; //use self::winapi::windef::HWND;
//use self::winapi::windef::HDC; //use self::winapi::windef::HDC;
@ -634,17 +635,27 @@ impl Window {
} }
} }
pub fn update_with_buffer(&mut self, buffer: &[u32]) { pub fn update_with_buffer(&mut self, buffer: &[u32]) -> Result<()> {
let window = self.window.unwrap(); let window = self.window.unwrap();
Self::generic_update(self, window); Self::generic_update(self, window);
let check_res = buffer_helper::check_buffer_size(self.width as usize,
self.height as usize,
self.scale_factor as usize,
buffer);
if check_res.is_err() {
return check_res;
}
self.buffer = buffer.to_vec(); self.buffer = buffer.to_vec();
unsafe { unsafe {
user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE); user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE);
} }
Self::message_loop(self, window); Self::message_loop(self, window);
Ok(())
} }
pub fn update(&mut self) { pub fn update(&mut self) {