Skip to content

Commit

Permalink
Auto merge of #35969 - bluss:memrchr-alignment, r=nagisa
Browse files Browse the repository at this point in the history
memrchr: Correct aligned offset computation

The memrchr fallback did not compute the offset correctly. It was
intentioned to land on usize-aligned addresses but did not.
This was suspected to have resulted in a crash on ARMv7!

This bug affected non-linux platforms.

I think like this, if we have a slice with pointer `ptr` and length
`len`, we want to find the last usize-aligned offset in the slice.
The correct computation should be:

For example if ptr = 1 and len = 6, and `size_of::<usize>()` is 4:

```
[ x x x x x x ]
  1 2 3 4 5 6
        ^-- last aligned address at offset 3 from the start.
```

The last aligned address is ptr + len - (ptr + len) % usize_size.

Compute offset from the start as:

offset = len - (ptr + len) % usize_size = 6 - (1 + 6) % 4 = 6 - 3 = 3.

I believe the function's return value was always correct previously, if
the platform supported unaligned addresses.

Fixes #35967
  • Loading branch information
bors authored Aug 27, 2016
2 parents 099b9fd + 8295c50 commit 1194695
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/libstd/memchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ mod fallback {
let end_align = (ptr as usize + len) & (usize_bytes - 1);
let mut offset;
if end_align > 0 {
offset = len - cmp::min(usize_bytes - end_align, len);
offset = if end_align >= len { 0 } else { len - end_align };
if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
return Some(offset + index);
}
Expand Down Expand Up @@ -309,6 +309,17 @@ mod fallback {
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}

#[test]
fn each_alignment_reversed() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -385,4 +396,15 @@ mod tests {
fn no_match_reversed() {
assert_eq!(None, memrchr(b'a', b"xyz"));
}

#[test]
fn each_alignment() {
let mut data = [1u8; 64];
let needle = 2;
let pos = 40;
data[pos] = needle;
for start in 0..16 {
assert_eq!(Some(pos - start), memchr(needle, &data[start..]));
}
}
}

0 comments on commit 1194695

Please sign in to comment.