Skip to content

Commit 3eb5bee

Browse files
committed
Fix binary_search_by() overflow issue in ZST case
1 parent 385ad48 commit 3eb5bee

File tree

2 files changed

+19
-3
lines changed

2 files changed

+19
-3
lines changed

library/core/src/slice/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -2154,11 +2154,12 @@ impl<T> [T] {
21542154
where
21552155
F: FnMut(&'a T) -> Ordering,
21562156
{
2157+
let mut size = self.len();
21572158
let mut left = 0;
2158-
let mut right = self.len();
2159+
let mut right = size;
21592160
while left < right {
2160-
// never overflow because `slice::len()` max is `isize::MAX`.
2161-
let mid = (left + right) / 2;
2161+
let mid = left + size / 2;
2162+
21622163
// SAFETY: the call is made safe by the following invariants:
21632164
// - `mid >= 0`
21642165
// - `mid < size`: `mid` is limited by `[left; right)` bound.
@@ -2174,6 +2175,8 @@ impl<T> [T] {
21742175
} else {
21752176
return Ok(mid);
21762177
}
2178+
2179+
size = right - left;
21772180
}
21782181
Err(left)
21792182
}

library/core/tests/slice.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::cell::Cell;
2+
use core::cmp::Ordering;
23
use core::result::Result::{Err, Ok};
34

45
#[test]
@@ -64,6 +65,17 @@ fn test_binary_search() {
6465
assert_eq!(b.binary_search(&6), Err(4));
6566
assert_eq!(b.binary_search(&7), Ok(4));
6667
assert_eq!(b.binary_search(&8), Err(5));
68+
69+
let b = [(); usize::MAX];
70+
assert_eq!(b.binary_search(&()), Ok(usize::MAX / 2));
71+
}
72+
73+
#[test]
74+
fn test_binary_search_by_overflow() {
75+
let b = [(); usize::MAX];
76+
assert_eq!(b.binary_search_by(|_| Ordering::Equal), Ok(usize::MAX / 2));
77+
assert_eq!(b.binary_search_by(|_| Ordering::Greater), Err(0));
78+
assert_eq!(b.binary_search_by(|_| Ordering::Less), Err(usize::MAX));
6779
}
6880

6981
#[test]
@@ -1982,6 +1994,7 @@ fn test_copy_within_panics_dest_too_long() {
19821994
// The length is only 13, so a slice of length 4 starting at index 10 is out of bounds.
19831995
bytes.copy_within(0..4, 10);
19841996
}
1997+
19851998
#[test]
19861999
#[should_panic(expected = "slice index starts at 2 but ends at 1")]
19872000
fn test_copy_within_panics_src_inverted() {

0 commit comments

Comments
 (0)