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]
name = "minifb"
version = "0.9.2"
version = "0.10.0"
license = "MIT/Apache-2.0"
authors = ["Daniel Collin <daniel@collin.com>"]
description = "Cross-platform window setup with optional bitmap rendering"

View file

@ -43,7 +43,8 @@ fn main() {
*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",
WIDTH,
HEIGHT,
HEIGHT + 2,
WindowOptions {
resize: true,
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);
});
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

@ -5,12 +5,14 @@ use std::fmt;
///
#[derive(Debug)]
pub enum Error {
/// Returned if menu Menu function isn't supported
/// Returned if menu Menu function isn't supported
MenusNotSupported,
/// Menu already exists
/// Menu already exists
MenuExists(String),
/// Menu already exists
/// Menu already exists
WindowCreate(String),
/// Unable to Update
UpdateFailed(String),
}
impl StdError for Error {
@ -18,7 +20,8 @@ impl StdError for Error {
match *self {
Error::MenusNotSupported => "Menus not supported",
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::MenuExists(_) => None,
Error::WindowCreate(_) => None,
Error::UpdateFailed(_) => None,
}
}
}
@ -43,6 +47,9 @@ impl fmt::Display for Error {
Error::WindowCreate(ref 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)]
pub mod os;
mod mouse_handler;
mod buffer_helper;
mod key_handler;
mod window_flags;
//mod menu;
@ -222,10 +223,10 @@ impl Window {
///
/// let mut window = match Window::new("Test", 640, 400, WindowOptions::default()).unwrap();
///
/// window.update_with_buffer(&buffer);
/// window.update_with_buffer(&buffer).unwrap();
/// ```
#[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)
}

View file

@ -7,6 +7,7 @@ use Result;
// use MenuItem;
use InputCallback;
use mouse_handler;
use buffer_helper;
use window_flags;
use {CursorStyle, MenuItem, MenuItemHandle, MenuHandle};
// use menu::Menu;
@ -291,9 +292,17 @@ impl Window {
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();
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 {
mfb_update_with_buffer(self.window_handle, buffer.as_ptr() as *const u8);
Self::set_mouse_data(self);
@ -302,6 +311,8 @@ impl Window {
key_callback,
char_callback);
}
Ok(())
}
pub fn update(&mut self) {

View file

@ -6,6 +6,7 @@ use os::redox::orbclient::Renderer;
use error::Error;
use Result;
use mouse_handler;
use buffer_height;
use key_handler::KeyHandler;
use InputCallback;
use {CursorStyle, MouseButton, MouseMode};
@ -100,11 +101,19 @@ impl Window {
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.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.window.sync();
Ok(())
}
pub fn update(&mut self) {

View file

@ -19,6 +19,7 @@ use std::ptr;
use std::mem;
use std::os::raw;
use mouse_handler;
use buffer_helper;
use window_flags;
#[link(name = "X11")]
@ -235,6 +236,14 @@ impl Window {
pub fn update_with_buffer(&mut self, buffer: &[u32]) {
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 {
Self::set_shared_data(self);
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::os::raw;
use mouse_handler;
use buffer_helper;
//use self::winapi::windef::HWND;
//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();
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();
unsafe {
user32::InvalidateRect(window, ptr::null_mut(), winapi::TRUE);
}
Self::message_loop(self, window);
Ok(())
}
pub fn update(&mut self) {