Tests & stronger guarantees for hidl_* pads.
- Test that pads are zero (for future proofing, also ran tests
on original implementation and bugfix).
- Use -Wpadded so that compiler guarantees there aren't padding
bits hiding elsewhere (there aren't)
Bug: 131356202
Test: libhidl_test
(without fixes, with fixes, and with this CL)
Change-Id: Ib52a16015b0393c104cd984376328cb0da888b03
diff --git a/Android.bp b/Android.bp
index 97ed108..f83ada8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -32,14 +32,18 @@
shared_libs: [
"android.hidl.memory@1.0",
"libbase",
- "libhidlbase",
- "libhidltransport",
"libhwbinder",
"liblog",
"libutils",
"libcutils",
+ "libvndksupport",
],
- static_libs: ["libgtest", "libgmock"],
+ static_libs: [
+ "libhidlbase",
+ "libhidltransport",
+ "libgtest",
+ "libgmock"
+ ],
cflags: [
"-O0",
diff --git a/base/HidlSupport.cpp b/base/HidlSupport.cpp
index f97f216..af805b9 100644
--- a/base/HidlSupport.cpp
+++ b/base/HidlSupport.cpp
@@ -35,10 +35,8 @@
}
} // namespace details
-hidl_handle::hidl_handle() {
- memset(this, 0, sizeof(*this));
- // mHandle = nullptr;
- // mOwnsHandle = false;
+hidl_handle::hidl_handle() : mHandle(nullptr), mOwnsHandle(false) {
+ memset(mPad, 0, sizeof(mPad));
}
hidl_handle::~hidl_handle() {
@@ -138,11 +136,8 @@
static const char *const kEmptyString = "";
-hidl_string::hidl_string() {
- memset(this, 0, sizeof(*this));
- // mSize is zero
- // mOwnsBuffer is false
- mBuffer = kEmptyString;
+hidl_string::hidl_string() : mBuffer(kEmptyString), mSize(0), mOwnsBuffer(false) {
+ memset(mPad, 0, sizeof(mPad));
}
hidl_string::~hidl_string() {
diff --git a/base/include/hidl/HidlSupport.h b/base/include/hidl/HidlSupport.h
index 7812099..112336f 100644
--- a/base/include/hidl/HidlSupport.h
+++ b/base/include/hidl/HidlSupport.h
@@ -20,18 +20,24 @@
#include <algorithm>
#include <array>
#include <iterator>
-#include <cutils/native_handle.h>
#include <hidl/HidlInternal.h>
-#include <hidl/Status.h>
#include <map>
#include <sstream>
#include <stddef.h>
#include <tuple>
#include <type_traits>
+#include <vector>
+
+// no requirements on types not used in scatter/gather
+// no requirements on other libraries
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wpadded"
+#include <cutils/native_handle.h>
+#include <hidl/Status.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
-#include <vector>
+#pragma clang diagnostic pop
namespace android {
@@ -123,8 +129,9 @@
private:
void freeHandle();
- details::hidl_pointer<const native_handle_t> mHandle __attribute__ ((aligned(8)));
- bool mOwnsHandle __attribute ((aligned(8)));
+ details::hidl_pointer<const native_handle_t> mHandle;
+ bool mOwnsHandle;
+ uint8_t mPad[7];
};
struct hidl_string {
@@ -174,6 +181,7 @@
details::hidl_pointer<const char> mBuffer;
uint32_t mSize; // NOT including the terminating '\0'.
bool mOwnsBuffer; // if true then mBuffer is a mutable char *
+ uint8_t mPad[3];
// copy from data with size. Assume that my memory is freed
// (through clear(), for example)
@@ -294,9 +302,9 @@
static const size_t kOffsetOfName;
private:
- hidl_handle mHandle __attribute__ ((aligned(8)));
- uint64_t mSize __attribute__ ((aligned(8)));
- hidl_string mName __attribute__ ((aligned(8)));
+ hidl_handle mHandle;
+ uint64_t mSize;
+ hidl_string mName;
};
// HidlMemory is a wrapper class to support sp<> for hidl_memory. It also
@@ -326,15 +334,12 @@
template<typename T>
struct hidl_vec {
- hidl_vec() {
+ hidl_vec() : mBuffer(nullptr), mSize(0), mOwnsBuffer(true) {
static_assert(hidl_vec<T>::kOffsetOfBuffer == 0, "wrong offset");
- memset(this, 0, sizeof(*this));
- // mSize is 0
- // mBuffer is nullptr
+ // mOwnsBuffer true to match original implementation
- // this is for consistency with the original implementation
- mOwnsBuffer = true;
+ memset(mPad, 0, sizeof(mPad));
}
// Note, does not initialize primitive types.
@@ -576,6 +581,7 @@
details::hidl_pointer<T> mBuffer;
uint32_t mSize;
bool mOwnsBuffer;
+ uint8_t mPad[3];
// copy from an array-like object, assuming my resources are freed.
template <typename Array>
diff --git a/test_main.cpp b/test_main.cpp
index 2b9f52c..9db076c 100644
--- a/test_main.cpp
+++ b/test_main.cpp
@@ -16,11 +16,16 @@
#define LOG_TAG "LibHidlTest"
+#pragma clang diagnostic push
+#pragma clang diagnostic fatal "-Wpadded"
+#include <hidl/HidlInternal.h>
+#include <hidl/HidlSupport.h>
+#pragma clang diagnostic pop
+
#include <android-base/logging.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <hidl/HidlSupport.h>
#include <hidl/ServiceManagement.h>
#include <hidl/Status.h>
#include <hidl/TaskRunner.h>
@@ -488,6 +493,51 @@
EXPECT_TRUE(isLibraryOpen(kLib));
}
+template <typename T, size_t start, size_t end>
+static void assertZeroInRange(const T* t) {
+ static_assert(start < sizeof(T));
+ static_assert(end <= sizeof(T));
+
+ const uint8_t* ptr = reinterpret_cast<const uint8_t*>(t);
+
+ for (size_t i = start; i < end; i++) {
+ EXPECT_EQ(0, ptr[i]);
+ }
+}
+
+template <typename T, size_t start, size_t end>
+static void uninitTest() {
+ uint8_t buf[sizeof(T)];
+ memset(buf, 0xFF, sizeof(T));
+
+ T* type = new (buf) T;
+ assertZeroInRange<T, start, end>(type);
+ type->~T();
+}
+
+TEST_F(LibHidlTest, HidlVecUninit) {
+ using ::android::hardware::hidl_vec;
+ struct SomeType {};
+ static_assert(sizeof(hidl_vec<SomeType>) == 16);
+
+ // padding after mOwnsBuffer
+ uninitTest<hidl_vec<SomeType>, 13, 16>();
+}
+TEST_F(LibHidlTest, HidlHandleUninit) {
+ using ::android::hardware::hidl_handle;
+ static_assert(sizeof(hidl_handle) == 16);
+
+ // padding after mOwnsHandle
+ uninitTest<hidl_handle, 9, 16>();
+}
+TEST_F(LibHidlTest, HidlStringUninit) {
+ using ::android::hardware::hidl_string;
+ static_assert(sizeof(hidl_string) == 16);
+
+ // padding after mOwnsBuffer
+ uninitTest<hidl_string, 13, 16>();
+}
+
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();