diff options
| author | Folyd <lyshuhow@gmail.com> | 2021-02-27 17:27:45 +0800 |
|---|---|---|
| committer | Folyd <lyshuhow@gmail.com> | 2021-02-27 22:11:44 +0800 |
| commit | 3eb5bee242fae12c4cf547bfe0665653c20ca0c2 (patch) | |
| tree | 37801e1d49d746a0924bc9fb98fdcb9fa402eaa6 | |
| parent | 385ad48b3563fc3cb6fe4d98dfa746a4204ac092 (diff) | |
| download | rust-3eb5bee242fae12c4cf547bfe0665653c20ca0c2.tar.gz rust-3eb5bee242fae12c4cf547bfe0665653c20ca0c2.zip | |
Fix `binary_search_by()` overflow issue in ZST case
| -rw-r--r-- | library/core/src/slice/mod.rs | 9 | ||||
| -rw-r--r-- | library/core/tests/slice.rs | 13 |
2 files changed, 19 insertions, 3 deletions
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index bc3f02efdda..d314d38c30a 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2154,11 +2154,12 @@ impl<T> [T] { where F: FnMut(&'a T) -> Ordering, { + let mut size = self.len(); let mut left = 0; - let mut right = self.len(); + let mut right = size; while left < right { - // never overflow because `slice::len()` max is `isize::MAX`. - let mid = (left + right) / 2; + let mid = left + size / 2; + // SAFETY: the call is made safe by the following invariants: // - `mid >= 0` // - `mid < size`: `mid` is limited by `[left; right)` bound. @@ -2174,6 +2175,8 @@ impl<T> [T] { } else { return Ok(mid); } + + size = right - left; } Err(left) } diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs index 390066359f6..7e198631cc7 100644 --- a/library/core/tests/slice.rs +++ b/library/core/tests/slice.rs @@ -1,4 +1,5 @@ use core::cell::Cell; +use core::cmp::Ordering; use core::result::Result::{Err, Ok}; #[test] @@ -64,6 +65,17 @@ fn test_binary_search() { assert_eq!(b.binary_search(&6), Err(4)); assert_eq!(b.binary_search(&7), Ok(4)); assert_eq!(b.binary_search(&8), Err(5)); + + let b = [(); usize::MAX]; + assert_eq!(b.binary_search(&()), Ok(usize::MAX / 2)); +} + +#[test] +fn test_binary_search_by_overflow() { + let b = [(); usize::MAX]; + assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX / 2)); + assert_eq!(b.binary_search_by(|_| Ordering::Greater), Err(0)); + assert_eq!(b.binary_search_by(|_| Ordering::Less), Err(usize::MAX)); } #[test] @@ -1982,6 +1994,7 @@ fn test_copy_within_panics_dest_too_long() { // The length is only 13, so a slice of length 4 starting at index 10 is out of bounds. bytes.copy_within(0..4, 10); } + #[test] #[should_panic(expected = "slice index starts at 2 but ends at 1")] fn test_copy_within_panics_src_inverted() { |
