Decoder: check read buffer bounds for safety
This commit is contained in:
parent
572194c0f2
commit
dd2ed70e70
1 changed files with 14 additions and 8 deletions
|
@ -4,29 +4,30 @@ use crate::consts::{QOI_HEADER_SIZE, QOI_INDEX, QOI_MAGIC, QOI_PADDING};
|
||||||
use crate::error::{Error, Result};
|
use crate::error::{Error, Result};
|
||||||
use crate::header::Header;
|
use crate::header::Header;
|
||||||
use crate::pixel::{Pixel, SupportedChannels};
|
use crate::pixel::{Pixel, SupportedChannels};
|
||||||
|
use crate::utils::unlikely;
|
||||||
|
|
||||||
struct ReadBuf {
|
struct ReadBuf {
|
||||||
start: *const u8,
|
current: *const u8,
|
||||||
end: *const u8,
|
end: *const u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ReadBuf {
|
impl ReadBuf {
|
||||||
pub unsafe fn new(ptr: *const u8) -> Self {
|
pub unsafe fn new(ptr: *const u8, len: usize) -> Self {
|
||||||
Self { start: ptr, end: ptr }
|
Self { current: ptr, end: ptr.add(len) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read(&mut self) -> u8 {
|
pub fn read(&mut self) -> u8 {
|
||||||
unsafe {
|
unsafe {
|
||||||
let v = self.end.read();
|
let v = self.current.read();
|
||||||
self.end = self.end.add(1);
|
self.current = self.current.add(1);
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn len(&self) -> usize {
|
pub fn within_bounds(&self) -> bool {
|
||||||
unsafe { self.end.offset_from(self.start).max(0) as usize }
|
self.current < self.end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +56,10 @@ where
|
||||||
// Safety: we have just allocated enough memory to set the length without problems
|
// Safety: we have just allocated enough memory to set the length without problems
|
||||||
pixels.set_len(n_pixels);
|
pixels.set_len(n_pixels);
|
||||||
}
|
}
|
||||||
|
let mut encoded_data_size = data.len() - QOI_HEADER_SIZE - QOI_PADDING;
|
||||||
let mut buf = unsafe {
|
let mut buf = unsafe {
|
||||||
// Safety: we will check within the loop that there are no reads outside the slice
|
// Safety: we will check within the loop that there are no reads outside the slice
|
||||||
ReadBuf::new(data.as_ptr().add(QOI_HEADER_SIZE))
|
ReadBuf::new(data.as_ptr().add(QOI_HEADER_SIZE), encoded_data_size)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut index = [Pixel::new(); 64];
|
let mut index = [Pixel::new(); 64];
|
||||||
|
@ -65,6 +67,10 @@ where
|
||||||
let mut run = 0_u16;
|
let mut run = 0_u16;
|
||||||
|
|
||||||
for px_out in pixels.iter_mut() {
|
for px_out in pixels.iter_mut() {
|
||||||
|
if unlikely(!buf.within_bounds()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: check for safety that ReadBuf is not over yet
|
// TODO: check for safety that ReadBuf is not over yet
|
||||||
if run != 0 {
|
if run != 0 {
|
||||||
run -= 1;
|
run -= 1;
|
||||||
|
|
Loading…
Reference in a new issue