Skip to content

Commit

Permalink
ipc: Update Message::FindNext to parse brokered attachments.
Browse files Browse the repository at this point in the history
The method Message::FindNext now takes an output parameter NextMessageInfo which
contains additional metadata needed for generating brokered attachments.

BUG=493414

Review URL: https://codereview.chromium.org/1308613006

Cr-Commit-Position: refs/heads/master@{#348459}
  • Loading branch information
erikchen authored and Commit bot committed Sep 11, 2015
1 parent b37d327 commit 29e0f2f
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 14 deletions.
16 changes: 10 additions & 6 deletions ipc/ipc_channel_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,15 @@ bool ChannelReader::TranslateInputData(const char* input_data,

// Dispatch all complete messages in the data buffer.
while (p < end) {
const char* message_tail = Message::FindNext(p, end);
if (message_tail) {
int len = static_cast<int>(message_tail - p);
Message::NextMessageInfo info;
Message::FindNext(p, end, &info);
if (info.message_found) {
int pickle_len = static_cast<int>(info.pickle_end - p);
Message translated_message(p, pickle_len);

// TODO(erikchen): Make attachments for info.attachment_ids.
// http://crbug.com/493414.

Message translated_message(p, len);
if (!GetNonBrokeredAttachments(&translated_message))
return false;

Expand All @@ -109,7 +113,7 @@ bool ChannelReader::TranslateInputData(const char* input_data,
if (blocked_ids.empty()) {
// Dispatch the message and continue the loop.
DispatchMessage(&translated_message);
p = message_tail;
p = info.message_end;
continue;
}

Expand All @@ -120,7 +124,7 @@ bool ChannelReader::TranslateInputData(const char* input_data,
// Make a deep copy of |translated_message| to add to the queue.
scoped_ptr<Message> m(new Message(translated_message));
queued_messages_.push_back(m.release());
p = message_tail;
p = info.message_end;
} else {
// Last message is partial.
break;
Expand Down
53 changes: 53 additions & 0 deletions ipc/ipc_message.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#include "ipc/ipc_message.h"

#include <limits.h>

#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "build/build_config.h"
Expand Down Expand Up @@ -127,6 +129,57 @@ void Message::set_received_time(int64_t time) const {
}
#endif

Message::NextMessageInfo::NextMessageInfo()
: message_found(false), pickle_end(nullptr), message_end(nullptr) {}
Message::NextMessageInfo::~NextMessageInfo() {}

// static
void Message::FindNext(const char* range_start,
const char* range_end,
NextMessageInfo* info) {
DCHECK(info);
const char* pickle_end =
base::Pickle::FindNext(sizeof(Header), range_start, range_end);
if (!pickle_end)
return;
info->pickle_end = pickle_end;

#if USE_ATTACHMENT_BROKER
// The data is not copied.
size_t pickle_len = static_cast<size_t>(pickle_end - range_start);
Message message(range_start, static_cast<int>(pickle_len));
int num_attachments = message.header()->num_brokered_attachments;

// Check for possible overflows.
size_t max_size_t = std::numeric_limits<size_t>::max();
if (num_attachments >= max_size_t / BrokerableAttachment::kNonceSize)
return;

size_t attachment_length = num_attachments * BrokerableAttachment::kNonceSize;
if (pickle_len > max_size_t - attachment_length)
return;

// Check whether the range includes the attachments.
size_t buffer_length = static_cast<size_t>(range_end - range_start);
if (buffer_length < attachment_length + pickle_len)
return;

for (int i = 0; i < num_attachments; ++i) {
const char* attachment_start =
pickle_end + i * BrokerableAttachment::kNonceSize;
BrokerableAttachment::AttachmentId id(attachment_start,
BrokerableAttachment::kNonceSize);
info->attachment_ids.push_back(id);
}
info->message_end =
pickle_end + num_attachments * BrokerableAttachment::kNonceSize;
#else
info->message_end = pickle_end;
#endif // USE_ATTACHMENT_BROKER

info->message_found = true;
}

bool Message::WriteAttachment(scoped_refptr<MessageAttachment> attachment) {
// We write the index of the descriptor so that we don't have to
// keep the current descriptor as extra decoding state when deserialising.
Expand Down
33 changes: 28 additions & 5 deletions ipc/ipc_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "base/memory/ref_counted.h"
#include "base/pickle.h"
#include "base/trace_event/trace_event.h"
#include "ipc/brokerable_attachment.h"
#include "ipc/ipc_export.h"

#if !defined(NDEBUG)
Expand Down Expand Up @@ -166,11 +167,33 @@ class IPC_EXPORT Message : public base::Pickle {
static void Log(std::string* name, const Message* msg, std::string* l) {
}

// Find the end of the message data that starts at range_start. Returns NULL
// if the entire message is not found in the given data range.
static const char* FindNext(const char* range_start, const char* range_end) {
return base::Pickle::FindNext(sizeof(Header), range_start, range_end);
}
// The static method FindNext() returns several pieces of information, which
// are aggregated into an instance of this struct.
struct NextMessageInfo {
NextMessageInfo();
~NextMessageInfo();

// Whether an entire message was found in the given memory range.
bool message_found;
// Only filled in if |message_found| is true.
// The start address is passed into FindNext() by the caller, so isn't
// repeated in this struct. The end address of the pickle should be used to
// construct a base::Pickle.
const char* pickle_end;
// Only filled in if |message_found| is true.
// The end address of the message should be used to determine the start
// address of the next message.
const char* message_end;
// If the message has brokerable attachments, this vector will contain the
// ids of the brokerable attachments. The caller of FindNext() is
// responsible for adding the attachments to the message.
std::vector<BrokerableAttachment::AttachmentId> attachment_ids;
};

// |info| is an output parameter and must not be nullptr.
static void FindNext(const char* range_start,
const char* range_end,
NextMessageInfo* info);

// WriteAttachment appends |attachment| to the end of the set. It returns
// false iff the set is full.
Expand Down
8 changes: 5 additions & 3 deletions tools/ipc_fuzzer/message_lib/message_file_reader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,15 @@ bool Reader::ReadMessages() {
for (size_t i = 0; i < header_->message_count; ++i) {
const char* begin = file_data_.begin();
const char* end = file_data_.end();
const char* message_tail = IPC::Message::FindNext(begin, end);
if (!message_tail) {
Message::NextMessageInfo info;
IPC::Message::FindNext(begin, end, &info);
if (!info.message_found) {
LOG(ERROR) << "Failed to parse message.";
return false;
}

size_t msglen = message_tail - begin;
CHECK_EQ(info.message_end, info.pickle_end);
size_t msglen = info.message_end - begin;
if (msglen > INT_MAX) {
LOG(ERROR) << "Message too large.";
return false;
Expand Down

0 comments on commit 29e0f2f

Please sign in to comment.