diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 72af47c71dd64..27c6b6f5bc02f 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -1,7 +1,6 @@ //! Comparison traits for `[T]`. -use crate::cmp; -use crate::cmp::Ordering::{self, Greater, Less}; +use crate::cmp::{self, Ordering}; use crate::mem; use super::from_raw_parts; @@ -189,18 +188,18 @@ impl SliceOrd for A { impl SliceOrd for u8 { #[inline] fn compare(left: &[Self], right: &[Self]) -> Ordering { - let order = - // SAFETY: `left` and `right` are references and are thus guaranteed to be valid. - // We use the minimum of both lengths which guarantees that both regions are - // valid for reads in that interval. - unsafe { memcmp(left.as_ptr(), right.as_ptr(), cmp::min(left.len(), right.len())) }; + // Since the length of a slice is always less than or equal to isize::MAX, this never underflows. + let diff = left.len() as isize - right.len() as isize; + // This comparison gets optimized away (on x86_64 and ARM) because the subtraction updates flags. + let len = if left.len() < right.len() { left.len() } else { right.len() }; + // SAFETY: `left` and `right` are references and are thus guaranteed to be valid. + // We use the minimum of both lengths which guarantees that both regions are + // valid for reads in that interval. + let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len) as isize }; if order == 0 { - left.len().cmp(&right.len()) - } else if order < 0 { - Less - } else { - Greater + order = diff; } + order.cmp(&0) } }