tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

BigBuffer.cpp (3711B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/ipc/BigBuffer.h"
      8 
      9 #include "chrome/common/ipc_message_utils.h"
     10 #include "nsDebug.h"
     11 
     12 namespace mozilla::ipc {
     13 
     14 BigBuffer::BigBuffer(Adopt, SharedMemoryMappingWithHandle&& aSharedMemory,
     15                     size_t aSize)
     16    : mSize(aSize), mData(AsVariant(std::move(aSharedMemory))) {
     17  MOZ_RELEASE_ASSERT(mData.as<1>(), "shared memory must be valid");
     18  MOZ_RELEASE_ASSERT(mSize <= mData.as<1>().Size(),
     19                     "shared memory region isn't large enough");
     20 }
     21 
     22 BigBuffer::BigBuffer(Adopt, uint8_t* aData, size_t aSize)
     23    : mSize(aSize), mData(AsVariant(UniqueFreePtr<uint8_t[]>{aData})) {}
     24 
     25 uint8_t* BigBuffer::Data() {
     26  return mData.is<0>() ? mData.as<0>().get() : mData.as<1>().DataAs<uint8_t>();
     27 }
     28 const uint8_t* BigBuffer::Data() const {
     29  return mData.is<0>() ? mData.as<0>().get()
     30                       : mData.as<1>().DataAs<const uint8_t>();
     31 }
     32 
     33 auto BigBuffer::TryAllocBuffer(size_t aSize) -> Maybe<Storage> {
     34  if (aSize <= kShmemThreshold) {
     35    auto mem = UniqueFreePtr<uint8_t[]>{
     36        reinterpret_cast<uint8_t*>(malloc(aSize))};  // Fallible!
     37    if (!mem) return {};
     38    return Some(AsVariant(std::move(mem)));
     39  }
     40 
     41  size_t capacity = shared_memory::PageAlignedSize(aSize);
     42  auto mapping = shared_memory::Create(capacity).MapWithHandle();
     43  if (!mapping) {
     44    return {};
     45  }
     46  return Some(AsVariant(std::move(mapping)));
     47 }
     48 
     49 }  // namespace mozilla::ipc
     50 
     51 void IPC::ParamTraits<mozilla::ipc::BigBuffer>::Write(MessageWriter* aWriter,
     52                                                      paramType&& aParam) {
     53  using namespace mozilla::ipc;
     54  size_t size = std::exchange(aParam.mSize, 0);
     55  auto data = std::exchange(aParam.mData, BigBuffer::NoData());
     56 
     57  WriteParam(aWriter, size);
     58  bool isShmem = data.is<1>();
     59  WriteParam(aWriter, isShmem);
     60 
     61  if (isShmem) {
     62    auto handle = data.as<1>().Handle().Clone();
     63    if (!handle) {
     64      aWriter->FatalError("Failed to write data shmem");
     65    } else {
     66      WriteParam(aWriter, std::move(handle));
     67    }
     68  } else {
     69    aWriter->WriteBytes(data.as<0>().get(), size);
     70  }
     71 }
     72 
     73 bool IPC::ParamTraits<mozilla::ipc::BigBuffer>::Read(MessageReader* aReader,
     74                                                     paramType* aResult) {
     75  using namespace mozilla::ipc;
     76  size_t size = 0;
     77  bool isShmem = false;
     78  if (!ReadParam(aReader, &size) || !ReadParam(aReader, &isShmem)) {
     79    aReader->FatalError("Failed to read data size and format");
     80    return false;
     81  }
     82 
     83  if (isShmem) {
     84    MutableSharedMemoryHandle handle;
     85    size_t expected_size = shared_memory::PageAlignedSize(size);
     86    if (!ReadParam(aReader, &handle) || !handle) {
     87      aReader->FatalError("Failed to read data shmem");
     88      return false;
     89    }
     90    auto mapping = std::move(handle).MapWithHandle();
     91    if (!mapping || mapping.Size() != expected_size) {
     92      aReader->FatalError("Failed to map data shmem");
     93      return false;
     94    }
     95    *aResult = BigBuffer(BigBuffer::Adopt{}, std::move(mapping), size);
     96    return true;
     97  }
     98 
     99  mozilla::UniqueFreePtr<uint8_t[]> buf{
    100      reinterpret_cast<uint8_t*>(malloc(size))};
    101  if (!buf) {
    102    aReader->FatalError("Failed to allocate data buffer");
    103    return false;
    104  }
    105  if (!aReader->ReadBytesInto(buf.get(), size)) {
    106    aReader->FatalError("Failed to read data");
    107    return false;
    108  }
    109  *aResult = BigBuffer(BigBuffer::Adopt{}, buf.release(), size);
    110  return true;
    111 }