Rollup merge of #52854 - RalfJung:memrchr, r=Kimundi
fix memrchr in miri The previous PR https://github.com/rust-lang/rust/pull/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.
This commit is contained in:
commit
e3928ccb2f
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue