Index: mojo/system/message_in_transit.cc |
diff --git a/mojo/system/message_in_transit.cc b/mojo/system/message_in_transit.cc |
index 6e2047ffa60a06d16e65b3dd02ecd6c24e04cd71..069218828d3edeccc8ad00b64cb769db8e011baa 100644 |
--- a/mojo/system/message_in_transit.cc |
+++ b/mojo/system/message_in_transit.cc |
@@ -16,14 +16,8 @@ |
namespace mojo { |
namespace system { |
-namespace { |
- |
- |
-} // namespace |
- |
struct MessageInTransit::PrivateStructForCompileAsserts { |
- // The size of |Header| must be appropriate to maintain alignment of the |
- // following data. |
+ // The size of |Header| must be a multiple of the alignment. |
COMPILE_ASSERT(sizeof(Header) % kMessageAlignment == 0, |
sizeof_MessageInTransit_Header_invalid); |
// Avoid dangerous situations, but making sure that the size of the "header" + |
@@ -37,10 +31,11 @@ struct MessageInTransit::PrivateStructForCompileAsserts { |
COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0, |
kMessageAlignment_not_a_multiple_of_alignment); |
+ // The maximum serialized dispatcher size must be a multiple of the alignment. |
COMPILE_ASSERT(kMaxSerializedDispatcherSize % kMessageAlignment == 0, |
kMaxSerializedDispatcherSize_not_a_multiple_of_alignment); |
- // The size of |HandleTableEntry| must be appropriate to maintain alignment. |
+ // The size of |HandleTableEntry| must be a multiple of the alignment. |
COMPILE_ASSERT(sizeof(HandleTableEntry) % kMessageAlignment == 0, |
sizeof_MessageInTransit_HandleTableEntry_invalid); |
}; |
@@ -61,6 +56,8 @@ STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment; |
STATIC_CONST_MEMBER_DEFINITION const size_t |
MessageInTransit::kMaxSerializedDispatcherSize; |
+// For each attached (Mojo) handle, there'll be a handle table entry and |
+// serialized dispatcher data. |
// static |
const size_t MessageInTransit::kMaxSecondaryBufferSize = kMaxMessageNumHandles * |
(sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize); |
@@ -256,9 +253,8 @@ void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { |
handle_table[i].offset = static_cast<uint32_t>(current_offset); |
handle_table[i].size = static_cast<uint32_t>(actual_size); |
} else { |
- // (Nothing to do on failure, since |secondary_buffer_| was cleared, and |
- // |kTypeUnknown| is zero.) |
- // The handle will simply be closed. |
+ // Nothing to do on failure, since |secondary_buffer_| was cleared, and |
+ // |kTypeUnknown| is zero. The handle was simply closed. |
LOG(ERROR) << "Failed to serialize handle to remote message pipe"; |
} |
@@ -269,10 +265,12 @@ void MessageInTransit::SerializeAndCloseDispatchers(Channel* channel) { |
UpdateTotalSize(); |
} |
+// Note: The message's secondary buffer should have been checked by calling |
+// |View::IsValid()| (on the |View|) first. |
void MessageInTransit::DeserializeDispatchers(Channel* channel) { |
DCHECK(!dispatchers_); |
- // This should have been checked by calling |IsValid()| on the |View| first. |
+ // Already checked by |View::IsValid()|: |
DCHECK_LE(num_handles(), kMaxMessageNumHandles); |
if (!num_handles()) |
@@ -282,24 +280,18 @@ void MessageInTransit::DeserializeDispatchers(Channel* channel) { |
new std::vector<scoped_refptr<Dispatcher> >(num_handles())); |
size_t handle_table_size = num_handles() * sizeof(HandleTableEntry); |
- if (secondary_buffer_size_ < handle_table_size) { |
- LOG(ERROR) << "Serialized handle table too small"; |
- return; |
- } |
+ // Already checked by |View::IsValid()|: |
+ DCHECK_LE(handle_table_size, secondary_buffer_size_); |
const HandleTableEntry* handle_table = |
static_cast<const HandleTableEntry*>(secondary_buffer_); |
for (size_t i = 0; i < num_handles(); i++) { |
size_t offset = handle_table[i].offset; |
size_t size = handle_table[i].size; |
- // TODO(vtl): Sanity-check the size. |
- if (offset % kMessageAlignment != 0 || offset > secondary_buffer_size_ || |
- offset + size > secondary_buffer_size_) { |
- // TODO(vtl): Maybe should report error (and make it possible to kill the |
- // connection with extreme prejudice). |
- LOG(ERROR) << "Invalid serialized handle table entry"; |
- continue; |
- } |
+ // Already checked by |View::IsValid()|: |
+ DCHECK_EQ(offset % kMessageAlignment, 0u); |
+ DCHECK_LE(offset, secondary_buffer_size_); |
+ DCHECK_LE(offset + size, secondary_buffer_size_); |
const void* source = static_cast<const char*>(secondary_buffer_) + offset; |
(*dispatchers_)[i] = Dispatcher::MessageInTransitAccess::Deserialize( |
@@ -314,15 +306,23 @@ const char* MessageInTransit::ValidateSecondaryBuffer( |
size_t num_handles, |
const void* secondary_buffer, |
size_t secondary_buffer_size) { |
- if (!num_handles) |
+ // Always make sure that the secondary buffer size is sane (even if we have no |
+ // handles); if it's not, someone's messing with us. |
+ if (secondary_buffer_size > kMaxSecondaryBufferSize) |
+ return "Message secondary buffer too large"; |
+ |
+ // Fast-path for the common case (no handles => no secondary buffer). |
+ if (num_handles == 0) { |
+ // We shouldn't have a secondary buffer in this case. |
+ if (secondary_buffer_size > 0) |
+ return "Message has no handles attached, but secondary buffer present"; |
return NULL; |
+ } |
+ // Sanity-check |num_handles| (before multiplying it against anything). |
if (num_handles > kMaxMessageNumHandles) |
return "Message handle payload too large"; |
- if (secondary_buffer_size > kMaxSecondaryBufferSize) |
- return "Message secondary buffer too large"; |
- |
if (secondary_buffer_size < num_handles * sizeof(HandleTableEntry)) |
return "Message secondary buffer too small"; |