more concise range error handling
parent
8d504612cb
commit
25488e7faa
|
@ -156,17 +156,26 @@ macro_rules! _durandal_read_impl {
|
|||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export(local_inner_macros)]
|
||||
#[macro_export]
|
||||
macro_rules! read_data {
|
||||
(
|
||||
$sz:expr , $ty:ident in $b:ident =>
|
||||
$( $nam:ident = $t:ident [ $n:expr ] $( $ex:ident )* ; )*
|
||||
) => {
|
||||
$crate::check_data!($sz, $b);
|
||||
$($crate::_durandal_read_impl!($ty $b $nam $($ex)* $t $n);)*
|
||||
};
|
||||
}
|
||||
|
||||
/// Checks if there is enough data in `b`.
|
||||
#[macro_export]
|
||||
macro_rules! check_data {
|
||||
(
|
||||
$sz:expr , $b:ident
|
||||
) => {
|
||||
if $b.len() < $sz {
|
||||
return Err(err_msg("not enough data"));
|
||||
}
|
||||
|
||||
$($crate::_durandal_read_impl!($ty $b $nam $($ex)* $t $n);)*
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -360,11 +369,7 @@ pub fn rd_ofstable<T, F>(b: &[u8],
|
|||
|
||||
for _ in 0..num {
|
||||
let ofs = usize_from_u32(u32b(&b[p..p + 4]));
|
||||
|
||||
if ofs >= b.len() {
|
||||
bail!("not enough data");
|
||||
}
|
||||
|
||||
check_data!(ofs, b);
|
||||
v.push(read(&b[ofs..])?);
|
||||
p += 4;
|
||||
}
|
||||
|
|
|
@ -2,53 +2,49 @@
|
|||
|
||||
use crate::durandal::err::*;
|
||||
|
||||
/// Reads `width` bits from `b` starting at bit `cr_ptr` into an integer.
|
||||
/// Reads `width` bits from `b` starting at bit `cr_bit` into an integer.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// The function will return an error if `width` is 0 or more than 64, or if
|
||||
/// `(cr_ptr + width - 1) / 8` would overflow an index into `b`.
|
||||
pub fn read_bits(b: &[u8], cr_ptr: usize, width: u8) -> ResultS<(usize, u64)>
|
||||
/// `(cr_bit + width - 1) / 8` would overflow an index into `b`.
|
||||
pub fn read_bits(b: &[u8], cr_bit: usize, width: u8) -> ResultS<(usize, u64)>
|
||||
{
|
||||
if width < 1 || width > 64 {
|
||||
bail!("invalid number of bits");
|
||||
}
|
||||
|
||||
let nx_ptr = cr_ptr + usize::from(width);
|
||||
let ed_ptr = nx_ptr - 1;
|
||||
let nx_bit = cr_bit + usize::from(width);
|
||||
let ed_bit = nx_bit - 1;
|
||||
|
||||
let first_byte = cr_ptr / 8;
|
||||
let last_byte = ed_ptr / 8;
|
||||
let cr_byte = cr_bit / 8;
|
||||
let ed_byte = ed_bit / 8;
|
||||
|
||||
if b.len() <= last_byte {
|
||||
bail!("not enough data");
|
||||
}
|
||||
check_data!(ed_byte + 1, b);
|
||||
|
||||
let first_bits = cr_ptr as u32 % 8;
|
||||
let last_bits = nx_ptr as u32 % 8;
|
||||
let cr_bits = cr_bit as u32 % 8;
|
||||
let nx_bits = nx_bit as u32 % 8;
|
||||
|
||||
let last_mask = ((1_u128 << last_bits) - 1) as u64;
|
||||
let nx_mask = ((1_u128 << nx_bits) - 1) as u64;
|
||||
|
||||
let num_bytes = last_byte - first_byte;
|
||||
let num_bytes = ed_byte - cr_byte;
|
||||
|
||||
let bytes = get_bytes(b, num_bytes, first_byte);
|
||||
let bytes = get_bytes(b, num_bytes, cr_byte);
|
||||
|
||||
let bits = u64::from_be_bytes(bytes);
|
||||
let bits = bits.wrapping_shl(first_bits);
|
||||
let bits = bits.wrapping_shl(cr_bits);
|
||||
let bits = bits >> (64 - width);
|
||||
|
||||
// special case for over byte boundary
|
||||
let bits = if num_bytes == 8 {
|
||||
let lbyt = u64::from(b[last_byte]);
|
||||
let lbyt = lbyt >> (8 - last_bits);
|
||||
let lbyt = lbyt & last_mask;
|
||||
if num_bytes == 8 {
|
||||
let lbyt = u64::from(b[ed_byte]);
|
||||
let lbyt = lbyt >> (8 - nx_bits);
|
||||
let lbyt = lbyt & nx_mask;
|
||||
|
||||
(bits & !last_mask) | lbyt
|
||||
Ok((nx_bit, bits & !nx_mask | lbyt))
|
||||
} else {
|
||||
bits
|
||||
};
|
||||
|
||||
Ok((nx_ptr, bits))
|
||||
Ok((nx_bit, bits))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bytes(b: &[u8], num_bytes: usize, f: usize) -> [u8; 8]
|
||||
|
|
|
@ -25,10 +25,7 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
|||
|
||||
if fl & FEXTRA != 0 {
|
||||
read_data!(p + 2, LE in b => xlen = u16[p] usize;);
|
||||
|
||||
if p + 2 + xlen > b.len() {
|
||||
bail!("not enough data");
|
||||
}
|
||||
check_data!(p + 2 + xlen, b);
|
||||
|
||||
p += xlen;
|
||||
}
|
||||
|
@ -42,7 +39,7 @@ pub fn load_gzip_header(b: &[u8]) -> ResultS<usize>
|
|||
}
|
||||
|
||||
if fl & FHCRC != 0 {
|
||||
read_data!(p + 2, LE in b => _crc = u16[p];);
|
||||
check_data!(p + 2, b);
|
||||
|
||||
p += 2;
|
||||
}
|
||||
|
|
|
@ -88,9 +88,7 @@ pub fn read_old_minf(b: &[u8]) -> ResultS<Minf>
|
|||
/// Reads an `iidx` chunk.
|
||||
pub fn read_iidx(b: &[u8]) -> ResultS<(u16, usize)>
|
||||
{
|
||||
if b.len() < 2 {
|
||||
bail!("not enough data");
|
||||
}
|
||||
check_data!(2, b);
|
||||
|
||||
Ok((u16b(b), 2))
|
||||
}
|
||||
|
|
|
@ -88,11 +88,12 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
|
|||
fst = u16[p] usize;
|
||||
lst = u16[p + 2] usize;
|
||||
}
|
||||
|
||||
let end = lst - fst;
|
||||
|
||||
p += 4;
|
||||
|
||||
if lst < fst || fst > pitch || lst > pitch || b.len() < p + end {
|
||||
if lst < fst || fst > pitch || lst > pitch {
|
||||
bail!("invalid compressed scanline");
|
||||
}
|
||||
|
||||
|
@ -110,10 +111,6 @@ pub fn read_bitmap(b: &[u8]) -> ResultS<Bitmap>
|
|||
}
|
||||
} else {
|
||||
// simple copy
|
||||
if b.len() < p + width * height {
|
||||
bail!("invalid scanline");
|
||||
}
|
||||
|
||||
bmp.cr.extend_from_slice(ok!(b.get(p..p + width * height),
|
||||
"not enough data")?);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue