From 2ebce7384bc7bc6c31122096326c9384d09bdce1 Mon Sep 17 00:00:00 2001 From: David Pursell Date: Fri, 23 Sep 2016 09:19:12 -0700 Subject: [PATCH] Flattenable: switch from assignment to memcpy(). FlattenableUtils read() and write() currently use assignment to copy bytes. However, by casting the void* buffer to type T, the compiler is allowed to assume that buffer obeys the alignment requirements of T, which is not necessarily the case during serialization. On some architectures, we can get SIGBUS when this alignment is violated. We don't want the users of these routines to have to worry about alignment when packing structures, so use memcpy() instead which should always be safe since the compiler won't assume any alignment for the void* buffer. On architectures that can handle unaligned direct read/write of type T, the compiler should be smart enough to optimize this code back to a direct read/write anyway, but architectures that can't handle it will fall back to memcpy; this means that this change shouldn't have any impact on current Android devices. See the linked bug for more details. Bug: http://b/31671510 Test: libgui Sensor serialization no longer gives SIGBUS. Test: libgui.so unchanged on Shamu before and after this CL. Change-Id: I2197127e8cbfb43f4f553bda6464f6ebe087febd --- include/utils/Flattenable.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/utils/Flattenable.h b/include/utils/Flattenable.h index 882a8b249..c37ac60c7 100644 --- a/include/utils/Flattenable.h +++ b/include/utils/Flattenable.h @@ -19,10 +19,13 @@ #include +#include #include #include #include +#include + namespace android { @@ -60,14 +63,18 @@ public: // write a POD structure template static void write(void*& buffer, size_t& size, const T& value) { - *static_cast(buffer) = value; + static_assert(std::is_trivially_copyable::value, + "Cannot flatten a non-trivially-copyable type"); + memcpy(buffer, &value, sizeof(T)); advance(buffer, size, sizeof(T)); } // read a POD structure template static void read(void const*& buffer, size_t& size, T& value) { - value = *static_cast(buffer); + static_assert(std::is_trivially_copyable::value, + "Cannot unflatten a non-trivially-copyable type"); + memcpy(&value, buffer, sizeof(T)); advance(buffer, size, sizeof(T)); } };