about summary refs log tree commit diff
path: root/src/libcore/slice
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-08-01 19:54:06 +0000
committerbors <bors@rust-lang.org>2018-08-01 19:54:06 +0000
commit97085f9fb0736b322dc216db3655da780b4d8041 (patch)
tree51ff3c45c1fdf154e186cb1c494a7ac93b94b5bf /src/libcore/slice
parentc4156768aa1f23117903e6954f3e9ba946f49295 (diff)
parent3e7897f773f48ce982cbee6fbfd3118e5648e352 (diff)
downloadrust-97085f9fb0736b322dc216db3655da780b4d8041.tar.gz
rust-97085f9fb0736b322dc216db3655da780b4d8041.zip
Auto merge of #52958 - pietroalbini:rollup, r=pietroalbini
Rollup of 15 pull requests

Successful merges:

 - #52793 (Add test for NLL: unexpected "free region `` does not outlive" error )
 - #52799 (Use BitVector for global sets of AttrId)
 - #52809 (Add test for unexpected region for local data ReStatic)
 - #52834 ([NLL] Allow conflicting borrows of promoted length zero arrays)
 - #52835 (Fix Alias intra doc ICE)
 - #52854 (fix memrchr in miri)
 - #52899 (tests/ui: Add missing mips{64} ignores)
 - #52908 (Use SetLenOnDrop in Vec::truncate())
 - #52915 (Don't count MIR locals as borrowed after StorageDead when finding locals live across a yield terminator)
 - #52926 (rustc: Trim down the `rust_2018_idioms` lint group)
 - #52930 (rustc_resolve: record single-segment extern crate import resolutions.)
 - #52939 (Make io::Read::read_to_end consider io::Take::limit)
 - #52942 (Another SmallVec.extend optimization)
 - #52947 (1.27 actually added the `armv5te-unknown-linux-musleabi` target)
 - #52954 (async can begin expressions)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libcore/slice')
-rw-r--r--src/libcore/slice/memchr.rs26
1 files changed, 16 insertions, 10 deletions
diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs
index 72e7b57a6cb..c9d3c7fea98 100644
--- a/src/libcore/slice/memchr.rs
+++ b/src/libcore/slice/memchr.rs
@@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // - the first remaining bytes, < 2 word size
     let len = text.len();
     let ptr = text.as_ptr();
-    let usize_bytes = mem::size_of::<usize>();
+    type Chunk = usize;
 
-    let mut offset = {
-        // We call this just to obtain the length of the suffix
-        let (_, _, suffix) = unsafe { text.align_to::<usize>() };
-        len - suffix.len()
+    let (min_aligned_offset, max_aligned_offset) = {
+        // We call this just to obtain the length of the prefix and suffix.
+        // In the middle we always process two chunks at once.
+        let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() };
+        (prefix.len(), len - suffix.len())
     };
+
+    let mut offset = max_aligned_offset;
     if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
         return Some(offset + index);
     }
 
-    // search the body of the text
+    // search the body of the text, make sure we don't cross min_aligned_offset.
+    // offset is always aligned, so just testing `>` is sufficient and avoids possible
+    // overflow.
     let repeated_x = repeat_byte(x);
+    let chunk_bytes = mem::size_of::<Chunk>();
 
-    while offset >= 2 * usize_bytes {
+    while offset > min_aligned_offset {
         unsafe {
-            let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
-            let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
+            let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
+            let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
 
             // break if there is a matching byte
             let zu = contains_zero_byte(u ^ repeated_x);
@@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
                 break;
             }
         }
-        offset -= 2 * usize_bytes;
+        offset -= 2 * chunk_bytes;
     }
 
     // find the byte before the point the body loop stopped