Index: mojo/public/cpp/bindings/lib/bindings_serialization.cc |
diff --git a/mojo/public/cpp/bindings/lib/bindings_serialization.cc b/mojo/public/cpp/bindings/lib/bindings_serialization.cc |
index 5e60c65a5c4b52e8e89a46b36ab368958d2c6696..8690ff0168301bf22f31dfc724780d310a887225 100644 |
--- a/mojo/public/cpp/bindings/lib/bindings_serialization.cc |
+++ b/mojo/public/cpp/bindings/lib/bindings_serialization.cc |
@@ -7,15 +7,17 @@ |
#include <assert.h> |
#include "mojo/public/cpp/bindings/lib/bindings_internal.h" |
+#include "mojo/public/cpp/bindings/lib/bounds_checker.h" |
namespace mojo { |
namespace internal { |
namespace { |
+const size_t kAlignment = 8; |
+ |
template<typename T> |
T AlignImpl(T t) { |
- const size_t kAlignment = 8; |
return t + (kAlignment - (t % kAlignment)) % kAlignment; |
} |
@@ -29,6 +31,10 @@ char* AlignPointer(char* ptr) { |
return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr))); |
} |
+bool IsAligned(const void* ptr) { |
+ return !(reinterpret_cast<uintptr_t>(ptr) % kAlignment); |
+} |
+ |
void EncodePointer(const void* ptr, uint64_t* offset) { |
if (!ptr) { |
*offset = 0; |
@@ -48,6 +54,12 @@ const void* DecodePointerRaw(const uint64_t* offset) { |
return reinterpret_cast<const char*>(offset) + *offset; |
} |
+bool ValidateEncodedPointer(const uint64_t* offset) { |
+ // Cast to uintptr_t so overflow behavior is well defined. |
+ return reinterpret_cast<uintptr_t>(offset) + *offset >= |
+ reinterpret_cast<uintptr_t>(offset); |
+} |
+ |
bool ValidatePointer(const void* ptr, const Message& message) { |
const uint8_t* data = static_cast<const uint8_t*>(ptr); |
if (reinterpret_cast<uintptr_t>(data) % 8 != 0) |
@@ -64,14 +76,12 @@ void EncodeHandle(Handle* handle, std::vector<Handle>* handles) { |
handles->push_back(*handle); |
handle->set_value(static_cast<MojoHandle>(handles->size() - 1)); |
} else { |
- // Encode -1 to mean the invalid handle. |
- handle->set_value(static_cast<MojoHandle>(-1)); |
+ handle->set_value(kEncodedInvalidHandleValue); |
} |
} |
bool DecodeHandle(Handle* handle, std::vector<Handle>* handles) { |
- // Decode -1 to mean the invalid handle. |
- if (handle->value() == static_cast<MojoHandle>(-1)) { |
+ if (handle->value() == kEncodedInvalidHandleValue) { |
*handle = Handle(); |
return true; |
} |
@@ -82,5 +92,28 @@ bool DecodeHandle(Handle* handle, std::vector<Handle>* handles) { |
return true; |
} |
+bool ValidateStructHeader(const void* data, |
+ uint32_t min_num_bytes, |
+ uint32_t min_num_fields, |
+ BoundsChecker* bounds_checker) { |
+ if (!IsAligned(data)) |
+ return false; |
+ if (!bounds_checker->IsWithinUnclaimedRange(data, sizeof(StructHeader))) |
+ return false; |
+ |
+ const StructHeader* header = static_cast<const StructHeader*>(data); |
+ |
+ // TODO(yzshen): Currently our binding code cannot handle structs of smaller |
+ // size or with fewer fields than the version that it sees. That needs to be |
+ // changed in order to provide backward compatibility. |
+ if (header->num_bytes < min_num_bytes || header->num_fields < min_num_fields) |
+ return false; |
+ |
+ if (!bounds_checker->ClaimMemory(data, header->num_bytes)) |
+ return false; |
+ |
+ return true; |
+} |
+ |
} // namespace internal |
} // namespace mojo |