Skip to content

Commit 6d5694a

Browse files
committed
fix memrchr in miri
1 parent 7bbcd00 commit 6d5694a

File tree

1 file changed

+16
-10
lines changed

1 file changed

+16
-10
lines changed

src/libcore/slice/memchr.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
100100
// - the first remaining bytes, < 2 word size
101101
let len = text.len();
102102
let ptr = text.as_ptr();
103-
let usize_bytes = mem::size_of::<usize>();
103+
type Chunk = usize;
104104

105-
let mut offset = {
106-
// We call this just to obtain the length of the suffix
107-
let (_, _, suffix) = unsafe { text.align_to::<usize>() };
108-
len - suffix.len()
105+
let (min_aligned_offset, max_aligned_offset) = {
106+
// We call this just to obtain the length of the prefix and suffix.
107+
// In the middle we always process two chunks at once.
108+
let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() };
109+
(prefix.len(), len - suffix.len())
109110
};
111+
112+
let mut offset = max_aligned_offset;
110113
if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
111114
return Some(offset + index);
112115
}
113116

114-
// search the body of the text
117+
// search the body of the text, make sure we don't cross min_aligned_offset.
118+
// offset is always aligned, so just testing `>` is sufficient and avoids possible
119+
// overflow.
115120
let repeated_x = repeat_byte(x);
121+
let chunk_bytes = mem::size_of::<Chunk>();
116122

117-
while offset >= 2 * usize_bytes {
123+
while offset > min_aligned_offset {
118124
unsafe {
119-
let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
120-
let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
125+
let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
126+
let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
121127

122128
// break if there is a matching byte
123129
let zu = contains_zero_byte(u ^ repeated_x);
@@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
126132
break;
127133
}
128134
}
129-
offset -= 2 * usize_bytes;
135+
offset -= 2 * chunk_bytes;
130136
}
131137

132138
// find the byte before the point the body loop stopped

0 commit comments

Comments
 (0)