| 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/struct.h> | |
| 6 | |
| 7 #include <assert.h> | |
| 8 #include <mojo/bindings/internal/type_descriptor.h> | |
| 9 #include <mojo/bindings/union.h> | |
| 10 #include <string.h> | |
| 11 | |
| 12 size_t MojomStruct_ComputeSerializedSize( | |
| 13 const struct MojomTypeDescriptorStruct* in_type_desc, | |
| 14 const struct MojomStructHeader* in_struct) { | |
| 15 assert(in_struct); | |
| 16 assert(in_type_desc); | |
| 17 | |
| 18 size_t size = in_struct->num_bytes; | |
| 19 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
| 20 const struct MojomTypeDescriptorStructEntry* entry = | |
| 21 &(in_type_desc->entries[i]); | |
| 22 | |
| 23 if (!MojomType_IsPointer(entry->elem_type) && | |
| 24 entry->elem_type != MOJOM_TYPE_DESCRIPTOR_TYPE_UNION) | |
| 25 continue; | |
| 26 | |
| 27 if (in_struct->version < entry->min_version) | |
| 28 continue; | |
| 29 | |
| 30 size += MojomType_DispatchComputeSerializedSize( | |
| 31 entry->elem_type, entry->elem_descriptor, entry->nullable, | |
| 32 (char*)in_struct + sizeof(struct MojomStructHeader) + entry->offset); | |
| 33 } | |
| 34 return size; | |
| 35 } | |
| 36 | |
| 37 void MojomStruct_EncodePointersAndHandles( | |
| 38 const struct MojomTypeDescriptorStruct* in_type_desc, | |
| 39 struct MojomStructHeader* inout_struct, | |
| 40 uint32_t in_struct_size, | |
| 41 struct MojomHandleBuffer* inout_handles_buffer) { | |
| 42 assert(in_type_desc); | |
| 43 assert(inout_struct); | |
| 44 assert(in_struct_size >= sizeof(struct MojomStructHeader)); | |
| 45 | |
| 46 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
| 47 const struct MojomTypeDescriptorStructEntry* entry = | |
| 48 &(in_type_desc->entries[i]); | |
| 49 | |
| 50 if (inout_struct->version < entry->min_version) | |
| 51 continue; | |
| 52 | |
| 53 assert(sizeof(struct MojomStructHeader) + entry->offset < in_struct_size); | |
| 54 void* elem_data = ((char*)inout_struct + sizeof(struct MojomStructHeader) + | |
| 55 entry->offset); | |
| 56 | |
| 57 MojomType_DispatchEncodePointersAndHandles( | |
| 58 entry->elem_type, | |
| 59 entry->elem_descriptor, | |
| 60 entry->nullable, | |
| 61 elem_data, | |
| 62 in_struct_size - ((char*)elem_data - (char*)inout_struct), | |
| 63 inout_handles_buffer); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 void MojomStruct_DecodePointersAndHandles( | |
| 68 const struct MojomTypeDescriptorStruct* in_type_desc, | |
| 69 struct MojomStructHeader* inout_struct, | |
| 70 uint32_t in_struct_size, | |
| 71 MojoHandle* inout_handles, | |
| 72 uint32_t in_num_handles) { | |
| 73 assert(in_type_desc); | |
| 74 assert(inout_struct); | |
| 75 assert(inout_handles != NULL || in_num_handles == 0); | |
| 76 | |
| 77 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
| 78 const struct MojomTypeDescriptorStructEntry* entry = | |
| 79 &(in_type_desc->entries[i]); | |
| 80 | |
| 81 if (inout_struct->version < entry->min_version) | |
| 82 continue; | |
| 83 | |
| 84 assert(sizeof(struct MojomStructHeader) + entry->offset < in_struct_size); | |
| 85 void* elem_data = ((char*)inout_struct + sizeof(struct MojomStructHeader) + | |
| 86 entry->offset); | |
| 87 | |
| 88 MojomType_DispatchDecodePointersAndHandles( | |
| 89 entry->elem_type, | |
| 90 entry->elem_descriptor, | |
| 91 entry->nullable, | |
| 92 elem_data, | |
| 93 in_struct_size - ((char*)elem_data - (char*)inout_struct), | |
| 94 inout_handles, | |
| 95 in_num_handles); | |
| 96 } | |
| 97 } | |
| 98 | |
| 99 static bool is_valid_size_for_version( | |
| 100 const struct MojomStructHeader* in_struct, | |
| 101 const struct MojomTypeDescriptorStructVersion versions[], | |
| 102 uint32_t num_versions) { | |
| 103 // Scan for a version size in reverse order (assuming structs are often newer | |
| 104 // versions than old). Seek to the most recent version that |in_struct| is | |
| 105 // compatible with. | |
| 106 uint32_t i = num_versions - 1; | |
| 107 for (; i > 0 && versions[i].version > in_struct->version; i--); | |
| 108 | |
| 109 if (in_struct->version == versions[i].version) { | |
| 110 return in_struct->num_bytes == versions[i].num_bytes; | |
| 111 } else { | |
| 112 return in_struct->num_bytes >= versions[i].num_bytes; | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 MojomValidationResult MojomStruct_Validate( | |
| 117 const struct MojomTypeDescriptorStruct* in_type_desc, | |
| 118 const struct MojomStructHeader* in_struct, | |
| 119 uint32_t in_struct_size, | |
| 120 uint32_t in_num_handles, | |
| 121 struct MojomValidationContext* inout_context) { | |
| 122 assert(in_type_desc); | |
| 123 assert(in_struct); | |
| 124 | |
| 125 // Struct header validation. | |
| 126 if (in_struct_size < sizeof(struct MojomStructHeader)) | |
| 127 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
| 128 | |
| 129 if (in_struct->num_bytes > in_struct_size) | |
| 130 return MOJOM_VALIDATION_ILLEGAL_MEMORY_RANGE; | |
| 131 | |
| 132 if (!is_valid_size_for_version(in_struct, in_type_desc->versions, | |
| 133 in_type_desc->num_versions)) { | |
| 134 return MOJOM_VALIDATION_UNEXPECTED_STRUCT_HEADER; | |
| 135 } | |
| 136 | |
| 137 if ((in_struct->num_bytes & 7) != 0) | |
| 138 return MOJOM_VALIDATION_MISALIGNED_OBJECT; | |
| 139 | |
| 140 // From here on out, all pointers need to point past the end of this struct. | |
| 141 inout_context->next_pointer = (char*)in_struct + in_struct->num_bytes; | |
| 142 | |
| 143 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
| 144 const struct MojomTypeDescriptorStructEntry* entry = | |
| 145 &(in_type_desc->entries[i]); | |
| 146 | |
| 147 if (in_struct->version < entry->min_version) | |
| 148 continue; | |
| 149 | |
| 150 void* elem_data = ((char*)in_struct + sizeof(struct MojomStructHeader) + | |
| 151 entry->offset); | |
| 152 MojomValidationResult result = MojomType_DispatchValidate( | |
| 153 entry->elem_type, | |
| 154 entry->elem_descriptor, | |
| 155 entry->nullable, | |
| 156 elem_data, | |
| 157 in_struct_size - ((char*)elem_data - (char*)in_struct), | |
| 158 in_num_handles, | |
| 159 inout_context); | |
| 160 if (result != MOJOM_VALIDATION_ERROR_NONE) | |
| 161 return result; | |
| 162 } | |
| 163 | |
| 164 return MOJOM_VALIDATION_ERROR_NONE; | |
| 165 } | |
| 166 | |
| 167 bool MojomStruct_DeepCopy( | |
| 168 struct MojomBuffer* buffer, | |
| 169 const struct MojomTypeDescriptorStruct* in_type_desc, | |
| 170 const struct MojomStructHeader* in_struct, | |
| 171 struct MojomStructHeader** out_struct) { | |
| 172 assert(in_type_desc); | |
| 173 assert(in_struct); | |
| 174 assert(out_struct); | |
| 175 | |
| 176 *out_struct = MojomBuffer_Allocate(buffer, in_struct->num_bytes); | |
| 177 if (*out_struct == NULL) | |
| 178 return false; | |
| 179 | |
| 180 memcpy(*out_struct, in_struct, in_struct->num_bytes); | |
| 181 | |
| 182 for (size_t i = 0; i < in_type_desc->num_entries; i++) { | |
| 183 const struct MojomTypeDescriptorStructEntry* entry = | |
| 184 &(in_type_desc->entries[i]); | |
| 185 | |
| 186 if (in_struct->version < entry->min_version) | |
| 187 continue; | |
| 188 | |
| 189 void* in_elem_data = | |
| 190 ((char*)in_struct + sizeof(struct MojomStructHeader) + entry->offset); | |
| 191 void* out_elem_data = ((char*)*out_struct + | |
| 192 sizeof(struct MojomStructHeader) + entry->offset); | |
| 193 if (!MojomType_DispatchDeepCopy( | |
| 194 buffer, | |
| 195 entry->elem_type, | |
| 196 entry->elem_descriptor, | |
| 197 in_elem_data, | |
| 198 out_elem_data)) { | |
| 199 return false; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 return true; | |
| 204 } | |
| OLD | NEW |