mirror of
https://github.com/italicsjenga/rust_minifb.git
synced 2024-12-24 03:41:29 +11:00
Implemented bounds checking for update_with_buffer
This commit is contained in:
parent
6db90d717f
commit
900deba9a7
|
@ -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"
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
15
src/buffer_helper.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in a new issue