-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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