Cherry-pick crrev.com/350033 to avoid misaligned access. Avoid misaligned read/write on little endian platforms Asan build with -fsanitize=alignment flag crash on out/Debug/base_unittests --gtest_filter=Base* Code does not use memcpy for consistency with code around. BUG=chromium:1017267 BUG=chromium:1015098 TEST=pre-cq passes Change-Id: Ie5c1d60204967c117e6b6ac2d9bd06c6fd7c1b50 Reviewed-on: https://chromium-review.googlesource.com/1877433 Tested-by: Manoj Gupta <manojgupta@chromium.org> Commit-Ready: Manoj Gupta <manojgupta@chromium.org> Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org> Reviewed-by: Eric Caruso <ejcaruso@chromium.org> Reviewed-by: Luis Lozano <llozano@chromium.org>
diff --git a/README.chromium b/README.chromium index 35b9e54..40b93d2 100644 --- a/README.chromium +++ b/README.chromium
@@ -13,3 +13,5 @@ The modp_b64.cc and modp_b64.h files were modified to make them safe on 64-bit systems. +The modp_b64.cc was modified to avoid misaligned read/write on +little-endian hardware.
diff --git a/modp_b64.cc b/modp_b64.cc index e5f6cf1..fdb8a40 100644 --- a/modp_b64.cc +++ b/modp_b64.cc
@@ -211,28 +211,18 @@ uint8_t* p = (uint8_t*)dest; uint32_t x = 0; - uint32_t* destInt = (uint32_t*) p; - uint32_t* srcInt = (uint32_t*) src; - uint32_t y = *srcInt++; - for (i = 0; i < chunks; ++i) { - x = d0[y & 0xff] | - d1[(y >> 8) & 0xff] | - d2[(y >> 16) & 0xff] | - d3[(y >> 24) & 0xff]; - + const uint8_t* y = (uint8_t*)src; + for (i = 0; i < chunks; ++i, y += 4) { + x = d0[y[0]] | d1[y[1]] | d2[y[2]] | d3[y[3]]; if (x >= BADCHAR) return MODP_B64_ERROR; - *destInt = x ; - p += 3; - destInt = (uint32_t*)p; - y = *srcInt++;} - + *p++ = ((uint8_t*)(&x))[0]; + *p++ = ((uint8_t*)(&x))[1]; + *p++ = ((uint8_t*)(&x))[2]; + } switch (leftover) { case 0: - x = d0[y & 0xff] | - d1[(y >> 8) & 0xff] | - d2[(y >> 16) & 0xff] | - d3[(y >> 24) & 0xff]; + x = d0[y[0]] | d1[y[1]] | d2[y[2]] | d3[y[3]]; if (x >= BADCHAR) return MODP_B64_ERROR; *p++ = ((uint8_t*)(&x))[0]; @@ -241,17 +231,15 @@ return (chunks+1)*3; break; case 1: /* with padding this is an impossible case */ - x = d0[y & 0xff]; + x = d0[y[0]]; *p = *((uint8_t*)(&x)); // i.e. first char/byte in int break; case 2: // * case 2, 1 output byte */ - x = d0[y & 0xff] | d1[y >> 8 & 0xff]; + x = d0[y[0]] | d1[y[1]]; *p = *((uint8_t*)(&x)); // i.e. first char break; default: /* case 3, 2 output bytes */ - x = d0[y & 0xff] | - d1[y >> 8 & 0xff ] | - d2[y >> 16 & 0xff]; /* 0x3c */ + x = d0[y[0]] | d1[y[1]] | d2[y[2]]; /* 0x3c */ *p++ = ((uint8_t*)(&x))[0]; *p = ((uint8_t*)(&x))[1]; break;