-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
memrchr: Correct aligned offset computation #35969
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
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 resulted in a crash on ARMv7 platform! 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.
fed896d
to
d1ecee9
Compare
@@ -209,7 +209,7 @@ mod fallback { | |||
let end_align = (ptr as usize + len) & (usize_bytes - 1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preexisting, but this uses size_of
to calculate usize_bytes
, but alignment of usize on a system is not size_of::<usize>
but rather align_of::<usize>
? Seems like a pessimisation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like a big deal. I prefer a separate PR to deal with this. Let's have the fix here be minimal, especially if we backport it.
LGTM, but it took me some 10 mins in a distraction-ful environment to figure out the offset calculation. I think a bug like this would’ve been obvious with a plain conditional as I proposed above. |
Thank you for contributing the concentration! I agree that the conditional is better that way, will amend. |
This makes the critical calculation easier to understand.
@bors r=nagisa |
📌 Commit 8295c50 has been approved by |
⌛ Testing commit 8295c50 with merge 0f1f6ce... |
💔 Test failed - auto-win-gnu-32-opt-rustbuild |
|
@bors retry |
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
Nominating for beta: It's a crashing bug affecting std::io::stdout (common libstd feature) on a minority platform (discovered on ARMv7 on android). Neither x86, x86-64, nor cfg(linux) platforms are affected. |
Fix was verified by #35967 (comment) |
Libs decided to accept for backport. |
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 lengthlen
, 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: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