Skip to content

Commit

Permalink
Rollup merge of rust-lang#52854 - RalfJung:memrchr, r=Kimundi
Browse files Browse the repository at this point in the history
fix memrchr in miri

The previous PR rust-lang#52744 was not enough because it assumed that the split between the `mid` and `end` parts returned by `align_to` was aligned. But really the only guarantee we have is that the `mid` part is aligned, so make use of that.
  • Loading branch information
pietroalbini committed Aug 1, 2018
2 parents f52ef3b + 6d5694a commit e3928cc
Showing 1 changed file with 16 additions and 10 deletions.
26 changes: 16 additions & 10 deletions src/libcore/slice/memchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down

0 comments on commit e3928cc

Please sign in to comment.