14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/bindings/lib/bindings_serialization.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "mojo/public/cpp/bindings/lib/bindings_internal.h" 846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/cpp/bindings/lib/bounds_checker.h" 946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "mojo/public/cpp/bindings/lib/validation_errors.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "mojo/public/cpp/environment/logging.h" 115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo { 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace internal { 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace { 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)const size_t kAlignment = 8; 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)template<typename T> 20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)T AlignImpl(T t) { 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return t + (kAlignment - (t % kAlignment)) % kAlignment; 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} // namespace 25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)size_t Align(size_t size) { 27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return AlignImpl(size); 28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)char* AlignPointer(char* ptr) { 31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr))); 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool IsAligned(const void* ptr) { 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return !(reinterpret_cast<uintptr_t>(ptr) % kAlignment); 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void EncodePointer(const void* ptr, uint64_t* offset) { 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!ptr) { 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *offset = 0; 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return; 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const char* p_obj = reinterpret_cast<const char*>(ptr); 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const char* p_slot = reinterpret_cast<const char*>(offset); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOJO_DCHECK(p_obj > p_slot); 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *offset = static_cast<uint64_t>(p_obj - p_slot); 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const void* DecodePointerRaw(const uint64_t* offset) { 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!*offset) 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return NULL; 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return reinterpret_cast<const char*>(offset) + *offset; 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ValidateEncodedPointer(const uint64_t* offset) { 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Cast to uintptr_t so overflow behavior is well defined. 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return reinterpret_cast<uintptr_t>(offset) + *offset >= 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) reinterpret_cast<uintptr_t>(offset); 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void EncodeHandle(Handle* handle, std::vector<Handle>* handles) { 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (handle->is_valid()) { 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) handles->push_back(*handle); 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) handle->set_value(static_cast<MojoHandle>(handles->size() - 1)); 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) handle->set_value(kEncodedInvalidHandleValue); 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void DecodeHandle(Handle* handle, std::vector<Handle>* handles) { 7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (handle->value() == kEncodedInvalidHandleValue) { 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *handle = Handle(); 7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOJO_DCHECK(handle->value() < handles->size()); 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Just leave holes in the vector so we don't screw up other indices. 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *handle = FetchAndReset(&handles->at(handle->value())); 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)bool ValidateStructHeader(const void* data, 8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uint32_t min_num_bytes, 8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) uint32_t min_num_fields, 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BoundsChecker* bounds_checker) { 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOJO_DCHECK(min_num_bytes >= sizeof(StructHeader)); 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!IsAligned(data)) { 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT); 9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!bounds_checker->IsValidRange(data, sizeof(StructHeader))) { 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const StructHeader* header = static_cast<const StructHeader*>(data); 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // TODO(yzshen): Currently our binding code cannot handle structs of smaller 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // size or with fewer fields than the version that it sees. That needs to be 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // changed in order to provide backward compatibility. 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (header->num_bytes < min_num_bytes || 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) header->num_fields < min_num_fields) { 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER); 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!bounds_checker->ClaimMemory(data, header->num_bytes)) { 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE); 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return false; 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace internal 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace mojo 118