about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFolyd <lyshuhow@gmail.com>2021-02-27 17:27:45 +0800
committerFolyd <lyshuhow@gmail.com>2021-02-27 22:11:44 +0800
commit3eb5bee242fae12c4cf547bfe0665653c20ca0c2 (patch)
tree37801e1d49d746a0924bc9fb98fdcb9fa402eaa6
parent385ad48b3563fc3cb6fe4d98dfa746a4204ac092 (diff)
downloadrust-3eb5bee242fae12c4cf547bfe0665653c20ca0c2.tar.gz
rust-3eb5bee242fae12c4cf547bfe0665653c20ca0c2.zip
Fix `binary_search_by()` overflow issue in ZST case
-rw-r--r--library/core/src/slice/mod.rs9
-rw-r--r--library/core/tests/slice.rs13
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() {