Skip to content
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

Fix aligned access in memrchr fallback #9

Merged
merged 4 commits into from
Oct 12, 2016

Conversation

bluss
Copy link
Contributor

@bluss bluss commented Aug 24, 2016

The fallback implementation is not computing the aligned offset correctly(!). This is UB unfortunately and does crash on platforms where aligned accesses are not allowed.

@tomaka found a crash in memrchr on an ARMv7 (using the memrchr in libstd) and I suspect this was the cause. I wanted to put the fix here first, so that we can review it together. I think the original calculation was just bogus. See the first commit's log for more explanation.

bluss added 3 commits August 24, 2016 13:58
The fallback did not compute the offset correctly. It was intentioned to
land on usize-aligned addresses but did not. This resulted in a SIGBUS
on an ARMv7 platform!

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 answer was always correct previously, if the platform
supported unaligned addresses.
@BurntSushi
Copy link
Owner

Interesting! Do any of the newly added tests fail without the fix? (I'm assuming not.)

@bluss
Copy link
Contributor Author

bluss commented Aug 24, 2016

They do fail due to the new debug assertion.

@bluss
Copy link
Contributor Author

bluss commented Aug 24, 2016

failures: 

---- tests::fallback::qc_never_fail_reversed stdout ----
        thread 'tests::fallback::qc_never_fail_reversed' panicked at '[quickcheck] TEST FAILED (runtime error). Arguments: (0, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1])
Error: "assertion failed: `(left == right)` (left: `2`, right: `0`)"', cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/quickcheck-0.2.27/src/tester.rs:116

---- tests::fallback::qc_correct_memrchr stdout ----
        thread 'tests::fallback::qc_correct_memrchr' panicked at '[quickcheck] TEST FAILED (runtime error). Arguments: ([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 0)  
Error: "assertion failed: `(left == right)` (left: `2`, right: `0`)"', cargo/registry/src/jackfan.us.kg-1ecc6299db9ec823/quickcheck-0.2.27/src/tester.rs:116


failures: 
    tests::fallback::qc_correct_memrchr
    tests::fallback::qc_never_fail_reversed

This makes the critical calculation easier to understand.
@bluss bluss force-pushed the memrchr-alignment-fix branch from 15016b7 to 9a0ad22 Compare August 30, 2016 07:24
@BurntSushi BurntSushi merged commit 29918e8 into BurntSushi:master Oct 12, 2016
@BurntSushi
Copy link
Owner

Thanks for this! Sorry for the tardiness, completely forgot this was sitting here. :-)

@bluss bluss deleted the memrchr-alignment-fix branch October 12, 2016 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants