Add guards/tests for div,rem overflow cases

This commit is contained in:
miguel raz 2021-01-25 17:58:29 -06:00
parent b931c15c0b
commit c67fc2e4c5
2 changed files with 84 additions and 2 deletions

View file

@ -283,13 +283,20 @@ macro_rules! impl_unsigned_int_ops {
#[inline]
fn div(self, rhs: Self) -> Self::Output {
// TODO there is probably a better way of doing this
if AsRef::<[$scalar]>::as_ref(&rhs)
if rhs.as_slice()
.iter()
.any(|x| *x == 0)
{
panic!("attempt to divide by zero");
}
// Guards for div(MIN, -1),
// this check only applies to signed ints
if <$scalar>::MIN != 0 && self.as_slice().iter()
.zip(rhs.as_slice().iter())
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
panic!("attempt to divide with overflow");
}
unsafe { crate::intrinsics::simd_div(self, rhs) }
}
}
@ -304,6 +311,11 @@ macro_rules! impl_unsigned_int_ops {
if rhs == 0 {
panic!("attempt to divide by zero");
}
if <$scalar>::MIN != 0 &&
self.as_slice().iter().any(|x| *x == <$scalar>::MIN) &&
rhs == -1 as _ {
panic!("attempt to divide with overflow");
}
let rhs = Self::splat(rhs);
unsafe { crate::intrinsics::simd_div(self, rhs) }
}
@ -353,6 +365,14 @@ macro_rules! impl_unsigned_int_ops {
{
panic!("attempt to calculate the remainder with a divisor of zero");
}
// Guards for rem(MIN, -1)
// this branch applies the check only to signed ints
if <$scalar>::MIN != 0 && self.as_slice().iter()
.zip(rhs.as_slice().iter())
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
panic!("attempt to calculate the remainder with overflow");
}
unsafe { crate::intrinsics::simd_rem(self, rhs) }
}
}
@ -367,6 +387,11 @@ macro_rules! impl_unsigned_int_ops {
if rhs == 0 {
panic!("attempt to calculate the remainder with a divisor of zero");
}
if <$scalar>::MIN != 0 &&
self.as_slice().iter().any(|x| *x == <$scalar>::MIN) &&
rhs == -1 as _ {
panic!("attempt to calculate the remainder with overflow");
}
let rhs = Self::splat(rhs);
unsafe { crate::intrinsics::simd_rem(self, rhs) }
}

View file

@ -228,6 +228,39 @@ macro_rules! int_tests {
assert_biteq!(a, expected);
}
#[test]
#[should_panic]
fn div_min_panics() {
let a = from_slice(&vec![$scalar::MIN; 64]);
let b = from_slice(&vec![-1; 64]);
let _ = a / b;
}
#[test]
#[should_panic]
fn div_by_all_zeros_panics() {
let a = from_slice(&A);
let b = from_slice(&vec![0 ; 64]);
let _ = a / b;
}
#[test]
#[should_panic]
fn div_by_one_zero_panics() {
let a = from_slice(&A);
let mut b = from_slice(&B);
b[0] = 0 as _;
let _ = a / b;
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn div_min_neg_one_no_panic() {
let a = from_slice(&A);
let b = from_slice(&vec![-1; 64]);
let _ = a / b;
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn rem() {
@ -275,6 +308,30 @@ macro_rules! int_tests {
assert_biteq!(a, expected);
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn rem_min_neg_one_no_panic() {
let a = from_slice(&A);
let b = from_slice(&vec![-1; 64]);
let _ = a % b;
}
#[test]
#[should_panic]
fn rem_min_panic() {
let a = from_slice(&vec![$scalar::MIN; 64]);
let b = from_slice(&vec![-1 ; 64]);
let _ = a % b;
}
#[test]
#[should_panic]
fn rem_min_zero_panic() {
let a = from_slice(&A);
let b = from_slice(&vec![0 ; 64]);
let _ = a % b;
}
#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn bitand() {