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