Skip to content

Commit 151df5c

Browse files
committed
Fix overflow in usize as i64
1 parent 383af35 commit 151df5c

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

src/range.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ macro_rules! unindexed_range_impl {
153153
{
154154
if let Some(len) = self.opt_len() {
155155
(0..len).into_par_iter()
156-
.map(|i| self.range.start + i as $t)
156+
.map(|i| self.range.start.wrapping_add(i as $t))
157157
.drive_unindexed(consumer)
158158
} else {
159159
bridge_unindexed(IterProducer { range: self.range }, consumer)
@@ -211,7 +211,7 @@ unindexed_range_impl!{i64, u64}
211211
#[cfg(has_i128)] unindexed_range_impl!{i128, u128}
212212

213213
#[test]
214-
pub fn check_range_split_at_overflow() {
214+
fn check_range_split_at_overflow() {
215215
// Note, this split index overflows i8!
216216
let producer = IterProducer { range: -100i8..100 };
217217
let (left, right) = producer.split_at(150);
@@ -222,7 +222,7 @@ pub fn check_range_split_at_overflow() {
222222

223223
#[cfg(has_i128)]
224224
#[test]
225-
pub fn test_i128_len_doesnt_overflow() {
225+
fn test_i128_len_doesnt_overflow() {
226226
use std::{i128, u128};
227227

228228
// Using parse because some versions of rust don't allow long literals
@@ -238,7 +238,7 @@ pub fn test_i128_len_doesnt_overflow() {
238238
}
239239

240240
#[test]
241-
pub fn test_u64_opt_len() {
241+
fn test_u64_opt_len() {
242242
use std::{u64, usize};
243243
assert_eq!(Some(100), (0..100u64).into_par_iter().opt_len());
244244
assert_eq!(Some(usize::MAX), (0..usize::MAX as u64).into_par_iter().opt_len());
@@ -250,10 +250,26 @@ pub fn test_u64_opt_len() {
250250

251251
#[cfg(has_i128)]
252252
#[test]
253-
pub fn test_u128_opt_len() {
253+
fn test_u128_opt_len() {
254254
use std::{u128, usize};
255255
assert_eq!(Some(100), (0..100u128).into_par_iter().opt_len());
256256
assert_eq!(Some(usize::MAX), (0..usize::MAX as u128).into_par_iter().opt_len());
257257
assert_eq!(None, (0..1 + usize::MAX as u128).into_par_iter().opt_len());
258258
assert_eq!(None, (0..u128::MAX).into_par_iter().opt_len());
259259
}
260+
261+
// `usize as i64` can overflow, so make sure to wrap it appropriately
262+
// when using the `opt_len` "indexed" mode.
263+
#[test]
264+
#[cfg(target_pointer_width = "64")]
265+
fn test_usize_i64_overflow() {
266+
use std::i64;
267+
use ThreadPoolBuilder;
268+
269+
let iter = (-2..i64::MAX).into_par_iter();
270+
assert_eq!(iter.opt_len(), Some(i64::MAX as usize + 2));
271+
272+
// always run with multiple threads to split into, or this will take forever...
273+
let pool = ThreadPoolBuilder::new().num_threads(8).build().unwrap();
274+
pool.install(|| assert_eq!(iter.find_last(|_| true), Some(i64::MAX - 1)));
275+
}

0 commit comments

Comments
 (0)