From 0d97be4d7db1baa831d0432229dec08c87193919 Mon Sep 17 00:00:00 2001 From: Daichi Hirono Date: Thu, 10 Nov 2016 09:17:17 +0900 Subject: [PATCH] Add static assert to check if FuseBuffer is standard layout union. Bug: 32260320 Test: libappfuse_test Change-Id: I6430c11fdeb2405996410c97044b4260c25209b8 --- libappfuse/FuseBuffer.cc | 30 ++++++++++++++-------- libappfuse/include/libappfuse/FuseBuffer.h | 12 +++++---- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc index ca47aa8c7..74fe756a9 100644 --- a/libappfuse/FuseBuffer.cc +++ b/libappfuse/FuseBuffer.cc @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -28,9 +29,14 @@ namespace android { namespace fuse { -template -bool FuseMessage::CheckHeaderLength() const { - if (sizeof(Header) <= header.len && header.len <= sizeof(T)) { +static_assert( + std::is_standard_layout::value, + "FuseBuffer must be standard layout union."); + +template +bool FuseMessage::CheckHeaderLength() const { + const auto& header = static_cast(this)->header; + if (sizeof(header) <= header.len && header.len <= sizeof(T)) { return true; } else { LOG(ERROR) << "Packet size is invalid=" << header.len; @@ -38,9 +44,10 @@ bool FuseMessage::CheckHeaderLength() const { } } -template -bool FuseMessage::CheckResult( +template +bool FuseMessage::CheckResult( int result, const char* operation_name) const { + const auto& header = static_cast(this)->header; if (result >= 0 && static_cast(result) == header.len) { return true; } else { @@ -51,14 +58,15 @@ bool FuseMessage::CheckResult( } } -template -bool FuseMessage::Read(int fd) { +template +bool FuseMessage::Read(int fd) { const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, this, sizeof(T))); return CheckHeaderLength() && CheckResult(result, "read"); } -template -bool FuseMessage::Write(int fd) const { +template +bool FuseMessage::Write(int fd) const { + const auto& header = static_cast(this)->header; if (!CheckHeaderLength()) { return false; } @@ -66,8 +74,8 @@ bool FuseMessage::Write(int fd) const { return CheckResult(result, "write"); } -template struct FuseMessage; -template struct FuseMessage; +template class FuseMessage; +template class FuseMessage; void FuseRequest::Reset( uint32_t data_length, uint32_t opcode, uint64_t unique) { diff --git a/libappfuse/include/libappfuse/FuseBuffer.h b/libappfuse/include/libappfuse/FuseBuffer.h index 1464142c4..e7f620cb6 100644 --- a/libappfuse/include/libappfuse/FuseBuffer.h +++ b/libappfuse/include/libappfuse/FuseBuffer.h @@ -28,9 +28,9 @@ constexpr size_t kFuseMaxWrite = 256 * 1024; constexpr size_t kFuseMaxRead = 128 * 1024; constexpr int32_t kFuseSuccess = 0; -template -struct FuseMessage { - Header header; +template +class FuseMessage { + public: bool Read(int fd); bool Write(int fd) const; private: @@ -40,7 +40,8 @@ struct FuseMessage { // FuseRequest represents file operation requests from /dev/fuse. It starts // from fuse_in_header. The body layout depends on the operation code. -struct FuseRequest final : public FuseMessage { +struct FuseRequest : public FuseMessage { + fuse_in_header header; union { // for FUSE_WRITE struct { @@ -61,7 +62,8 @@ struct FuseRequest final : public FuseMessage { // FuseResponse represents file operation responses to /dev/fuse. It starts // from fuse_out_header. The body layout depends on the operation code. -struct FuseResponse final : public FuseMessage { +struct FuseResponse : public FuseMessage { + fuse_out_header header; union { // for FUSE_INIT fuse_init_out init_out;