-
Notifications
You must be signed in to change notification settings - Fork 136
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 invalid pointer casts in arm64 implementation #65
Conversation
It is UB in C and C++ to type-pun pointers in this way, for two reasons. First, casting to a pointer is forbidden if the pointer is not aligned. Second, this kind of type-punning is a strict aliasing violation. Instead, the way to read 8 bytes as a time as a uint64_t is to call memcpy. Compilers recognize this pattern and optimize it, lowering it to the same code, but without breaking the language's abstract state machine. This is needed to fix some UBSan warnings in Chromium.
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.
Thank you for for flagging this problem!
Would you be willing to address these comments, or would you prefer that I do it in a follow-up?
src/crc32c_arm64.cc
Outdated
@@ -24,17 +25,31 @@ | |||
#define KBYTES 1032 | |||
#define SEGMENTBYTES 256 | |||
|
|||
static uint64_t LoadU64(const uint8_t in[sizeof(uint64_t)]) { |
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.
Can you use and extend crc32c_read_le.h?
I think that ReadUint32LE() and ReadUint64LE() there work as you need them to, and we checked that they're compiled as efficiently as memcpy on little-endian architectures.
You can add a ReadUint16LE() with tests, and then use it here.
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.
Ah nice! Done. See commit message of 1b4eb1a for some notes on what I changed there.
In doing so, I fixed up crc32c_read_le.h a bit: 1. The documentation and tests say the buffers need to be aligned, but they don't. 2. Add a 16-bit version. 3. Remove an unnecessary static_cast<uint8_t>. The pointer is already uint8_t. 4. Replace the necessary static_casts with uintN_t{x} per the Google style guide. https://google.github.io/styleguide/cppguide.html#Casting
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.
Thank you very much for the revisions!
It is UB in C and C++ to type-pun pointers in this way, for two reasons. First, casting to a pointer is forbidden if the pointer is not aligned. Second, this kind of type-punning is a strict aliasing violation.
Instead, the way to read 8 bytes as a time as a uint64_t is to call memcpy. Compilers recognize this pattern and optimize it, lowering it to the same code, but without breaking the language's abstract state machine.
This is needed to fix some UBSan warnings in Chromium.