Skip to content

Commit 9801540

Browse files
Merge pull request rust-lang#55 from miguelraz/min-panics
implement guards in rem and div unsound cases
2 parents 3717408 + c67fc2e commit 9801540

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

crates/core_simd/src/ops.rs

+27-2
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,20 @@ macro_rules! impl_unsigned_int_ops {
283283

284284
#[inline]
285285
fn div(self, rhs: Self) -> Self::Output {
286-
// TODO there is probably a better way of doing this
287-
if AsRef::<[$scalar]>::as_ref(&rhs)
286+
if rhs.as_slice()
288287
.iter()
289288
.any(|x| *x == 0)
290289
{
291290
panic!("attempt to divide by zero");
292291
}
292+
293+
// Guards for div(MIN, -1),
294+
// this check only applies to signed ints
295+
if <$scalar>::MIN != 0 && self.as_slice().iter()
296+
.zip(rhs.as_slice().iter())
297+
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
298+
panic!("attempt to divide with overflow");
299+
}
293300
unsafe { crate::intrinsics::simd_div(self, rhs) }
294301
}
295302
}
@@ -304,6 +311,11 @@ macro_rules! impl_unsigned_int_ops {
304311
if rhs == 0 {
305312
panic!("attempt to divide by zero");
306313
}
314+
if <$scalar>::MIN != 0 &&
315+
self.as_slice().iter().any(|x| *x == <$scalar>::MIN) &&
316+
rhs == -1 as _ {
317+
panic!("attempt to divide with overflow");
318+
}
307319
let rhs = Self::splat(rhs);
308320
unsafe { crate::intrinsics::simd_div(self, rhs) }
309321
}
@@ -353,6 +365,14 @@ macro_rules! impl_unsigned_int_ops {
353365
{
354366
panic!("attempt to calculate the remainder with a divisor of zero");
355367
}
368+
369+
// Guards for rem(MIN, -1)
370+
// this branch applies the check only to signed ints
371+
if <$scalar>::MIN != 0 && self.as_slice().iter()
372+
.zip(rhs.as_slice().iter())
373+
.any(|(x,y)| *x == <$scalar>::MIN && *y == -1 as _) {
374+
panic!("attempt to calculate the remainder with overflow");
375+
}
356376
unsafe { crate::intrinsics::simd_rem(self, rhs) }
357377
}
358378
}
@@ -367,6 +387,11 @@ macro_rules! impl_unsigned_int_ops {
367387
if rhs == 0 {
368388
panic!("attempt to calculate the remainder with a divisor of zero");
369389
}
390+
if <$scalar>::MIN != 0 &&
391+
self.as_slice().iter().any(|x| *x == <$scalar>::MIN) &&
392+
rhs == -1 as _ {
393+
panic!("attempt to calculate the remainder with overflow");
394+
}
370395
let rhs = Self::splat(rhs);
371396
unsafe { crate::intrinsics::simd_rem(self, rhs) }
372397
}

crates/core_simd/tests/ops_impl/int_macros.rs

+57
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,39 @@ macro_rules! int_tests {
228228
assert_biteq!(a, expected);
229229
}
230230

231+
#[test]
232+
#[should_panic]
233+
fn div_min_panics() {
234+
let a = from_slice(&vec![$scalar::MIN; 64]);
235+
let b = from_slice(&vec![-1; 64]);
236+
let _ = a / b;
237+
}
238+
239+
#[test]
240+
#[should_panic]
241+
fn div_by_all_zeros_panics() {
242+
let a = from_slice(&A);
243+
let b = from_slice(&vec![0 ; 64]);
244+
let _ = a / b;
245+
}
246+
247+
#[test]
248+
#[should_panic]
249+
fn div_by_one_zero_panics() {
250+
let a = from_slice(&A);
251+
let mut b = from_slice(&B);
252+
b[0] = 0 as _;
253+
let _ = a / b;
254+
}
255+
256+
#[test]
257+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
258+
fn div_min_neg_one_no_panic() {
259+
let a = from_slice(&A);
260+
let b = from_slice(&vec![-1; 64]);
261+
let _ = a / b;
262+
}
263+
231264
#[test]
232265
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
233266
fn rem() {
@@ -275,6 +308,30 @@ macro_rules! int_tests {
275308
assert_biteq!(a, expected);
276309
}
277310

311+
#[test]
312+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
313+
fn rem_min_neg_one_no_panic() {
314+
let a = from_slice(&A);
315+
let b = from_slice(&vec![-1; 64]);
316+
let _ = a % b;
317+
}
318+
319+
#[test]
320+
#[should_panic]
321+
fn rem_min_panic() {
322+
let a = from_slice(&vec![$scalar::MIN; 64]);
323+
let b = from_slice(&vec![-1 ; 64]);
324+
let _ = a % b;
325+
}
326+
327+
#[test]
328+
#[should_panic]
329+
fn rem_min_zero_panic() {
330+
let a = from_slice(&A);
331+
let b = from_slice(&vec![0 ; 64]);
332+
let _ = a % b;
333+
}
334+
278335
#[test]
279336
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
280337
fn bitand() {

0 commit comments

Comments
 (0)