aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/utils/mem_ops.h
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-12-31 11:59:27 -0500
committerJack Lloyd <[email protected]>2015-12-31 11:59:27 -0500
commitb269c8d1ce0cb5412712a8df963b2205364e17ae (patch)
tree8245489665f1f31c35626d4cf5275afbf0914276 /src/lib/utils/mem_ops.h
parent18d81936b55874ba76eca59b1d01e8028cc2bf9a (diff)
Use memcpy instead of misaligned pointer casts for reading words.
It works on x86, but C says it is undefined and it makes UBSan unhappy. Happily, this memcpy approach probably also works fine under processors which previously used the byte-at-a-time approach such as ARM. But for right now using memcpy here is still gated under the processor alignment flags. In my tests recent GCC and Clang seemed to produce basically identical code for either approach when using -O3; I imagine most compilers these days are very good at analyzing/inlining/unrolling memcpys. Also remove the manually unrolled versions of xor_buf, which caused problems with GCC and -O3 due to it vectorizing the loads into (aligned) SSE2 loads, which would fail when a misaligned pointer was passed. Which always seemed kind of bogus to me, but I guess that's what undefined behavior is for. Enable -O3 for GCC. With this change the test suite is clean under GCC ASan+UBSan and Clang ASan+UBSan, with the exception of one failure due to a bug in libstdc++ (GCC bug 60734) when compiled by Clang.
Diffstat (limited to 'src/lib/utils/mem_ops.h')
-rw-r--r--src/lib/utils/mem_ops.h66
1 files changed, 5 insertions, 61 deletions
diff --git a/src/lib/utils/mem_ops.h b/src/lib/utils/mem_ops.h
index d11e3368c..0d2d0dab0 100644
--- a/src/lib/utils/mem_ops.h
+++ b/src/lib/utils/mem_ops.h
@@ -1,6 +1,6 @@
/*
* Memory Operations
-* (C) 1999-2009,2012 Jack Lloyd
+* (C) 1999-2009,2012,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -81,7 +81,7 @@ template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
}
/**
-* XOR arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
+* XOR_ arrays. Postcondition out[i] = in[i] ^ out[i] forall i = 0...length
* @param out the input/output buffer
* @param in the read-only input buffer
* @param length the length of the buffers
@@ -89,18 +89,10 @@ template<typename T> inline bool same_mem(const T* p1, const T* p2, size_t n)
template<typename T>
void xor_buf(T out[], const T in[], size_t length)
{
- while(length >= 8)
- {
- out[0] ^= in[0]; out[1] ^= in[1];
- out[2] ^= in[2]; out[3] ^= in[3];
- out[4] ^= in[4]; out[5] ^= in[5];
- out[6] ^= in[6]; out[7] ^= in[7];
-
- out += 8; in += 8; length -= 8;
- }
-
for(size_t i = 0; i != length; ++i)
+ {
out[i] ^= in[i];
+ }
}
/**
@@ -115,60 +107,12 @@ template<typename T> void xor_buf(T out[],
const T in2[],
size_t length)
{
- while(length >= 8)
- {
- out[0] = in[0] ^ in2[0];
- out[1] = in[1] ^ in2[1];
- out[2] = in[2] ^ in2[2];
- out[3] = in[3] ^ in2[3];
- out[4] = in[4] ^ in2[4];
- out[5] = in[5] ^ in2[5];
- out[6] = in[6] ^ in2[6];
- out[7] = in[7] ^ in2[7];
-
- in += 8; in2 += 8; out += 8; length -= 8;
- }
-
for(size_t i = 0; i != length; ++i)
- out[i] = in[i] ^ in2[i];
- }
-
-#if BOTAN_TARGET_UNALIGNED_MEMORY_ACCESS_OK
-
-template<>
-inline void xor_buf<byte>(byte out[], const byte in[], size_t length)
- {
- while(length >= 8)
{
- *reinterpret_cast<u64bit*>(out) ^= *reinterpret_cast<const u64bit*>(in);
- out += 8; in += 8; length -= 8;
- }
-
- for(size_t i = 0; i != length; ++i)
- out[i] ^= in[i];
- }
-
-template<>
-inline void xor_buf<byte>(byte out[],
- const byte in[],
- const byte in2[],
- size_t length)
- {
- while(length >= 8)
- {
- *reinterpret_cast<u64bit*>(out) =
- *reinterpret_cast<const u64bit*>(in) ^
- *reinterpret_cast<const u64bit*>(in2);
-
- in += 8; in2 += 8; out += 8; length -= 8;
- }
-
- for(size_t i = 0; i != length; ++i)
out[i] = in[i] ^ in2[i];
+ }
}
-#endif
-
template<typename Alloc, typename Alloc2>
void xor_buf(std::vector<byte, Alloc>& out,
const std::vector<byte, Alloc2>& in,