Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d97be4d authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Add static assert to check if FuseBuffer is standard layout union.

Bug: 32260320
Test: libappfuse_test
Change-Id: I6430c11fdeb2405996410c97044b4260c25209b8
parent a0aecda1
Loading
Loading
Loading
Loading
+19 −11
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <unistd.h>

#include <algorithm>
#include <type_traits>

#include <android-base/logging.h>
#include <android-base/macros.h>
@@ -28,9 +29,14 @@
namespace android {
namespace fuse {

template <typename T, typename Header>
bool FuseMessage<T, Header>::CheckHeaderLength() const {
  if (sizeof(Header) <= header.len && header.len <= sizeof(T)) {
static_assert(
    std::is_standard_layout<FuseBuffer>::value,
    "FuseBuffer must be standard layout union.");

template <typename T>
bool FuseMessage<T>::CheckHeaderLength() const {
  const auto& header = static_cast<const T*>(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<T, Header>::CheckHeaderLength() const {
  }
}

template <typename T, typename Header>
bool FuseMessage<T, Header>::CheckResult(
template <typename T>
bool FuseMessage<T>::CheckResult(
    int result, const char* operation_name) const {
  const auto& header = static_cast<const T*>(this)->header;
  if (result >= 0 && static_cast<uint32_t>(result) == header.len) {
    return true;
  } else {
@@ -51,14 +58,15 @@ bool FuseMessage<T, Header>::CheckResult(
  }
}

template <typename T, typename Header>
bool FuseMessage<T, Header>::Read(int fd) {
template <typename T>
bool FuseMessage<T>::Read(int fd) {
  const ssize_t result = TEMP_FAILURE_RETRY(::read(fd, this, sizeof(T)));
  return CheckHeaderLength() && CheckResult(result, "read");
}

template <typename T, typename Header>
bool FuseMessage<T, Header>::Write(int fd) const {
template <typename T>
bool FuseMessage<T>::Write(int fd) const {
  const auto& header = static_cast<const T*>(this)->header;
  if (!CheckHeaderLength()) {
    return false;
  }
@@ -66,8 +74,8 @@ bool FuseMessage<T, Header>::Write(int fd) const {
  return CheckResult(result, "write");
}

template struct FuseMessage<FuseRequest, fuse_in_header>;
template struct FuseMessage<FuseResponse, fuse_out_header>;
template class FuseMessage<FuseRequest>;
template class FuseMessage<FuseResponse>;

void FuseRequest::Reset(
    uint32_t data_length, uint32_t opcode, uint64_t unique) {
+7 −5
Original line number Diff line number Diff line
@@ -28,9 +28,9 @@ constexpr size_t kFuseMaxWrite = 256 * 1024;
constexpr size_t kFuseMaxRead = 128 * 1024;
constexpr int32_t kFuseSuccess = 0;

template<typename T, typename Header>
struct FuseMessage {
  Header header;
template<typename T>
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<FuseRequest, fuse_in_header> {
struct FuseRequest : public FuseMessage<FuseRequest> {
  fuse_in_header header;
  union {
    // for FUSE_WRITE
    struct {
@@ -61,7 +62,8 @@ struct FuseRequest final : public FuseMessage<FuseRequest, fuse_in_header> {

// 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<FuseResponse, fuse_out_header> {
struct FuseResponse : public FuseMessage<FuseResponse> {
  fuse_out_header header;
  union {
    // for FUSE_INIT
    fuse_init_out init_out;