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 |