tor-browser

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

ipc_message_utils.cc (4126B)


      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 "chrome/common/ipc_message_utils.h"
      8 #include "mozilla/ipc/SharedMemoryCursor.h"
      9 
     10 namespace IPC {
     11 
     12 MessageBufferWriter::MessageBufferWriter(MessageWriter* writer,
     13                                         uint32_t full_len)
     14    : writer_(writer) {
     15  // NOTE: We only write out the `shmem_ok` bool if we're over
     16  // kMessageBufferShmemThreshold to avoid bloating the size of messages with
     17  // small buffers.
     18  if (full_len > kMessageBufferShmemThreshold) {
     19    auto handle = mozilla::ipc::shared_memory::Create(full_len);
     20    bool shmem_ok = handle.IsValid();
     21    writer->WriteBool(shmem_ok);
     22    if (shmem_ok) {
     23      shmem_cursor_ = mozilla::MakeUnique<mozilla::ipc::shared_memory::Cursor>(
     24          std::move(handle));
     25      MOZ_ASSERT(shmem_cursor_->IsValid());
     26    } else {
     27      writer->NoteLargeBufferShmemFailure(full_len);
     28    }
     29  }
     30  remaining_ = full_len;
     31 }
     32 
     33 MessageBufferWriter::~MessageBufferWriter() {
     34  if (remaining_ != 0) {
     35    writer_->FatalError("didn't fully write message buffer");
     36  }
     37 
     38  // We couldn't write out the shared memory region until now, as the cursor
     39  // needs to hold on to the handle to potentially re-map sub-regions while
     40  // writing.
     41  if (shmem_cursor_) {
     42    IPC::WriteParam(writer_, shmem_cursor_->TakeHandle());
     43  }
     44 }
     45 
     46 bool MessageBufferWriter::WriteBytes(const void* data, uint32_t len) {
     47  MOZ_RELEASE_ASSERT(len == remaining_ || (len % 4) == 0,
     48                     "all writes except for the final write must be a multiple "
     49                     "of 4 bytes in length due to padding");
     50  if (len > remaining_) {
     51    writer_->FatalError("MessageBufferWriter overrun");
     52    return false;
     53  }
     54  remaining_ -= len;
     55  // If we're serializing using a shared memory region, `shmem_cursor_` will be
     56  // initialized.
     57  if (shmem_cursor_) {
     58    return shmem_cursor_->Write(data, len);
     59  }
     60  return writer_->WriteBytes(data, len);
     61 }
     62 
     63 MessageBufferReader::MessageBufferReader(MessageReader* reader,
     64                                         uint32_t full_len)
     65    : reader_(reader) {
     66  // NOTE: We only write out the `shmem_ok` bool if we're over
     67  // kMessageBufferShmemThreshold to avoid bloating the size of messages with
     68  // small buffers.
     69  if (full_len > kMessageBufferShmemThreshold) {
     70    bool shmem_ok = false;
     71    if (!reader->ReadBool(&shmem_ok)) {
     72      reader->FatalError("MessageReader::ReadBool failed!");
     73      return;
     74    }
     75    if (shmem_ok) {
     76      mozilla::ipc::shared_memory::MutableHandle handle;
     77      if (!IPC::ReadParam(reader, &handle)) {
     78        reader->FatalError("failed to read shared memory handle");
     79        return;
     80      }
     81      if (!handle.IsValid()) {
     82        reader->FatalError("invalid shared memory handle");
     83        return;
     84      }
     85      if (handle.Size() < full_len) {
     86        reader->FatalError("too small shared memory handle");
     87        return;
     88      }
     89      shmem_cursor_ = mozilla::MakeUnique<mozilla::ipc::shared_memory::Cursor>(
     90          std::move(handle));
     91      MOZ_ASSERT(shmem_cursor_->IsValid());
     92    }
     93  }
     94  remaining_ = full_len;
     95 }
     96 
     97 MessageBufferReader::~MessageBufferReader() {
     98  if (remaining_ != 0) {
     99    reader_->FatalError("didn't fully write message buffer");
    100  }
    101 }
    102 
    103 bool MessageBufferReader::ReadBytesInto(void* data, uint32_t len) {
    104  MOZ_RELEASE_ASSERT(len == remaining_ || (len % 4) == 0,
    105                     "all reads except for the final read must be a multiple "
    106                     "of 4 bytes in length due to padding");
    107  if (len > remaining_) {
    108    reader_->FatalError("MessageBufferReader overrun");
    109    return false;
    110  }
    111  remaining_ -= len;
    112  // If we're serializing using a shared memory region, `shmem_cursor_` will be
    113  // initialized.
    114  if (shmem_cursor_) {
    115    return shmem_cursor_->Read(data, len);
    116  }
    117  return reader_->ReadBytesInto(data, len);
    118 }
    119 
    120 }  // namespace IPC