1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "mojo/public/cpp/bindings/lib/bindings_serialization.h"
7 #include "mojo/public/cpp/bindings/lib/bindings_internal.h"
8 #include "mojo/public/cpp/bindings/lib/bounds_checker.h"
9 #include "mojo/public/cpp/bindings/lib/validation_errors.h"
10 #include "mojo/public/cpp/environment/logging.h"
17 const size_t kAlignment
= 8;
21 return t
+ (kAlignment
- (t
% kAlignment
)) % kAlignment
;
26 size_t Align(size_t size
) {
27 return AlignImpl(size
);
30 char* AlignPointer(char* ptr
) {
31 return reinterpret_cast<char*>(AlignImpl(reinterpret_cast<uintptr_t>(ptr
)));
34 bool IsAligned(const void* ptr
) {
35 return !(reinterpret_cast<uintptr_t>(ptr
) % kAlignment
);
38 void EncodePointer(const void* ptr
, uint64_t* offset
) {
44 const char* p_obj
= reinterpret_cast<const char*>(ptr
);
45 const char* p_slot
= reinterpret_cast<const char*>(offset
);
46 MOJO_DCHECK(p_obj
> p_slot
);
48 *offset
= static_cast<uint64_t>(p_obj
- p_slot
);
51 const void* DecodePointerRaw(const uint64_t* offset
) {
54 return reinterpret_cast<const char*>(offset
) + *offset
;
57 bool ValidateEncodedPointer(const uint64_t* offset
) {
58 // Cast to uintptr_t so overflow behavior is well defined.
59 return reinterpret_cast<uintptr_t>(offset
) + *offset
>=
60 reinterpret_cast<uintptr_t>(offset
);
63 void EncodeHandle(Handle
* handle
, std::vector
<Handle
>* handles
) {
64 if (handle
->is_valid()) {
65 handles
->push_back(*handle
);
66 handle
->set_value(static_cast<MojoHandle
>(handles
->size() - 1));
68 handle
->set_value(kEncodedInvalidHandleValue
);
72 void DecodeHandle(Handle
* handle
, std::vector
<Handle
>* handles
) {
73 if (handle
->value() == kEncodedInvalidHandleValue
) {
77 MOJO_DCHECK(handle
->value() < handles
->size());
78 // Just leave holes in the vector so we don't screw up other indices.
79 *handle
= FetchAndReset(&handles
->at(handle
->value()));
82 bool ValidateStructHeader(const void* data
,
83 uint32_t min_num_bytes
,
84 uint32_t min_num_fields
,
85 BoundsChecker
* bounds_checker
) {
86 MOJO_DCHECK(min_num_bytes
>= sizeof(StructHeader
));
88 if (!IsAligned(data
)) {
89 ReportValidationError(VALIDATION_ERROR_MISALIGNED_OBJECT
);
92 if (!bounds_checker
->IsValidRange(data
, sizeof(StructHeader
))) {
93 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE
);
97 const StructHeader
* header
= static_cast<const StructHeader
*>(data
);
99 // TODO(yzshen): Currently our binding code cannot handle structs of smaller
100 // size or with fewer fields than the version that it sees. That needs to be
101 // changed in order to provide backward compatibility.
102 if (header
->num_bytes
< min_num_bytes
||
103 header
->num_fields
< min_num_fields
) {
104 ReportValidationError(VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER
);
108 if (!bounds_checker
->ClaimMemory(data
, header
->num_bytes
)) {
109 ReportValidationError(VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE
);
116 } // namespace internal