| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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. | |
| 4 | |
| 5 #include <mojo/bindings/array.h> | |
| 6 | |
| 7 #include <assert.h> | |
| 8 #include <mojo/bindings/buffer.h> | |
| 9 #include <mojo/bindings/interface.h> | |
| 10 #include <mojo/bindings/internal/type_descriptor.h> | |
| 11 #include <mojo/bindings/internal/util.h> | |
| 12 #include <mojo/bindings/union.h> | |
| 13 #include <stddef.h> | |
| 14 #include <stdint.h> | |
| 15 #include <string.h> | |
| 16 | |
| 17 struct MojomArrayHeader* MojomArray_New(struct MojomBuffer* buf, | |
| 18 uint32_t num_elements, | |
| 19 uint32_t element_byte_size) { | |
| 20 assert(buf); | |
| 21 | |
| 22 uint64_t num_bytes = sizeof(struct MojomArrayHeader) + | |
| 23 (uint64_t)num_elements * element_byte_size; | |
| 24 if (num_bytes > UINT32_MAX) | |
| 25 return NULL; | |
| 26 | |
| 27 struct MojomArrayHeader* arr = | |
| 28 (struct MojomArrayHeader*)MojomBuffer_Allocate(buf, (uint32_t)num_bytes); | |
| 29 if (arr == NULL) | |
| 30 return NULL; | |
| 31 | |
| 32 assert((uintptr_t)arr + MOJOM_INTERNAL_ROUND_TO_8(num_bytes) == | |
| 33 (uintptr_t)buf->buf + buf->num_bytes_used); | |
| 34 | |
| 35 arr->num_elements = num_elements; | |
| 36 arr->num_bytes = MOJOM_INTERNAL_ROUND_TO_8((uint32_t)num_bytes); | |
| 37 | |
| 38 return arr; | |
| 39 } | |
| 40 | |
| 41 // Gets the |index|th element (whose type is described by |type|) of |array|. | |
| 42 // Only supports non-POD types. | |
| 43 static void* array_index_by_type(const struct MojomArrayHeader* array, | |
| 44 enum MojomTypeDescriptorType type, | |
| 45 size_t index) { | |
| 46 switch (type) { | |
| 47 case MOJOM_TYPE_DESCRIPTOR_TYPE_STRUCT_PTR: | |
| 48 case MOJOM_TYPE_DESCRIPTOR_TYPE_MAP_PTR: | |
| 49 case MOJOM_TYPE_DESCRIPTOR_TYPE_ARRAY_PTR: | |
| 50 return MOJOM_ARRAY_INDEX(array, union MojomPointer, index); | |
| 51 case MOJOM_TYPE_DESCRIPTOR_TYPE_UNION: | |
| 52 return MOJOM_ARRAY_INDEX(array, struct MojomUnionLayout, index); | |
| 53 case MOJOM_TYPE_DESCRIPTOR_TYPE_HANDLE: | |
| 54 return MOJOM_ARRAY_INDEX(array, MojoHandle, index); | |
| 55 case MOJOM_TYPE_DESCRIPTOR_TYPE_INTERFACE: | |
| 56 return MOJOM_ARRAY_INDEX(array, struct MojomInterfaceData, index); | |
| 57 case MOJOM_TYPE_DESCRIPTOR_TYPE_UNION_PTR: | |
| 58 case MOJOM_TYPE_DESCRIPTOR_TYPE_POD: | |
| 59 // This is a type that isn't supported in an array. | |
| 60 assert(0); | |
| 61 break; | |
| 62 } | |
| 63 return NULL; | |
| 64 } | |
| 65 | |
| 66 size_t MojomArray_ComputeSerializedSize( | |
| 67 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 68 const struct MojomArrayHeader* in_array) { | |
| 69 assert(in_array); | |
| 70 assert(in_type_desc); | |
| 71 | |
| 72 size_t size = in_array->num_bytes; | |
| 73 if (!MojomType_IsPointer(in_type_desc->elem_type) && | |
| 74 in_type_desc->elem_type != MOJOM_TYPE_DESCRIPTOR_TYPE_UNION) | |
| 75 return size; | |
| 76 | |
| 77 for (uint32_t i = 0; i < in_array->num_elements; i++) { | |
| 78 size += MojomType_DispatchComputeSerializedSize( | |
| 79 in_type_desc->elem_type, | |
| 80 in_type_desc->elem_descriptor, | |
| 81 in_type_desc->nullable, | |
| 82 array_index_by_type(in_array, in_type_desc->elem_type, i)); | |
| 83 } | |
| 84 | |
| 85 return size; | |
| 86 } | |
| 87 | |
| 88 void MojomArray_EncodePointersAndHandles( | |
| 89 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 90 struct MojomArrayHeader* inout_array, | |
| 91 uint32_t in_array_size, | |
| 92 struct MojomHandleBuffer* inout_handles_buffer) { | |
| 93 assert(in_type_desc); | |
| 94 assert(inout_array); | |
| 95 assert(in_array_size >= sizeof(struct MojomArrayHeader)); | |
| 96 assert(in_array_size >= inout_array->num_bytes); | |
| 97 | |
| 98 // Nothing to encode for POD types. | |
| 99 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
| 100 return; | |
| 101 | |
| 102 for (size_t i = 0; i < inout_array->num_elements; i++) { | |
| 103 char* elem_data = | |
| 104 array_index_by_type(inout_array, in_type_desc->elem_type, i); | |
| 105 assert(elem_data < (char*)inout_array + in_array_size); | |
| 106 | |
| 107 MojomType_DispatchEncodePointersAndHandles( | |
| 108 in_type_desc->elem_type, | |
| 109 in_type_desc->elem_descriptor, | |
| 110 in_type_desc->nullable, | |
| 111 elem_data, | |
| 112 in_array_size - (uint32_t)(elem_data - (char*)inout_array), | |
| 113 inout_handles_buffer); | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 void MojomArray_DecodePointersAndHandles( | |
| 118 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 119 struct MojomArrayHeader* inout_array, | |
| 120 uint32_t in_array_size, | |
| 121 MojoHandle* inout_handles, | |
| 122 uint32_t in_num_handles) { | |
| 123 assert(in_type_desc); | |
| 124 assert(inout_array); | |
| 125 assert(inout_handles != NULL || in_num_handles == 0); | |
| 126 | |
| 127 // Nothing to encode for POD types. | |
| 128 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
| 129 return; | |
| 130 | |
| 131 for (size_t i = 0; i < inout_array->num_elements; i++) { | |
| 132 char* elem_data = | |
| 133 array_index_by_type(inout_array, in_type_desc->elem_type, i); | |
| 134 assert(elem_data < (char*)inout_array + in_array_size); | |
| 135 | |
| 136 MojomType_DispatchDecodePointersAndHandles( | |
| 137 in_type_desc->elem_type, | |
| 138 in_type_desc->elem_descriptor, | |
| 139 in_type_desc->nullable, | |
| 140 elem_data, | |
| 141 in_array_size - (uint32_t)(elem_data - (char*)inout_array), | |
| 142 inout_handles, | |
| 143 in_num_handles); | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 // Rounds up to nearest byte. | |
| 148 static uint64_t bits_to_bytes(uint64_t bits) { | |
| 149 return (bits + 7) / 8; | |
| 150 } | |
| 151 | |
| 152 static MojomValidationResult validate_array_header( | |
| 153 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 154 const struct MojomArrayHeader* in_array, | |
| 155 uint32_t in_buf_size) { | |
| 156 if (in_buf_size < sizeof(struct MojomArrayHeader)) | |
| 157 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
| 158 | |
| 159 if (in_array->num_bytes < sizeof(struct MojomArrayHeader)) | |
| 160 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
| 161 | |
| 162 if (in_array->num_bytes > in_buf_size) | |
| 163 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
| 164 | |
| 165 if (in_type_desc->num_elements != 0 && | |
| 166 in_array->num_elements != in_type_desc->num_elements) | |
| 167 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
| 168 | |
| 169 // Array size is less than what we need to fit the elements. | |
| 170 if (in_array->num_bytes < | |
| 171 sizeof(struct MojomArrayHeader) + | |
| 172 bits_to_bytes((uint64_t)in_type_desc->elem_num_bits * | |
| 173 (uint64_t)in_array->num_elements)) { | |
| 174 return MOJOM_VALIDATION_UNEXPECTED_ARRAY_HEADER; | |
| 175 } | |
| 176 | |
| 177 return MOJOM_VALIDATION_ERROR_NONE; | |
| 178 } | |
| 179 | |
| 180 MojomValidationResult MojomArray_Validate( | |
| 181 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 182 const struct MojomArrayHeader* in_array, | |
| 183 uint32_t in_array_size, | |
| 184 uint32_t in_num_handles, | |
| 185 struct MojomValidationContext* inout_context) { | |
| 186 assert(in_type_desc); | |
| 187 assert(in_array); | |
| 188 | |
| 189 MojomValidationResult result = | |
| 190 validate_array_header(in_type_desc, in_array, in_array_size); | |
| 191 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
| 192 return result; | |
| 193 | |
| 194 // From here on out, all pointers need to point past the end of this struct. | |
| 195 inout_context->next_pointer = (char*)in_array + in_array->num_bytes; | |
| 196 | |
| 197 // Nothing to validate for POD types. | |
| 198 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
| 199 return MOJOM_VALIDATION_ERROR_NONE; | |
| 200 | |
| 201 for (size_t i = 0; i < in_array->num_elements; i++) { | |
| 202 char* elem_data = | |
| 203 array_index_by_type(in_array, in_type_desc->elem_type, i); | |
| 204 | |
| 205 MojomValidationResult result = MojomType_DispatchValidate( | |
| 206 in_type_desc->elem_type, | |
| 207 in_type_desc->elem_descriptor, | |
| 208 in_type_desc->nullable, | |
| 209 elem_data, | |
| 210 in_array_size - (uint32_t)(elem_data - (char*)in_array), | |
| 211 in_num_handles, | |
| 212 inout_context); | |
| 213 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
| 214 return result; | |
| 215 } | |
| 216 | |
| 217 return MOJOM_VALIDATION_ERROR_NONE; | |
| 218 } | |
| 219 | |
| 220 bool MojomArray_DeepCopy( | |
| 221 struct MojomBuffer* buffer, | |
| 222 const struct MojomTypeDescriptorArray* in_type_desc, | |
| 223 const struct MojomArrayHeader* in_array, | |
| 224 struct MojomArrayHeader** out_array) { | |
| 225 assert(in_type_desc); | |
| 226 assert(in_array); | |
| 227 assert(out_array); | |
| 228 | |
| 229 *out_array = MojomBuffer_Allocate(buffer, in_array->num_bytes); | |
| 230 if (*out_array == NULL) | |
| 231 return false; | |
| 232 | |
| 233 memcpy(*out_array, in_array, in_array->num_bytes); | |
| 234 | |
| 235 // Nothing else to copy for POD types. | |
| 236 if (in_type_desc->elem_type == MOJOM_TYPE_DESCRIPTOR_TYPE_POD) | |
| 237 return true; | |
| 238 | |
| 239 for (size_t i = 0; i < in_array->num_elements; i++) { | |
| 240 void* in_elem_data = | |
| 241 array_index_by_type(in_array, in_type_desc->elem_type, i); | |
| 242 void* out_elem_data = | |
| 243 array_index_by_type(*out_array, in_type_desc->elem_type, i); | |
| 244 | |
| 245 if (!MojomType_DispatchDeepCopy(buffer, in_type_desc->elem_type, | |
| 246 in_type_desc->elem_descriptor, in_elem_data, | |
| 247 out_elem_data)) { | |
| 248 return false; | |
| 249 } | |
| 250 } | |
| 251 | |
| 252 return true; | |
| 253 } | |
| OLD | NEW |