Skip to content

Commit

Permalink
Merge #6: Fix UBSan "misaligned-pointer-use" warning on aarch64
Browse files Browse the repository at this point in the history
1ac401e Fix UBSan "misaligned-pointer-use" warning on aarch64 (Hennadii Stepanov)

Pull request description:

  As `data` type is a pointer to `uint8_t`, the access to the memory via the `(uint64_t *)data` pointer is misaligned. It can be an issue on ARM hardware. As suggested in https://en.cppreference.com/w/cpp/language/reinterpret_cast:
  > When it is needed to interpret the bytes of an object as a value of a different type, `std::memcpy` ... can be used.

  For more details, please refer to bitcoin/bitcoin#29178.

  Also: https://stackoverflow.com/questions/32062894/take-advantage-of-arm-unaligned-memory-access-while-writing-clean-c-code.

ACKs for top commit:
  theuni:
    ACK 1ac401e.
  dergoegge:
    ACK 1ac401e

Tree-SHA512: c459da5571dd607a742ed4d7d3aece264bbde83d30d62c500bf0708eadc3b101e505f7f5b6fd453650aea63703909d776db151b234845c414944913fecb5a862
  • Loading branch information
fanquake committed Feb 27, 2024
2 parents 0bac72c + 1ac401e commit b60d2b7
Showing 1 changed file with 20 additions and 12 deletions.
32 changes: 20 additions & 12 deletions src/crc32c_arm64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <cstddef>
#include <cstdint>
#include <cstring>

#include "./crc32c_internal.h"
#ifdef CRC32C_HAVE_CONFIG_H
Expand All @@ -29,14 +30,14 @@
// compute 8bytes for each segment parallelly
#define CRC32C32BYTES(P, IND) \
do { \
crc1 = __crc32cd( \
crc1, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 1 + (IND))); \
crc2 = __crc32cd( \
crc2, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 2 + (IND))); \
crc3 = __crc32cd( \
crc3, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 3 + (IND))); \
crc0 = __crc32cd( \
crc0, *((const uint64_t *)(P) + (SEGMENTBYTES / 8) * 0 + (IND))); \
std::memcpy(&d64, (P) + SEGMENTBYTES * 1 + (IND) * 8, sizeof(d64)); \
crc1 = __crc32cd(crc1, d64); \
std::memcpy(&d64, (P) + SEGMENTBYTES * 2 + (IND) * 8, sizeof(d64)); \
crc2 = __crc32cd(crc2, d64); \
std::memcpy(&d64, (P) + SEGMENTBYTES * 3 + (IND) * 8, sizeof(d64)); \
crc3 = __crc32cd(crc3, d64); \
std::memcpy(&d64, (P) + SEGMENTBYTES * 0 + (IND) * 8, sizeof(d64)); \
crc0 = __crc32cd(crc0, d64); \
} while (0);

// compute 8*8 bytes for each segment parallelly
Expand Down Expand Up @@ -68,6 +69,9 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *data, size_t size) {
int64_t length = size;
uint32_t crc0, crc1, crc2, crc3;
uint64_t t0, t1, t2;
uint16_t d16;
uint32_t d32;
uint64_t d64;

// k0=CRC(x^(3*SEGMENTBYTES*8)), k1=CRC(x^(2*SEGMENTBYTES*8)),
// k2=CRC(x^(SEGMENTBYTES*8))
Expand All @@ -88,7 +92,8 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *data, size_t size) {
t2 = (uint64_t)vmull_p64(crc2, k2);
t1 = (uint64_t)vmull_p64(crc1, k1);
t0 = (uint64_t)vmull_p64(crc0, k0);
crc = __crc32cd(crc3, *(uint64_t *)data);
std::memcpy(&d64, data, sizeof(d64));
crc = __crc32cd(crc3, d64);
data += sizeof(uint64_t);
crc ^= __crc32cd(0, t2);
crc ^= __crc32cd(0, t1);
Expand All @@ -98,18 +103,21 @@ uint32_t ExtendArm64(uint32_t crc, const uint8_t *data, size_t size) {
}

while (length >= 8) {
crc = __crc32cd(crc, *(uint64_t *)data);
std::memcpy(&d64, data, sizeof(d64));
crc = __crc32cd(crc, d64);
data += 8;
length -= 8;
}

if (length & 4) {
crc = __crc32cw(crc, *(uint32_t *)data);
std::memcpy(&d32, data, sizeof(d32));
crc = __crc32cw(crc, d32);
data += 4;
}

if (length & 2) {
crc = __crc32ch(crc, *(uint16_t *)data);
std::memcpy(&d16, data, sizeof(d16));
crc = __crc32ch(crc, d16);
data += 2;
}

Expand Down

0 comments on commit b60d2b7

Please sign in to comment.